From 563dc35aa06e96134d10382b982f9bc6acdc2caa Mon Sep 17 00:00:00 2001 From: Milan Andric Date: Wed, 4 Jan 2012 17:50:22 -0600 Subject: [PATCH 1/3] minor package resolution fixes. --- lib/shows.js | 9 +++++---- lib/views.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/shows.js b/lib/shows.js index a40e507..e84abcb 100644 --- a/lib/shows.js +++ b/lib/shows.js @@ -3,6 +3,7 @@ var utils = require('./utils'), duality_utils = require('duality/utils'), + couchtypes_utils = require('couchtypes/utils'), db = require('db'), core = require('duality/core'), loader = require('./loader'), @@ -143,7 +144,7 @@ exports.fieldPairs = function (fields_module, fields, doc, path) { for (var k in fields) { if (fields.hasOwnProperty(k)) { if (fields[k] instanceof fields_module.Field) { - val = duality_utils.getPropertyPath(doc, path.concat([k])); + val = couchtypes_utils.getPropertyPath(doc, path.concat([k])); if (!fields[k].isEmpty(val) || !fields[k].omit_empty) { pairs.push({ field: path.concat([k]).join('.'), @@ -152,7 +153,7 @@ exports.fieldPairs = function (fields_module, fields, doc, path) { } } else if (fields[k] instanceof fields_module.Embedded) { - val = duality_utils.getPropertyPath(doc, path.concat([k])); + val = couchtypes_utils.getPropertyPath(doc, path.concat([k])); type = fields[k].type; display_name = val ? val._id: ''; if (type.display_name) { @@ -164,10 +165,10 @@ exports.fieldPairs = function (fields_module, fields, doc, path) { }); } else if (fields[k] instanceof fields_module.EmbeddedList) { - var items = duality_utils.getPropertyPath(doc, path.concat([k])); + var items = couchtypes_utils.getPropertyPath(doc, path.concat([k])); if (items) { for (var i = 0; i < items.length; i++) { - val = duality_utils.getPropertyPath(doc, path.concat([k, i])); + val = couchtypes_utils.getPropertyPath(doc, path.concat([k, i])); type = fields[k].type; display_name = val ? val._id: ''; if (type.display_name) { diff --git a/lib/views.js b/lib/views.js index 0c43a8c..ae2efa8 100644 --- a/lib/views.js +++ b/lib/views.js @@ -4,7 +4,7 @@ exports.apps = { map: function (doc) { var id = doc._id; - if (doc.format === 'kanso') { + if (doc.couchtypes) { if (id !== '_design/admin' && id.substr(0, 8) === '_design/') { var name = id.substr(8); var cap = name.substr(0, 1).toUpperCase() + name.substr(1); From 018c791d1c3b460b3cfde2761871c18b13f2ffeb Mon Sep 17 00:00:00 2001 From: Milan Andric Date: Sun, 8 Jan 2012 14:33:56 -0600 Subject: [PATCH 2/3] upgraded packages to kanso 0.1.2 --- packages/attachments/build/add.js | 2 +- packages/attachments/build/cleanup.js | 2 +- packages/attachments/kanso.json | 2 +- .../attachments/node_modules/async/LICENSE | 19 + .../attachments/node_modules/async/Makefile | 21 + .../attachments/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ .../attachments/node_modules/async/index.js | 3 + .../node_modules/async/lib/async.js | 690 ++++++ .../node_modules/async/nodelint.cfg | 4 + .../node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../node_modules/async/test/test.html | 24 + .../node_modules/kanso-utils/attachments.js | 116 + .../node_modules/kanso-utils/index.js | 5 + .../node_modules/kanso-utils/modules.js | 289 +++ .../kanso-utils/node_modules/async/LICENSE | 19 + .../kanso-utils/node_modules/async/Makefile | 21 + .../kanso-utils/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ .../kanso-utils/node_modules/async/index.js | 3 + .../node_modules/async/lib/async.js | 690 ++++++ .../node_modules/async/nodelint.cfg | 4 + .../node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../node_modules/async/test/test.html | 24 + .../kanso-utils/node_modules/mime/LICENSE | 19 + .../kanso-utils/node_modules/mime/README.md | 50 + .../kanso-utils/node_modules/mime/mime.js | 92 + .../node_modules/mime/package.json | 22 + .../kanso-utils/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../node_modules/kanso-utils/package.json | 17 + .../node_modules/kanso-utils/utils.js | 512 +++++ packages/duality/build/app.js | 4 +- packages/duality/build/apputils.js | 2 +- packages/duality/duality/core.js | 18 +- packages/duality/kanso.json | 2 +- .../node_modules/kanso-utils/attachments.js | 116 + .../duality/node_modules/kanso-utils/index.js | 5 + .../node_modules/kanso-utils/modules.js | 289 +++ .../kanso-utils/node_modules/async/LICENSE | 19 + .../kanso-utils/node_modules/async/Makefile | 21 + .../kanso-utils/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ .../kanso-utils/node_modules/async/index.js | 3 + .../node_modules/async/lib/async.js | 690 ++++++ .../node_modules/async/nodelint.cfg | 4 + .../node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../node_modules/async/test/test.html | 24 + .../kanso-utils/node_modules/mime/LICENSE | 19 + .../kanso-utils/node_modules/mime/README.md | 50 + .../kanso-utils/node_modules/mime/mime.js | 92 + .../node_modules/mime/package.json | 22 + .../kanso-utils/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../node_modules/kanso-utils/package.json | 17 + .../duality/node_modules/kanso-utils/utils.js | 512 +++++ .../node_modules/underscore/.npmignore | 3 + .../duality/node_modules/underscore/LICENSE | 22 + .../duality/node_modules/underscore/README | 19 + .../node_modules/underscore/index.html | 1777 +++++++++++++++ .../duality/node_modules/underscore/index.js | 1 + .../node_modules/underscore/package.json | 12 + .../node_modules/underscore/underscore-min.js | 30 + .../node_modules/underscore/underscore.js | 981 ++++++++ packages/dust/build/utils.js | 6 +- packages/dust/node_modules/async/LICENSE | 19 + packages/dust/node_modules/async/Makefile | 21 + packages/dust/node_modules/async/README.md | 1009 +++++++++ .../dust/node_modules/async/deps/nodeunit.css | 70 + .../dust/node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ packages/dust/node_modules/async/index.js | 3 + packages/dust/node_modules/async/lib/async.js | 690 ++++++ packages/dust/node_modules/async/nodelint.cfg | 4 + packages/dust/node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../dust/node_modules/async/test/test.html | 24 + .../{dustjs => node_modules/dust}/LICENSE | 0 .../{dustjs => node_modules/dust}/Makefile | 0 .../{dustjs => node_modules/dust}/README.md | 0 .../dust/{dustjs => node_modules/dust}/TODO | 0 .../dust}/benchmark/index.html | 0 .../dust}/benchmark/server.js | 0 .../dust}/benchmark/suites/dust_suite.js | 0 .../benchmark/suites/handlebars_suite.js | 0 .../dust}/benchmark/suites/jquery_suite.js | 0 .../dust}/benchmark/suites/mustache_suite.js | 0 .../dust}/benchmark/uubench.js | 0 .../dust}/docs/about.md | 0 .../{dustjs => node_modules/dust}/docs/api.md | 0 .../dust}/docs/build.js | 0 .../dust}/docs/index.css | 0 .../dust}/docs/index.dust.html | 0 .../dust}/docs/index.js | 0 .../dust}/docs/select.dust.html | 0 .../dust}/docs/syntax.md | 0 .../{dustjs => node_modules/dust}/index.html | 0 .../dust}/lib/compiler.js | 0 .../{dustjs => node_modules/dust}/lib/dust.js | 0 .../dust}/lib/parser.js | 0 .../dust}/lib/server.js | 0 .../dust}/package.json | 0 .../dust}/src/build.js | 0 .../dust}/src/dust.pegjs | 0 .../dust}/test/core.js | 0 .../dust}/test/examples.js | 0 .../dust}/test/server.js | 0 .../dust}/test/uutest.js | 0 .../dust}/vendor/beautify.js | 0 .../dust}/vendor/ecma.js | 0 .../dust}/vendor/hijs.js | 0 .../dust}/vendor/jquery.min.js | 0 .../dust}/vendor/jsdump.js | 0 .../dust}/vendor/showdown.js | 0 .../node_modules/kanso-utils/attachments.js | 116 + .../dust/node_modules/kanso-utils/index.js | 5 + .../dust/node_modules/kanso-utils/modules.js | 289 +++ .../kanso-utils/node_modules/mime/LICENSE | 19 + .../kanso-utils/node_modules/mime/README.md | 50 + .../kanso-utils/node_modules/mime/mime.js | 92 + .../node_modules/mime/package.json | 22 + .../kanso-utils/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../node_modules/kanso-utils/package.json | 17 + .../dust/node_modules/kanso-utils/utils.js | 512 +++++ .../dust/node_modules/underscore/.npmignore | 3 + packages/dust/node_modules/underscore/LICENSE | 22 + packages/dust/node_modules/underscore/README | 19 + .../dust/node_modules/underscore/index.html | 1777 +++++++++++++++ .../dust/node_modules/underscore/index.js | 1 + .../dust/node_modules/underscore/package.json | 12 + .../node_modules/underscore/underscore-min.js | 30 + .../node_modules/underscore/underscore.js | 981 ++++++++ packages/modules/build/add.js | 4 +- packages/modules/build/attachment.js | 25 +- packages/modules/kanso.json | 2 +- packages/modules/node_modules/.bin/uglifyjs | 323 +++ packages/modules/node_modules/async/LICENSE | 19 + packages/modules/node_modules/async/Makefile | 21 + packages/modules/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ packages/modules/node_modules/async/index.js | 3 + .../modules/node_modules/async/lib/async.js | 690 ++++++ .../modules/node_modules/async/nodelint.cfg | 4 + .../modules/node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../modules/node_modules/async/test/test.html | 24 + .../node_modules/kanso-utils/attachments.js | 116 + .../modules/node_modules/kanso-utils/index.js | 5 + .../node_modules/kanso-utils/modules.js | 289 +++ .../node_modules/kanso-utils/package.json | 17 + .../modules/node_modules/kanso-utils/utils.js | 512 +++++ packages/modules/node_modules/mime/LICENSE | 19 + packages/modules/node_modules/mime/README.md | 50 + packages/modules/node_modules/mime/mime.js | 92 + .../modules/node_modules/mime/package.json | 22 + packages/modules/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../modules/node_modules/uglify-js/.npmignore | 4 + .../node_modules/uglify-js/README.html | 981 ++++++++ .../modules/node_modules/uglify-js/README.org | 574 +++++ .../node_modules/uglify-js/bin/uglifyjs | 323 +++ .../node_modules/uglify-js/docstyle.css | 75 + .../node_modules/uglify-js/lib/object-ast.js | 75 + .../node_modules/uglify-js/lib/parse-js.js | 1339 +++++++++++ .../node_modules/uglify-js/lib/process.js | 2002 +++++++++++++++++ .../uglify-js/lib/squeeze-more.js | 69 + .../node_modules/uglify-js/package.json | 24 + .../node_modules/uglify-js/test/beautify.js | 28 + .../node_modules/uglify-js/test/testparser.js | 403 ++++ .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + .../uglify-js/test/unit/scripts.js | 55 + .../modules/node_modules/uglify-js/tmp/269.js | 13 + .../uglify-js/tmp/embed-tokens.js | 15 + .../node_modules/uglify-js/tmp/goto.js | 26 + .../node_modules/uglify-js/tmp/goto2.js | 8 + .../node_modules/uglify-js/tmp/hoist.js | 33 + .../node_modules/uglify-js/tmp/instrument.js | 97 + .../node_modules/uglify-js/tmp/instrument2.js | 138 ++ .../node_modules/uglify-js/tmp/test.js | 30 + .../node_modules/uglify-js/uglify-js.js | 17 + packages/properties/build/load.js | 9 +- packages/properties/kanso.json | 2 +- .../node_modules/kanso-utils/attachments.js | 116 + .../node_modules/kanso-utils/index.js | 5 + .../node_modules/kanso-utils/modules.js | 289 +++ .../kanso-utils/node_modules/async/LICENSE | 19 + .../kanso-utils/node_modules/async/Makefile | 21 + .../kanso-utils/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ .../kanso-utils/node_modules/async/index.js | 3 + .../node_modules/async/lib/async.js | 690 ++++++ .../node_modules/async/nodelint.cfg | 4 + .../node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../node_modules/async/test/test.html | 24 + .../kanso-utils/node_modules/mime/LICENSE | 19 + .../kanso-utils/node_modules/mime/README.md | 50 + .../kanso-utils/node_modules/mime/mime.js | 92 + .../node_modules/mime/package.json | 22 + .../kanso-utils/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../node_modules/kanso-utils/package.json | 17 + .../node_modules/kanso-utils/utils.js | 512 +++++ .../node_modules/underscore/.npmignore | 3 + .../node_modules/underscore/LICENSE | 22 + .../properties/node_modules/underscore/README | 19 + .../node_modules/underscore/index.html | 1777 +++++++++++++++ .../node_modules/underscore/index.js | 1 + .../node_modules/underscore/package.json | 12 + .../node_modules/underscore/underscore-min.js | 30 + .../node_modules/underscore/underscore.js | 981 ++++++++ packages/settings/build/add.js | 35 +- packages/settings/build/add_root.js | 13 + packages/settings/build/utils.js | 40 + packages/settings/kanso.json | 5 +- .../node_modules/kanso-utils/attachments.js | 116 + .../node_modules/kanso-utils/index.js | 5 + .../node_modules/kanso-utils/modules.js | 289 +++ .../kanso-utils/node_modules/async/LICENSE | 19 + .../kanso-utils/node_modules/async/Makefile | 21 + .../kanso-utils/node_modules/async/README.md | 1009 +++++++++ .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 ++++++++++++++++ .../kanso-utils/node_modules/async/index.js | 3 + .../node_modules/async/lib/async.js | 690 ++++++ .../node_modules/async/nodelint.cfg | 4 + .../node_modules/async/package.json | 16 + .../node_modules/async/test/test-async.js | 1577 +++++++++++++ .../node_modules/async/test/test.html | 24 + .../kanso-utils/node_modules/mime/LICENSE | 19 + .../kanso-utils/node_modules/mime/README.md | 50 + .../kanso-utils/node_modules/mime/mime.js | 92 + .../node_modules/mime/package.json | 22 + .../kanso-utils/node_modules/mime/test.js | 79 + .../node_modules/mime/types/mime.types | 1479 ++++++++++++ .../node_modules/mime/types/node.types | 43 + .../node_modules/kanso-utils/package.json | 17 + .../node_modules/kanso-utils/utils.js | 512 +++++ 330 files changed, 69653 insertions(+), 66 deletions(-) create mode 100644 packages/attachments/node_modules/async/LICENSE create mode 100644 packages/attachments/node_modules/async/Makefile create mode 100644 packages/attachments/node_modules/async/README.md create mode 100644 packages/attachments/node_modules/async/deps/nodeunit.css create mode 100644 packages/attachments/node_modules/async/deps/nodeunit.js create mode 100644 packages/attachments/node_modules/async/index.js create mode 100644 packages/attachments/node_modules/async/lib/async.js create mode 100644 packages/attachments/node_modules/async/nodelint.cfg create mode 100644 packages/attachments/node_modules/async/package.json create mode 100644 packages/attachments/node_modules/async/test/test-async.js create mode 100644 packages/attachments/node_modules/async/test/test.html create mode 100644 packages/attachments/node_modules/kanso-utils/attachments.js create mode 100644 packages/attachments/node_modules/kanso-utils/index.js create mode 100644 packages/attachments/node_modules/kanso-utils/modules.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/LICENSE create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/Makefile create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/README.md create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/index.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/lib/async.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/nodelint.cfg create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/package.json create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/test/test-async.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/async/test/test.html create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/LICENSE create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/README.md create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/mime.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/package.json create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/test.js create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/types/mime.types create mode 100644 packages/attachments/node_modules/kanso-utils/node_modules/mime/types/node.types create mode 100644 packages/attachments/node_modules/kanso-utils/package.json create mode 100644 packages/attachments/node_modules/kanso-utils/utils.js create mode 100644 packages/duality/node_modules/kanso-utils/attachments.js create mode 100644 packages/duality/node_modules/kanso-utils/index.js create mode 100644 packages/duality/node_modules/kanso-utils/modules.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/LICENSE create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/Makefile create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/README.md create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/index.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/lib/async.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/nodelint.cfg create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/package.json create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/test/test-async.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/async/test/test.html create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/LICENSE create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/README.md create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/mime.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/package.json create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/test.js create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/types/mime.types create mode 100644 packages/duality/node_modules/kanso-utils/node_modules/mime/types/node.types create mode 100644 packages/duality/node_modules/kanso-utils/package.json create mode 100644 packages/duality/node_modules/kanso-utils/utils.js create mode 100644 packages/duality/node_modules/underscore/.npmignore create mode 100644 packages/duality/node_modules/underscore/LICENSE create mode 100644 packages/duality/node_modules/underscore/README create mode 100644 packages/duality/node_modules/underscore/index.html create mode 100644 packages/duality/node_modules/underscore/index.js create mode 100644 packages/duality/node_modules/underscore/package.json create mode 100644 packages/duality/node_modules/underscore/underscore-min.js create mode 100644 packages/duality/node_modules/underscore/underscore.js create mode 100644 packages/dust/node_modules/async/LICENSE create mode 100644 packages/dust/node_modules/async/Makefile create mode 100644 packages/dust/node_modules/async/README.md create mode 100644 packages/dust/node_modules/async/deps/nodeunit.css create mode 100644 packages/dust/node_modules/async/deps/nodeunit.js create mode 100644 packages/dust/node_modules/async/index.js create mode 100644 packages/dust/node_modules/async/lib/async.js create mode 100644 packages/dust/node_modules/async/nodelint.cfg create mode 100644 packages/dust/node_modules/async/package.json create mode 100644 packages/dust/node_modules/async/test/test-async.js create mode 100644 packages/dust/node_modules/async/test/test.html rename packages/dust/{dustjs => node_modules/dust}/LICENSE (100%) rename packages/dust/{dustjs => node_modules/dust}/Makefile (100%) rename packages/dust/{dustjs => node_modules/dust}/README.md (100%) rename packages/dust/{dustjs => node_modules/dust}/TODO (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/index.html (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/server.js (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/suites/dust_suite.js (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/suites/handlebars_suite.js (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/suites/jquery_suite.js (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/suites/mustache_suite.js (100%) rename packages/dust/{dustjs => node_modules/dust}/benchmark/uubench.js (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/about.md (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/api.md (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/build.js (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/index.css (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/index.dust.html (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/index.js (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/select.dust.html (100%) rename packages/dust/{dustjs => node_modules/dust}/docs/syntax.md (100%) rename packages/dust/{dustjs => node_modules/dust}/index.html (100%) rename packages/dust/{dustjs => node_modules/dust}/lib/compiler.js (100%) rename packages/dust/{dustjs => node_modules/dust}/lib/dust.js (100%) rename packages/dust/{dustjs => node_modules/dust}/lib/parser.js (100%) rename packages/dust/{dustjs => node_modules/dust}/lib/server.js (100%) rename packages/dust/{dustjs => node_modules/dust}/package.json (100%) rename packages/dust/{dustjs => node_modules/dust}/src/build.js (100%) rename packages/dust/{dustjs => node_modules/dust}/src/dust.pegjs (100%) rename packages/dust/{dustjs => node_modules/dust}/test/core.js (100%) rename packages/dust/{dustjs => node_modules/dust}/test/examples.js (100%) rename packages/dust/{dustjs => node_modules/dust}/test/server.js (100%) rename packages/dust/{dustjs => node_modules/dust}/test/uutest.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/beautify.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/ecma.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/hijs.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/jquery.min.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/jsdump.js (100%) rename packages/dust/{dustjs => node_modules/dust}/vendor/showdown.js (100%) create mode 100644 packages/dust/node_modules/kanso-utils/attachments.js create mode 100644 packages/dust/node_modules/kanso-utils/index.js create mode 100644 packages/dust/node_modules/kanso-utils/modules.js create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/LICENSE create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/README.md create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/mime.js create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/package.json create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/test.js create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/types/mime.types create mode 100644 packages/dust/node_modules/kanso-utils/node_modules/mime/types/node.types create mode 100644 packages/dust/node_modules/kanso-utils/package.json create mode 100644 packages/dust/node_modules/kanso-utils/utils.js create mode 100644 packages/dust/node_modules/underscore/.npmignore create mode 100644 packages/dust/node_modules/underscore/LICENSE create mode 100644 packages/dust/node_modules/underscore/README create mode 100644 packages/dust/node_modules/underscore/index.html create mode 100644 packages/dust/node_modules/underscore/index.js create mode 100644 packages/dust/node_modules/underscore/package.json create mode 100644 packages/dust/node_modules/underscore/underscore-min.js create mode 100644 packages/dust/node_modules/underscore/underscore.js create mode 100755 packages/modules/node_modules/.bin/uglifyjs create mode 100644 packages/modules/node_modules/async/LICENSE create mode 100644 packages/modules/node_modules/async/Makefile create mode 100644 packages/modules/node_modules/async/README.md create mode 100644 packages/modules/node_modules/async/deps/nodeunit.css create mode 100644 packages/modules/node_modules/async/deps/nodeunit.js create mode 100644 packages/modules/node_modules/async/index.js create mode 100644 packages/modules/node_modules/async/lib/async.js create mode 100644 packages/modules/node_modules/async/nodelint.cfg create mode 100644 packages/modules/node_modules/async/package.json create mode 100644 packages/modules/node_modules/async/test/test-async.js create mode 100644 packages/modules/node_modules/async/test/test.html create mode 100644 packages/modules/node_modules/kanso-utils/attachments.js create mode 100644 packages/modules/node_modules/kanso-utils/index.js create mode 100644 packages/modules/node_modules/kanso-utils/modules.js create mode 100644 packages/modules/node_modules/kanso-utils/package.json create mode 100644 packages/modules/node_modules/kanso-utils/utils.js create mode 100644 packages/modules/node_modules/mime/LICENSE create mode 100644 packages/modules/node_modules/mime/README.md create mode 100644 packages/modules/node_modules/mime/mime.js create mode 100644 packages/modules/node_modules/mime/package.json create mode 100644 packages/modules/node_modules/mime/test.js create mode 100644 packages/modules/node_modules/mime/types/mime.types create mode 100644 packages/modules/node_modules/mime/types/node.types create mode 100644 packages/modules/node_modules/uglify-js/.npmignore create mode 100644 packages/modules/node_modules/uglify-js/README.html create mode 100644 packages/modules/node_modules/uglify-js/README.org create mode 100755 packages/modules/node_modules/uglify-js/bin/uglifyjs create mode 100644 packages/modules/node_modules/uglify-js/docstyle.css create mode 100644 packages/modules/node_modules/uglify-js/lib/object-ast.js create mode 100644 packages/modules/node_modules/uglify-js/lib/parse-js.js create mode 100644 packages/modules/node_modules/uglify-js/lib/process.js create mode 100644 packages/modules/node_modules/uglify-js/lib/squeeze-more.js create mode 100644 packages/modules/node_modules/uglify-js/package.json create mode 100755 packages/modules/node_modules/uglify-js/test/beautify.js create mode 100755 packages/modules/node_modules/uglify-js/test/testparser.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 packages/modules/node_modules/uglify-js/test/unit/scripts.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/269.js create mode 100755 packages/modules/node_modules/uglify-js/tmp/embed-tokens.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/goto.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/goto2.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/hoist.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/instrument.js create mode 100644 packages/modules/node_modules/uglify-js/tmp/instrument2.js create mode 100755 packages/modules/node_modules/uglify-js/tmp/test.js create mode 100644 packages/modules/node_modules/uglify-js/uglify-js.js create mode 100644 packages/properties/node_modules/kanso-utils/attachments.js create mode 100644 packages/properties/node_modules/kanso-utils/index.js create mode 100644 packages/properties/node_modules/kanso-utils/modules.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/LICENSE create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/Makefile create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/README.md create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/index.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/lib/async.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/nodelint.cfg create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/package.json create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/test/test-async.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/async/test/test.html create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/LICENSE create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/README.md create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/mime.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/package.json create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/test.js create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/types/mime.types create mode 100644 packages/properties/node_modules/kanso-utils/node_modules/mime/types/node.types create mode 100644 packages/properties/node_modules/kanso-utils/package.json create mode 100644 packages/properties/node_modules/kanso-utils/utils.js create mode 100644 packages/properties/node_modules/underscore/.npmignore create mode 100644 packages/properties/node_modules/underscore/LICENSE create mode 100644 packages/properties/node_modules/underscore/README create mode 100644 packages/properties/node_modules/underscore/index.html create mode 100644 packages/properties/node_modules/underscore/index.js create mode 100644 packages/properties/node_modules/underscore/package.json create mode 100644 packages/properties/node_modules/underscore/underscore-min.js create mode 100644 packages/properties/node_modules/underscore/underscore.js create mode 100644 packages/settings/build/add_root.js create mode 100644 packages/settings/build/utils.js create mode 100644 packages/settings/node_modules/kanso-utils/attachments.js create mode 100644 packages/settings/node_modules/kanso-utils/index.js create mode 100644 packages/settings/node_modules/kanso-utils/modules.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/LICENSE create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/Makefile create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/README.md create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/index.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/lib/async.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/nodelint.cfg create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/package.json create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/test/test-async.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/async/test/test.html create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/LICENSE create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/README.md create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/mime.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/package.json create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/test.js create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/types/mime.types create mode 100644 packages/settings/node_modules/kanso-utils/node_modules/mime/types/node.types create mode 100644 packages/settings/node_modules/kanso-utils/package.json create mode 100644 packages/settings/node_modules/kanso-utils/utils.js diff --git a/packages/attachments/build/add.js b/packages/attachments/build/add.js index 37681e4..33384fc 100644 --- a/packages/attachments/build/add.js +++ b/packages/attachments/build/add.js @@ -1,4 +1,4 @@ -var attachments = require('kanso/attachments'), +var attachments = require('kanso-utils/attachments'), async = require('async'); diff --git a/packages/attachments/build/cleanup.js b/packages/attachments/build/cleanup.js index a612b73..814e8e5 100644 --- a/packages/attachments/build/cleanup.js +++ b/packages/attachments/build/cleanup.js @@ -1,4 +1,4 @@ -var attachments = require('kanso/attachments'), +var attachments = require('kanso-utils/attachments'), async = require('async'); diff --git a/packages/attachments/kanso.json b/packages/attachments/kanso.json index aacde3f..d3ab5b4 100644 --- a/packages/attachments/kanso.json +++ b/packages/attachments/kanso.json @@ -1,6 +1,6 @@ { "name": "attachments", - "version": "0.0.8", + "version": "0.0.9", "categories": ["build-tools"], "description": "Loads files or directories of files and attaches them to a design doc", "preprocessors": { diff --git a/packages/attachments/node_modules/async/LICENSE b/packages/attachments/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/attachments/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/attachments/node_modules/async/Makefile b/packages/attachments/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/attachments/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/attachments/node_modules/async/README.md b/packages/attachments/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/attachments/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/attachments/node_modules/async/deps/nodeunit.css b/packages/attachments/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/attachments/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/attachments/node_modules/async/deps/nodeunit.js b/packages/attachments/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/attachments/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/attachments/node_modules/async/index.js b/packages/attachments/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/attachments/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/attachments/node_modules/async/lib/async.js b/packages/attachments/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/attachments/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/attachments/node_modules/async/nodelint.cfg b/packages/attachments/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/attachments/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/attachments/node_modules/async/package.json b/packages/attachments/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/attachments/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/attachments/node_modules/async/test/test-async.js b/packages/attachments/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/attachments/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/attachments/node_modules/async/test/test.html b/packages/attachments/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/attachments/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/attachments/node_modules/kanso-utils/attachments.js b/packages/attachments/node_modules/kanso-utils/attachments.js new file mode 100644 index 0000000..330cc45 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/attachments.js @@ -0,0 +1,116 @@ +/** + * Functions related to the loading and manipulation of attachments in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + mime = require('mime'), + async = require('async'), + fs = require('fs'); + + +/** + * + * @param {Object} doc + * @param {String} path + * @param {Buffer} content + * @returns {Object} + */ + +exports.add = function (doc, ddoc_path, original_path, content) { + if (!doc._attachments) { + doc._attachments = {}; + } + doc._attachments[ddoc_path] = { + 'content_type': mime.lookup(original_path), + 'data': content.toString('base64'), + // custom addition removed in cleanup postprocessor + '_original_path': original_path + }; + return doc; +}; + + +/** + * Searchs a path for attachments, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a file or directory + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads an attachment file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + exports.add(doc, rel, p, content); + callback() + }); +}; + + +/** + * Find all attachments below or at a given path, recursing through + * subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for attachments. This function omits + * hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + return true; + }; +}; diff --git a/packages/attachments/node_modules/kanso-utils/index.js b/packages/attachments/node_modules/kanso-utils/index.js new file mode 100644 index 0000000..0b79a79 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/index.js @@ -0,0 +1,5 @@ +module.exports = { + attachments: require('./attachments'), + modules: require('./modules'), + utils: require('./utils') +}; diff --git a/packages/attachments/node_modules/kanso-utils/modules.js b/packages/attachments/node_modules/kanso-utils/modules.js new file mode 100644 index 0000000..4324d02 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/modules.js @@ -0,0 +1,289 @@ +/** + * Functions related to the loading and manipulation of CommonJS Modules in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + async = require('async'), + path = require('path'), + fs = require('fs'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +// As modules are added, their original file paths are added to this object +// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...} +exports.originalPaths = {}; + + +/** + * Add the module source to the document in the correct location for requiring + * server-side, then add the path to the _modules property for use by the + * modules plugin postprocessor (when creating the kanso.js attachment) + * + * Returns the updated document. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.add = function (doc, path, src) { + var curr = utils.getPropertyPath(doc, path, true); + if (curr !== undefined) { + var paths = utils.getPropertyPaths(path, curr); + throw new Error( + 'Adding ' + path + ' would overwrite:\n' + + ' ' + paths.join('\n ') + '\n' + + '\n' + + 'This error often occurs because there is a module with the\n' + + 'same name as a directory containing modules. There is no way\n' + + 'to map this structure in the design doc.\n' + ); + } + utils.setPropertyPath(doc, path, src); + if (!doc._modules) { + doc._modules = {}; + } + doc._modules[path] = null; + return doc; +}; + + +/** + * Wraps module source code with useful comments and module cache boilerplate + * code. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.wrap = function (path, src) { + return '/********** ' + path + ' **********/\n\n' + + 'kanso.moduleCache["' + path.replace('"', '\\"') + '"] = ' + + '{load: (function (module, exports, require) {\n\n' + src + '\n\n})};' + + '\n\n'; +}; + + +/** + * Searchs a path for commonjs modules, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a module file or directory of modules + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads a module file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + var module_path = rel.replace(/\.js$/, ''); + var src = content.toString(); + exports.add(doc, module_path, src); + utils.setPropertyPath(exports.originalPaths, rel, p); + callback() + }); +}; + + +/** + * Find all modules below or at a given path, recursing through subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for module files. This function tests + * for a .js extension and omits hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + // should have a .js extension + if (!/\.js$/.test(f)) { + return false; + } + return true; + }; +}; + + +/** + * Parses the exports.originalPaths object to return an array of filenames + */ + +exports.getFilenames = function (obj) { + var names = []; + for (var k in obj) { + if (typeof obj[k] === 'object') { + names.concat(exports.getFilenames(obj[k]).map(function (n) { + return k + '/' + n; + })); + } + else { + names.push(k); + } + } + return names; +}; + + +/** + * Loads a commonjs module from the loaded design document, returning + * the exported properties. The current_dir and target parameters are not the + * path of the module on the filesystem, but rather the path of the module + * within couchdb, root ('/') being the design doc itself. + * + * @param {Object} module_cache + * @param {Object} doc + * @param {String} current_dir + * @param {String} target + * @param {Object} context - optional, extends sandbox object + */ + +exports.require = function (module_cache, doc, current, target, context) { + var current_dir = path.dirname(current); + if (target.charAt(0) !== '.') { + current_dir = '/'; + } + var p = path.normalize(path.join(current_dir, target)); + if (module_cache[p]) { + return module_cache[p]; + } + + var nodes = p.split('/').slice(1); + var content = nodes.reduce(function (a, x) { + if (a[x] === undefined) { + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ') - ' + + 'Module not found' + ); + } + a = a[x]; + return a; + }, doc); + + var filename = utils.getPropertyPath( + exports.originalPaths, p.substr(1), true + ); + + // if you attempt to require + if (typeof filename === 'object') { + var filenames = exports.getFilenames(filename); + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ')\n\n' + + 'It\'s not possible to require directories of modules in CouchDB,\n' + + 'you have to specify one of the following sub-modules directly:\n' + + filenames.map(function (f) { + return ' ' + p.replace(/^\//, '') + '/' + f; + }).join('\n') + '\n' + ); + } + + var module = { + id: p.substr(1), + exports: {}, + // TODO: this property is not provided by couchdb, but is by node: + //filename: filename, + // TODO: this property is not provided by couchdb, but is by node: + //require: async.apply(exports.require, module_cache, doc, p) + // TODO: module properties provided by couchdb, but not by kanso + // * current + // * parent + }; + var sandbox = { + module: module, + exports: module.exports, + //require: module.require, + require: async.apply(exports.require, module_cache, doc, p), + log: function () { + console.log.apply(console, arguments); + } + }; + + // copy context into sandbox + if (context) { + Object.keys(context).forEach(function (k) { + sandbox[k] = context[k]; + }); + } + + // Create a placeholder for this module's exports so circular requires + // are possible. TODO: node.js uses a loaded = false attribute on the + // cached module object to mark this as a placeholder. + module_cache[p] = {}; + + try { + var s = new Script(content, filename).runInNewContext(sandbox); + } + catch (e) { + if (e instanceof SyntaxError && filename) { + // gives a better syntax error than runInNewContext + // with filename and line number + require(filename); + } + if (!e.got_filename) { + e.message = 'Error loading: ' + filename + '\n' + e.message; + e.got_filename = true; + } + throw e; + } + module_cache[p] = sandbox.module.exports; + return module_cache[p]; +}; diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/LICENSE b/packages/attachments/node_modules/kanso-utils/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/attachments/node_modules/kanso-utils/node_modules/async/Makefile b/packages/attachments/node_modules/kanso-utils/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/README.md b/packages/attachments/node_modules/kanso-utils/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + +
+### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css b/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js b/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/index.js b/packages/attachments/node_modules/kanso-utils/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/lib/async.js b/packages/attachments/node_modules/kanso-utils/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/nodelint.cfg b/packages/attachments/node_modules/kanso-utils/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/package.json b/packages/attachments/node_modules/kanso-utils/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test-async.js b/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test.html b/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/LICENSE b/packages/attachments/node_modules/kanso-utils/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/attachments/node_modules/kanso-utils/node_modules/mime/README.md b/packages/attachments/node_modules/kanso-utils/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/mime.js b/packages/attachments/node_modules/kanso-utils/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/package.json b/packages/attachments/node_modules/kanso-utils/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/test.js b/packages/attachments/node_modules/kanso-utils/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/mime.types b/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/node.types b/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/attachments/node_modules/kanso-utils/package.json b/packages/attachments/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/attachments/node_modules/kanso-utils/utils.js b/packages/attachments/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/attachments/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; diff --git a/packages/duality/build/app.js b/packages/duality/build/app.js index 5411ec9..7740d90 100644 --- a/packages/duality/build/app.js +++ b/packages/duality/build/app.js @@ -1,6 +1,6 @@ var apputils = require('./apputils'), - modules = require('kanso/modules'), - _ = require('underscore/underscore')._; + modules = require('kanso-utils/modules'), + _ = require('underscore')._; /** * Loads module directories specified in kanso.json and adds the modules diff --git a/packages/duality/build/apputils.js b/packages/duality/build/apputils.js index efc8f5c..e512104 100644 --- a/packages/duality/build/apputils.js +++ b/packages/duality/build/apputils.js @@ -1,4 +1,4 @@ -var utils = require('kanso/utils'); +var utils = require('kanso-utils/utils'); exports.proxyShowFn = function (path, app, doc, props) { diff --git a/packages/duality/duality/core.js b/packages/duality/duality/core.js index 7fa80f8..4e4baab 100644 --- a/packages/duality/duality/core.js +++ b/packages/duality/duality/core.js @@ -175,17 +175,17 @@ function loadDeps(deps) { } } } -if (settings.load) { - // load root app - var tmp = {}; - tmp[settings.name] = null; - loadDeps(tmp); - // load dependencies of root app - loadDeps(settings.dependencies); - exports._rewrites = _.flatten(exports._rewrites); -} +// load root app +var tmp = {}; +tmp[settings.name] = null; +loadDeps(tmp); + +// load dependencies of root app +loadDeps(settings.dependencies); + +exports._rewrites = _.flatten(exports._rewrites); /** diff --git a/packages/duality/kanso.json b/packages/duality/kanso.json index 0f8484b..830e983 100644 --- a/packages/duality/kanso.json +++ b/packages/duality/kanso.json @@ -1,6 +1,6 @@ { "name": "duality", - "version": "0.0.13", + "version": "0.0.15", "categories": ["frameworks", "duality"], "description": "The central part of the Duality framework. Implements the CouchDB design doc API in the browser and handles the dispatching of URLs", "modules": "duality", diff --git a/packages/duality/node_modules/kanso-utils/attachments.js b/packages/duality/node_modules/kanso-utils/attachments.js new file mode 100644 index 0000000..330cc45 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/attachments.js @@ -0,0 +1,116 @@ +/** + * Functions related to the loading and manipulation of attachments in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + mime = require('mime'), + async = require('async'), + fs = require('fs'); + + +/** + * + * @param {Object} doc + * @param {String} path + * @param {Buffer} content + * @returns {Object} + */ + +exports.add = function (doc, ddoc_path, original_path, content) { + if (!doc._attachments) { + doc._attachments = {}; + } + doc._attachments[ddoc_path] = { + 'content_type': mime.lookup(original_path), + 'data': content.toString('base64'), + // custom addition removed in cleanup postprocessor + '_original_path': original_path + }; + return doc; +}; + + +/** + * Searchs a path for attachments, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a file or directory + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads an attachment file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + exports.add(doc, rel, p, content); + callback() + }); +}; + + +/** + * Find all attachments below or at a given path, recursing through + * subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for attachments. This function omits + * hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + return true; + }; +}; diff --git a/packages/duality/node_modules/kanso-utils/index.js b/packages/duality/node_modules/kanso-utils/index.js new file mode 100644 index 0000000..0b79a79 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/index.js @@ -0,0 +1,5 @@ +module.exports = { + attachments: require('./attachments'), + modules: require('./modules'), + utils: require('./utils') +}; diff --git a/packages/duality/node_modules/kanso-utils/modules.js b/packages/duality/node_modules/kanso-utils/modules.js new file mode 100644 index 0000000..4324d02 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/modules.js @@ -0,0 +1,289 @@ +/** + * Functions related to the loading and manipulation of CommonJS Modules in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + async = require('async'), + path = require('path'), + fs = require('fs'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +// As modules are added, their original file paths are added to this object +// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...} +exports.originalPaths = {}; + + +/** + * Add the module source to the document in the correct location for requiring + * server-side, then add the path to the _modules property for use by the + * modules plugin postprocessor (when creating the kanso.js attachment) + * + * Returns the updated document. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.add = function (doc, path, src) { + var curr = utils.getPropertyPath(doc, path, true); + if (curr !== undefined) { + var paths = utils.getPropertyPaths(path, curr); + throw new Error( + 'Adding ' + path + ' would overwrite:\n' + + ' ' + paths.join('\n ') + '\n' + + '\n' + + 'This error often occurs because there is a module with the\n' + + 'same name as a directory containing modules. There is no way\n' + + 'to map this structure in the design doc.\n' + ); + } + utils.setPropertyPath(doc, path, src); + if (!doc._modules) { + doc._modules = {}; + } + doc._modules[path] = null; + return doc; +}; + + +/** + * Wraps module source code with useful comments and module cache boilerplate + * code. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.wrap = function (path, src) { + return '/********** ' + path + ' **********/\n\n' + + 'kanso.moduleCache["' + path.replace('"', '\\"') + '"] = ' + + '{load: (function (module, exports, require) {\n\n' + src + '\n\n})};' + + '\n\n'; +}; + + +/** + * Searchs a path for commonjs modules, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a module file or directory of modules + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads a module file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + var module_path = rel.replace(/\.js$/, ''); + var src = content.toString(); + exports.add(doc, module_path, src); + utils.setPropertyPath(exports.originalPaths, rel, p); + callback() + }); +}; + + +/** + * Find all modules below or at a given path, recursing through subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for module files. This function tests + * for a .js extension and omits hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + // should have a .js extension + if (!/\.js$/.test(f)) { + return false; + } + return true; + }; +}; + + +/** + * Parses the exports.originalPaths object to return an array of filenames + */ + +exports.getFilenames = function (obj) { + var names = []; + for (var k in obj) { + if (typeof obj[k] === 'object') { + names.concat(exports.getFilenames(obj[k]).map(function (n) { + return k + '/' + n; + })); + } + else { + names.push(k); + } + } + return names; +}; + + +/** + * Loads a commonjs module from the loaded design document, returning + * the exported properties. The current_dir and target parameters are not the + * path of the module on the filesystem, but rather the path of the module + * within couchdb, root ('/') being the design doc itself. + * + * @param {Object} module_cache + * @param {Object} doc + * @param {String} current_dir + * @param {String} target + * @param {Object} context - optional, extends sandbox object + */ + +exports.require = function (module_cache, doc, current, target, context) { + var current_dir = path.dirname(current); + if (target.charAt(0) !== '.') { + current_dir = '/'; + } + var p = path.normalize(path.join(current_dir, target)); + if (module_cache[p]) { + return module_cache[p]; + } + + var nodes = p.split('/').slice(1); + var content = nodes.reduce(function (a, x) { + if (a[x] === undefined) { + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ') - ' + + 'Module not found' + ); + } + a = a[x]; + return a; + }, doc); + + var filename = utils.getPropertyPath( + exports.originalPaths, p.substr(1), true + ); + + // if you attempt to require + if (typeof filename === 'object') { + var filenames = exports.getFilenames(filename); + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ')\n\n' + + 'It\'s not possible to require directories of modules in CouchDB,\n' + + 'you have to specify one of the following sub-modules directly:\n' + + filenames.map(function (f) { + return ' ' + p.replace(/^\//, '') + '/' + f; + }).join('\n') + '\n' + ); + } + + var module = { + id: p.substr(1), + exports: {}, + // TODO: this property is not provided by couchdb, but is by node: + //filename: filename, + // TODO: this property is not provided by couchdb, but is by node: + //require: async.apply(exports.require, module_cache, doc, p) + // TODO: module properties provided by couchdb, but not by kanso + // * current + // * parent + }; + var sandbox = { + module: module, + exports: module.exports, + //require: module.require, + require: async.apply(exports.require, module_cache, doc, p), + log: function () { + console.log.apply(console, arguments); + } + }; + + // copy context into sandbox + if (context) { + Object.keys(context).forEach(function (k) { + sandbox[k] = context[k]; + }); + } + + // Create a placeholder for this module's exports so circular requires + // are possible. TODO: node.js uses a loaded = false attribute on the + // cached module object to mark this as a placeholder. + module_cache[p] = {}; + + try { + var s = new Script(content, filename).runInNewContext(sandbox); + } + catch (e) { + if (e instanceof SyntaxError && filename) { + // gives a better syntax error than runInNewContext + // with filename and line number + require(filename); + } + if (!e.got_filename) { + e.message = 'Error loading: ' + filename + '\n' + e.message; + e.got_filename = true; + } + throw e; + } + module_cache[p] = sandbox.module.exports; + return module_cache[p]; +}; diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/LICENSE b/packages/duality/node_modules/kanso-utils/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/duality/node_modules/kanso-utils/node_modules/async/Makefile b/packages/duality/node_modules/kanso-utils/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/README.md b/packages/duality/node_modules/kanso-utils/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + +
+### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css b/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js b/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/index.js b/packages/duality/node_modules/kanso-utils/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/lib/async.js b/packages/duality/node_modules/kanso-utils/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/nodelint.cfg b/packages/duality/node_modules/kanso-utils/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/package.json b/packages/duality/node_modules/kanso-utils/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/test/test-async.js b/packages/duality/node_modules/kanso-utils/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/duality/node_modules/kanso-utils/node_modules/async/test/test.html b/packages/duality/node_modules/kanso-utils/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/LICENSE b/packages/duality/node_modules/kanso-utils/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/duality/node_modules/kanso-utils/node_modules/mime/README.md b/packages/duality/node_modules/kanso-utils/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/mime.js b/packages/duality/node_modules/kanso-utils/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/package.json b/packages/duality/node_modules/kanso-utils/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/test.js b/packages/duality/node_modules/kanso-utils/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/types/mime.types b/packages/duality/node_modules/kanso-utils/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/duality/node_modules/kanso-utils/node_modules/mime/types/node.types b/packages/duality/node_modules/kanso-utils/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/duality/node_modules/kanso-utils/package.json b/packages/duality/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/duality/node_modules/kanso-utils/utils.js b/packages/duality/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/duality/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; diff --git a/packages/duality/node_modules/underscore/.npmignore b/packages/duality/node_modules/underscore/.npmignore new file mode 100644 index 0000000..2ce2684 --- /dev/null +++ b/packages/duality/node_modules/underscore/.npmignore @@ -0,0 +1,3 @@ +test/ +Rakefile +docs/ \ No newline at end of file diff --git a/packages/duality/node_modules/underscore/LICENSE b/packages/duality/node_modules/underscore/LICENSE new file mode 100644 index 0000000..58c73b9 --- /dev/null +++ b/packages/duality/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Jeremy Ashkenas, DocumentCloud + +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. \ No newline at end of file diff --git a/packages/duality/node_modules/underscore/README b/packages/duality/node_modules/underscore/README new file mode 100644 index 0000000..408145a --- /dev/null +++ b/packages/duality/node_modules/underscore/README @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ +/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ +\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://documentcloud.github.com/underscore/ + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/packages/duality/node_modules/underscore/index.html b/packages/duality/node_modules/underscore/index.html new file mode 100644 index 0000000..7453112 --- /dev/null +++ b/packages/duality/node_modules/underscore/index.html @@ -0,0 +1,1777 @@ + + + + + + Underscore.js + + + + +
+ +

Underscore.js

+ +

+ Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux. +

+ +

+ Underscore provides 60-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

+ +

+ A complete Test & Benchmark Suite + is included for your perusal. +

+ +

+ You may also read through the annotated source code. +

+ +

+ The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

+ +

+ Underscore is an open-source component of DocumentCloud. +

+ +

Downloads (Right-click, and use "Save As")

+ + + + + + + + + + +
Development Version (1.2.3)34kb, Uncompressed with Comments
Production Version (1.2.3)< 4kb, Minified and Gzipped
+ +

Table of Contents

+ + Object-Oriented and Functional Styles + +

+ Collections +
+ each, map, + reduce, reduceRight, + find, filter, + reject, all, + any, include, + invoke, pluck, + max, min, + sortBy, groupBy, + sortedIndex, shuffle, + toArray, size +

+ +

+ Arrays +
+ first, initial, last, rest, + compact, flatten, without, + union, intersection, difference, + uniq, zip, indexOf, + lastIndexOf, range +

+ +

+ Functions +
+ bind, bindAll, + memoize, delay, defer, + throttle, debounce, + once, after, wrap, compose +

+ +

+ Objects +
+ keys, values, + functions, extend, defaults, clone, tap, + isEqual, isEmpty, isElement, + isArray, isArguments, isFunction, isString, + isNumber, isBoolean, isDate, isRegExp, + isNaN, isNull, + isUndefined + +

+ +

+ Utility +
+ noConflict, + identity, times, + mixin, uniqueId, + escape, template +

+ +

+ Chaining +
+ chain, value +

+ +
+ +

Object-Oriented and Functional Styles

+ +

+ You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

+ +
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });
+ +

+ Using the object-oriented style allows you to chain together methods. Calling + chain on a wrapped object will cause all future method calls to + return wrapped objects as well. When you've finished the computation, + use value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

+ +
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_(lyrics).chain()
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+}, {}).value();
+
+=> {lumberjack : 2, all : 4, night : 2 ... }
+ +

+ In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

+ +

Collection Functions (Arrays or Objects)

+ +

+ each_.each(list, iterator, [context]) + Alias: forEach +
+ Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

+
+_.each([1, 2, 3], function(num){ alert(num); });
+=> alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
+=> alerts each number in turn...
+ +

+ map_.map(list, iterator, [context]) +
+ Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

+
+_.map([1, 2, 3], function(num){ return num * 3; });
+=> [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=> [3, 6, 9]
+ +

+ reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
+ Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. +

+
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=> 6
+
+ +

+ reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
+ The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

+
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=> [4, 5, 2, 3, 0, 1]
+
+ +

+ find_.find(list, iterator, [context]) + Alias: detect +
+ Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

+
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> 2
+
+ +

+ filter_.filter(list, iterator, [context]) + Alias: select +
+ Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

+
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [2, 4, 6]
+
+ +

+ reject_.reject(list, iterator, [context]) +
+ Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

+
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [1, 3, 5]
+
+ +

+ all_.all(list, iterator, [context]) + Alias: every +
+ Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

+
+_.all([true, 1, null, 'yes'], _.identity);
+=> false
+
+ +

+ any_.any(list, [iterator], [context]) + Alias: some +
+ Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

+
+_.any([null, 0, 'yes', false]);
+=> true
+
+ +

+ include_.include(list, value) + Alias: contains +
+ Returns true if the value is present in the list, using + === to test equality. Uses indexOf internally, if list + is an Array. +

+
+_.include([1, 2, 3], 3);
+=> true
+
+ +

+ invoke_.invoke(list, methodName, [*arguments]) +
+ Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

+
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=> [[1, 5, 7], [1, 2, 3]]
+
+ +

+ pluck_.pluck(list, propertyName) +
+ A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=> ["moe", "larry", "curly"]
+
+ +

+ max_.max(list, [iterator], [context]) +
+ Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=> {name : 'curly', age : 60};
+
+ +

+ min_.min(list, [iterator], [context]) +
+ Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=> 2
+
+ +

+ sortBy_.sortBy(list, iterator, [context]) +
+ Returns a sorted copy of list, ranked by the results of running + each value through iterator. +

+
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=> [5, 4, 6, 3, 1, 2]
+
+ +

+ groupBy_.groupBy(list, iterator) +
+ Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

+
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=> {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=> {3: ["one", "two"], 5: ["three"]}
+
+ +

+ sortedIndex_.sortedIndex(list, value, [iterator]) +
+ Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value. +

+
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=> 3
+
+ +

+ shuffle_.shuffle(list) +
+ Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

+
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=> [4, 1, 6, 3, 5, 2]
+
+ +

+ toArray_.toArray(list) +
+ Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

+
+(function(){ return _.toArray(arguments).slice(0); })(1, 2, 3);
+=> [1, 2, 3]
+
+ +

+ size_.size(list) +
+ Return the number of values in the list. +

+
+_.size({one : 1, two : 2, three : 3});
+=> 3
+
+ +

Array Functions

+ +

+ Note: All array functions will also work on the arguments object. +

+ +

+ first_.first(array, [n]) + Alias: head +
+ Returns the first element of an array. Passing n will + return the first n elements of the array. +

+
+_.first([5, 4, 3, 2, 1]);
+=> 5
+
+ +

+ initial_.initial(array, [n]) +
+ Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

+
+_.initial([5, 4, 3, 2, 1]);
+=> [5, 4, 3, 2]
+
+ +

+ last_.last(array, [n]) +
+ Returns the last element of an array. Passing n will return + the last n elements of the array. +

+
+_.last([5, 4, 3, 2, 1]);
+=> 1
+
+ +

+ rest_.rest(array, [index]) + Alias: tail +
+ Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

+
+_.rest([5, 4, 3, 2, 1]);
+=> [4, 3, 2, 1]
+
+ +

+ compact_.compact(array) +
+ Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

+
+_.compact([0, 1, false, 2, '', 3]);
+=> [1, 2, 3]
+
+ +

+ flatten_.flatten(array) +
+ Flattens a nested array (the nesting can be to any depth). +

+
+_.flatten([1, [2], [3, [[[4]]]]]);
+=> [1, 2, 3, 4];
+
+ +

+ without_.without(array, [*values]) +
+ Returns a copy of the array with all instances of the values + removed. === is used for the equality test. +

+
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=> [2, 3, 4]
+
+ +

+ union_.union(*arrays) +
+ Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

+
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2, 3, 101, 10]
+
+ +

+ intersection_.intersection(*arrays) +
+ Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

+
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2]
+
+ +

+ difference_.difference(array, *others) +
+ Similar to without, but returns the values from array that + are not present in the other arrays. +

+
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=> [1, 3, 4]
+
+ +

+ uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
+ Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

+
+_.uniq([1, 2, 1, 3, 1, 4]);
+=> [1, 2, 3, 4]
+
+ +

+ zip_.zip(*arrays) +
+ Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

+
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+
+ +

+ indexOf_.indexOf(array, value, [isSorted]) +
+ Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search. +

+
+_.indexOf([1, 2, 3], 2);
+=> 1
+
+ +

+ lastIndexOf_.lastIndexOf(array, value) +
+ Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. +

+
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=> 4
+
+ +

+ range_.range([start], stop, [step]) +
+ A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

+
+_.range(10);
+=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=> [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=> []
+
+ +

Function (uh, ahem) Functions

+ +

+ bind_.bind(function, object, [*arguments]) +
+ Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, bind arguments to the function to pre-fill them, + also known as currying. +

+
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=> 'hi: moe'
+
+ +

+ bindAll_.bindAll(object, [*methodNames]) +
+ Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

+
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=> When the button is clicked, this.label will have the correct value...
+
+ +

+ memoize_.memoize(function, [hashFunction]) +
+ Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

+
+var fibonacci = _.memoize(function(n) {
+  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+
+ +

+ delay_.delay(function, wait, [*arguments]) +
+ Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

+
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=> 'logged later' // Appears after one second.
+
+ +

+ defer_.defer(function) +
+ Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. +

+
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+
+ +

+ throttle_.throttle(function, wait) +
+ Returns a throttled version of the function, that, when invoked repeatedly, + will only actually call the wrapped function at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

+
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+
+ +

+ debounce_.debounce(function, wait) +
+ Calling a debounced function will postpone its execution until after + wait milliseconds have elapsed since the last time the function + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized... +

+
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+
+ +

+ once_.once(function) +
+ Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

+
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+
+ +

+ after_.after(count, function) +
+ Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

+
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes}); 
+});
+// renderNotes is run once, after all notes have saved.
+
+ +

+ wrap_.wrap(function, wrapper) +
+ Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

+
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=> 'before, hello: moe, after'
+
+ +

+ compose_.compose(*functions) +
+ Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

+
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=> 'hi: moe!'
+
+ +

Object Functions

+ +

+ keys_.keys(object) +
+ Retrieve all the names of the object's properties. +

+
+_.keys({one : 1, two : 2, three : 3});
+=> ["one", "two", "three"]
+
+ +

+ values_.values(object) +
+ Return all of the values of the object's properties. +

+
+_.values({one : 1, two : 2, three : 3});
+=> [1, 2, 3]
+
+ +

+ functions_.functions(object) + Alias: methods +
+ Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

+
+_.functions(_);
+=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+
+ +

+ extend_.extend(destination, *sources) +
+ Copy all of the properties in the source objects over to the + destination object. It's in-order, so the last source will override + properties of the same name in previous arguments. +

+
+_.extend({name : 'moe'}, {age : 50});
+=> {name : 'moe', age : 50}
+
+ +

+ defaults_.defaults(object, *defaults) +
+ Fill in missing properties in object with default values from the + defaults objects. As soon as the property is filled, further defaults + will have no effect. +

+
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=> {flavor : "chocolate", sprinkles : "lots"}
+
+ +

+ clone_.clone(object) +
+ Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

+
+_.clone({name : 'moe'});
+=> {name : 'moe'};
+
+ +

+ tap_.tap(object, interceptor) +
+ Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

+
+_([1,2,3,200]).chain().
+  filter(function(num) { return num % 2 == 0; }).
+  tap(console.log).
+  map(function(num) { return num * num }).
+  value();
+=> [2, 200]
+=> [4, 40000]
+
+ +

+ isEqual_.isEqual(object, other) +
+ Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

+
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=> false
+_.isEqual(moe, clone);
+=> true
+
+ +

+ isEmpty_.isEmpty(object) +
+ Returns true if object contains no values. +

+
+_.isEmpty([1, 2, 3]);
+=> false
+_.isEmpty({});
+=> true
+
+ +

+ isElement_.isElement(object) +
+ Returns true if object is a DOM element. +

+
+_.isElement(jQuery('body')[0]);
+=> true
+
+ +

+ isArray_.isArray(object) +
+ Returns true if object is an Array. +

+
+(function(){ return _.isArray(arguments); })();
+=> false
+_.isArray([1,2,3]);
+=> true
+
+ +

+ isArguments_.isArguments(object) +
+ Returns true if object is an Arguments object. +

+
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=> true
+_.isArguments([1,2,3]);
+=> false
+
+ +

+ isFunction_.isFunction(object) +
+ Returns true if object is a Function. +

+
+_.isFunction(alert);
+=> true
+
+ +

+ isString_.isString(object) +
+ Returns true if object is a String. +

+
+_.isString("moe");
+=> true
+
+ +

+ isNumber_.isNumber(object) +
+ Returns true if object is a Number. +

+
+_.isNumber(8.4 * 5);
+=> true
+
+ +

+ isBoolean_.isBoolean(object) +
+ Returns true if object is either true or false. +

+
+_.isBoolean(null);
+=> false
+
+ +

+ isDate_.isDate(object) +
+ Returns true if object is a Date. +

+
+_.isDate(new Date());
+=> true
+
+ +

+ isRegExp_.isRegExp(object) +
+ Returns true if object is a RegExp. +

+
+_.isRegExp(/moe/);
+=> true
+
+ +

+ isNaN_.isNaN(object) +
+ Returns true if object is NaN.
Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

+
+_.isNaN(NaN);
+=> true
+isNaN(undefined);
+=> true
+_.isNaN(undefined);
+=> false
+
+ +

+ isNull_.isNull(object) +
+ Returns true if the value of object is null. +

+
+_.isNull(null);
+=> true
+_.isNull(undefined);
+=> false
+
+ +

+ isUndefined_.isUndefined(variable) +
+ Returns true if variable is undefined. +

+
+_.isUndefined(window.missingVariable);
+=> true
+
+ +

Utility Functions

+ +

+ noConflict_.noConflict() +
+ Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

+
+var underscore = _.noConflict();
+ +

+ identity_.identity(value) +
+ Returns the same value that is used as the argument. In math: + f(x) = x
+ This function looks useless, but is used throughout Underscore as + a default iterator. +

+
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=> true
+ +

+ times_.times(n, iterator) +
+ Invokes the given iterator function n times. +

+
+_(3).times(function(){ genie.grantWish(); });
+ +

+ mixin_.mixin(object) +
+ Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

+
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=> "Fabio"
+
+ +

+ uniqueId_.uniqueId([prefix]) +
+ Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. +

+
+_.uniqueId('contact_');
+=> 'contact_104'
+ +

+ escape_.escape(string) +
+ Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

+
+_.escape('Curly, Larry & Moe');
+=> "Curly, Larry &amp; Moe"
+ +

+ template_.template(templateString, [context]) +
+ Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using
+ <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + context object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the context + object as the second parameter to template in order to render + immediately instead of returning a template function. +

+
+var compiled = _.template("hello: <%= name %>");
+compiled({name : 'moe'});
+=> "hello: moe"
+
+var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=> "<li>moe</li><li>curly</li><li>larry</li>"
+
+var template = _.template("<b><%- value %></b>");
+template({value : '<script>'});
+=> "<b>&lt;script&gt;</b>"
+ +

+ You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

+ +
+var compiled = _.template("<% print('Hello ' + epithet); %>");
+compiled({epithet: "stooge"});
+=> "Hello stooge."
+ +

+ If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex, and an (optional) evaluate regex + to match expressions that should be inserted and evaluated, respectively. + If no evaluate regex is provided, your templates will only be + capable of interpolating values. + For example, to perform + Mustache.js + style templating: +

+ +
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=> "Hello Mustache!"
+ +

Chaining

+ +

+ chain_(obj).chain() +
+ Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. ( + A more realistic example.) +

+
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _(stooges).chain()
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=> "moe is 21"
+
+ +

+ value_(obj).value() +
+ Extracts the value of a wrapped object. +

+
+_([1, 2, 3]).value();
+=> [1, 2, 3]
+
+ +

Links & Suggested Reading

+ +

+ Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays, also + available on GitHub. +

+ +

+ Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

+ +

+ Ruby's Enumerable module. +

+ +

+ Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

+ +

+ Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

+ +

+ Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

+ +

+ Python's itertools. +

+ +

Change Log

+ +

+ 1.2.3Dec. 7, 2011
+

    +
  • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
  • +
  • + Sparse array support of _.indexOf, _.lastIndexOf. +
  • +
  • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
  • +
+

+ +

+ 1.2.2Nov. 14, 2011
+

    +
  • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
  • +
  • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
  • +
  • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
  • +
  • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
  • +
+

+ +

+ 1.2.1Oct. 24, 2011
+

    +
  • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
  • +
  • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
  • +
  • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
  • +
  • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
  • +
  • + Most of the _.is[Type] checks no longer ducktype. +
  • +
  • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
  • +
  • + _.clone no longer wraps non-object types in Objects. +
  • +
  • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
  • +
+

+ +

+ 1.2.0Oct. 5, 2011
+

    +
  • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
  • +
  • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
  • +
  • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
  • +
  • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
  • +
  • + _.last now takes an optional argument which will return the last + N elements of the list. +
  • +
  • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
  • +
+

+ +

+ 1.1.7July 13, 2011
+ Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

+ +

+ 1.1.6April 18, 2011
+ Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

+ +

+ 1.1.5Mar 20, 2011
+ Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

+ +

+ 1.1.4Jan 9, 2011
+ Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

+ +

+ 1.1.3Dec 1, 2010
+ In CommonJS, Underscore may now be required with just:
+ var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

+ +

+ 1.1.2
+ Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

+ +

+ 1.1.1
+ Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

+ +

+ 1.1.0
+ The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

+ +

+ 1.0.4
+ Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

+ +

+ 1.0.3
+ Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

+ +

+ 1.0.2
+ Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

+ +

+ 1.0.1
+ Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

+ +

+ 1.0.0
+ Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

+ +

+ 0.6.0
+ Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

+ +

+ 0.5.8
+ Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

+ +

+ 0.5.7
+ A safer implementation of _.isArguments, and a + faster _.isNumber,
thanks to + Jed Schmidt. +

+ +

+ 0.5.6
+ Customizable delimiters for _.template, contributed by + Noah Sloan. +

+ +

+ 0.5.5
+ Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

+ +

+ 0.5.4
+ Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

+ +

+ 0.5.2
+ New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

+ +

+ 0.5.1
+ Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

+ +

+ 0.5.0
+ [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

+ +

+ 0.4.7
+ Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

+ +

+ 0.4.6
+ Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

+ +

+ 0.4.5
+ Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

+ +

+ 0.4.4
+ Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

+ +

+ 0.4.3
+ Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

+ +

+ 0.4.2
+ Renamed the unwrapping function to value, for clarity. +

+ +

+ 0.4.1
+ Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

+ +

+ 0.4.0
+ All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

+ +

+ 0.3.3
+ Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

+ +

+ 0.3.2
+ Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

+ +

+ 0.3.1
+ All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

+ +

+ 0.3.0
+ Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

+ +

+ 0.2.0
+ Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

+ +

+ 0.1.1
+ Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

+ +

+ 0.1.0
+ Initial release of Underscore.js. +

+ +

+ + A DocumentCloud Project + +

+ +
+ +
+ + + + + + diff --git a/packages/duality/node_modules/underscore/index.js b/packages/duality/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/packages/duality/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/packages/duality/node_modules/underscore/package.json b/packages/duality/node_modules/underscore/package.json new file mode 100644 index 0000000..eda11ad --- /dev/null +++ b/packages/duality/node_modules/underscore/package.json @@ -0,0 +1,12 @@ +{ + "name" : "underscore", + "description" : "JavaScript's functional programming helper library.", + "homepage" : "http://documentcloud.github.com/underscore/", + "keywords" : ["util", "functional", "server", "client", "browser"], + "author" : "Jeremy Ashkenas ", + "contributors" : [], + "dependencies" : [], + "repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"}, + "main" : "underscore.js", + "version" : "1.2.3" +} diff --git a/packages/duality/node_modules/underscore/underscore-min.js b/packages/duality/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..a2a40e4 --- /dev/null +++ b/packages/duality/node_modules/underscore/underscore-min.js @@ -0,0 +1,30 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, +h)&&!f--)break;g=!f}}d.pop();return g}var s=this,F=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.concat,H=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&& +define.amd?define("underscore",function(){return b}):s._=b;b.VERSION="1.2.3";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(x&&a.reduce===x)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(y&&a.reduceRight===y)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g, +c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;D(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.filter===z)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(A&&a.every===A)return a.every(c, +b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var D=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(B&&a.some===B)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=D(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a, +d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex= +function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after= +function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments, +1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a=== +Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)== +"[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),function(c){J(c, +b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g, +"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var u=function(a,c){return c?b(a).chain():a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return u(c.apply(b, +a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped,arguments);return u(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return u(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/packages/duality/node_modules/underscore/underscore.js b/packages/duality/node_modules/underscore/underscore.js new file mode 100644 index 0000000..b6b2813 --- /dev/null +++ b/packages/duality/node_modules/underscore/underscore.js @@ -0,0 +1,981 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // 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 slice = ArrayProto.slice, + concat = ArrayProto.concat, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js** and **"CommonJS"**, with + // backwards-compatibility for the old `require()` API. If we're not in + // CommonJS, add `_` to the global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore', function() { + return _; + }); + } else { + // Exported as a string, for Closure Compiler "advanced" mode. + root['_'] = _; + } + + // Current version. + _.VERSION = '1.2.3'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (method.call ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 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. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // 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, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + 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)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // 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(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // 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 (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // 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(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // 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. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // 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 function() { + var args = concat.apply([func], arguments); + return wrapper.apply(this, args); + }; + }; + + // 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 funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // 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 = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (source[prop] !== void 0) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // 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; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // 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._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (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; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') 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`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (hasOwnProperty.call(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // 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 (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; + return true; + }; + + // 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) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && hasOwnProperty.call(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return 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 a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // 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; + }; + + // 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 iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // 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 + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape, function(match, code) { + return "',_.escape(" + code.replace(/\\'/g, "'") + "),'"; + }) + .replace(c.interpolate, function(match, code) { + return "'," + code.replace(/\\'/g, "'") + ",'"; + }) + .replace(c.evaluate || null, function(match, code) { + return "');" + code.replace(/\\'/g, "'") + .replace(/[\r\n\t]/g, ' ') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // The OOP Wrapper + // --------------- + + // 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. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // 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]; + wrapper.prototype[name] = function() { + method.apply(this._wrapped, arguments); + return result(this._wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/packages/dust/build/utils.js b/packages/dust/build/utils.js index c7caa2d..7c16082 100644 --- a/packages/dust/build/utils.js +++ b/packages/dust/build/utils.js @@ -1,8 +1,8 @@ var async = require('async'), - utils = require('kanso/utils'), - dust = require('../dustjs/lib/dust'), + utils = require('kanso-utils/utils'), + dust = require('dust'), fs = require('fs'), - _ = require('underscore/underscore')._; + _ = require('underscore')._; // disable whitespace compression diff --git a/packages/dust/node_modules/async/LICENSE b/packages/dust/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/dust/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/dust/node_modules/async/Makefile b/packages/dust/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/dust/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/dust/node_modules/async/README.md b/packages/dust/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/dust/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/dust/node_modules/async/deps/nodeunit.css b/packages/dust/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/dust/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/dust/node_modules/async/deps/nodeunit.js b/packages/dust/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/dust/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/dust/node_modules/async/index.js b/packages/dust/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/dust/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/dust/node_modules/async/lib/async.js b/packages/dust/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/dust/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/dust/node_modules/async/nodelint.cfg b/packages/dust/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/dust/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/dust/node_modules/async/package.json b/packages/dust/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/dust/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/dust/node_modules/async/test/test-async.js b/packages/dust/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/dust/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/dust/node_modules/async/test/test.html b/packages/dust/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/dust/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/dust/dustjs/LICENSE b/packages/dust/node_modules/dust/LICENSE similarity index 100% rename from packages/dust/dustjs/LICENSE rename to packages/dust/node_modules/dust/LICENSE diff --git a/packages/dust/dustjs/Makefile b/packages/dust/node_modules/dust/Makefile similarity index 100% rename from packages/dust/dustjs/Makefile rename to packages/dust/node_modules/dust/Makefile diff --git a/packages/dust/dustjs/README.md b/packages/dust/node_modules/dust/README.md similarity index 100% rename from packages/dust/dustjs/README.md rename to packages/dust/node_modules/dust/README.md diff --git a/packages/dust/dustjs/TODO b/packages/dust/node_modules/dust/TODO similarity index 100% rename from packages/dust/dustjs/TODO rename to packages/dust/node_modules/dust/TODO diff --git a/packages/dust/dustjs/benchmark/index.html b/packages/dust/node_modules/dust/benchmark/index.html similarity index 100% rename from packages/dust/dustjs/benchmark/index.html rename to packages/dust/node_modules/dust/benchmark/index.html diff --git a/packages/dust/dustjs/benchmark/server.js b/packages/dust/node_modules/dust/benchmark/server.js similarity index 100% rename from packages/dust/dustjs/benchmark/server.js rename to packages/dust/node_modules/dust/benchmark/server.js diff --git a/packages/dust/dustjs/benchmark/suites/dust_suite.js b/packages/dust/node_modules/dust/benchmark/suites/dust_suite.js similarity index 100% rename from packages/dust/dustjs/benchmark/suites/dust_suite.js rename to packages/dust/node_modules/dust/benchmark/suites/dust_suite.js diff --git a/packages/dust/dustjs/benchmark/suites/handlebars_suite.js b/packages/dust/node_modules/dust/benchmark/suites/handlebars_suite.js similarity index 100% rename from packages/dust/dustjs/benchmark/suites/handlebars_suite.js rename to packages/dust/node_modules/dust/benchmark/suites/handlebars_suite.js diff --git a/packages/dust/dustjs/benchmark/suites/jquery_suite.js b/packages/dust/node_modules/dust/benchmark/suites/jquery_suite.js similarity index 100% rename from packages/dust/dustjs/benchmark/suites/jquery_suite.js rename to packages/dust/node_modules/dust/benchmark/suites/jquery_suite.js diff --git a/packages/dust/dustjs/benchmark/suites/mustache_suite.js b/packages/dust/node_modules/dust/benchmark/suites/mustache_suite.js similarity index 100% rename from packages/dust/dustjs/benchmark/suites/mustache_suite.js rename to packages/dust/node_modules/dust/benchmark/suites/mustache_suite.js diff --git a/packages/dust/dustjs/benchmark/uubench.js b/packages/dust/node_modules/dust/benchmark/uubench.js similarity index 100% rename from packages/dust/dustjs/benchmark/uubench.js rename to packages/dust/node_modules/dust/benchmark/uubench.js diff --git a/packages/dust/dustjs/docs/about.md b/packages/dust/node_modules/dust/docs/about.md similarity index 100% rename from packages/dust/dustjs/docs/about.md rename to packages/dust/node_modules/dust/docs/about.md diff --git a/packages/dust/dustjs/docs/api.md b/packages/dust/node_modules/dust/docs/api.md similarity index 100% rename from packages/dust/dustjs/docs/api.md rename to packages/dust/node_modules/dust/docs/api.md diff --git a/packages/dust/dustjs/docs/build.js b/packages/dust/node_modules/dust/docs/build.js similarity index 100% rename from packages/dust/dustjs/docs/build.js rename to packages/dust/node_modules/dust/docs/build.js diff --git a/packages/dust/dustjs/docs/index.css b/packages/dust/node_modules/dust/docs/index.css similarity index 100% rename from packages/dust/dustjs/docs/index.css rename to packages/dust/node_modules/dust/docs/index.css diff --git a/packages/dust/dustjs/docs/index.dust.html b/packages/dust/node_modules/dust/docs/index.dust.html similarity index 100% rename from packages/dust/dustjs/docs/index.dust.html rename to packages/dust/node_modules/dust/docs/index.dust.html diff --git a/packages/dust/dustjs/docs/index.js b/packages/dust/node_modules/dust/docs/index.js similarity index 100% rename from packages/dust/dustjs/docs/index.js rename to packages/dust/node_modules/dust/docs/index.js diff --git a/packages/dust/dustjs/docs/select.dust.html b/packages/dust/node_modules/dust/docs/select.dust.html similarity index 100% rename from packages/dust/dustjs/docs/select.dust.html rename to packages/dust/node_modules/dust/docs/select.dust.html diff --git a/packages/dust/dustjs/docs/syntax.md b/packages/dust/node_modules/dust/docs/syntax.md similarity index 100% rename from packages/dust/dustjs/docs/syntax.md rename to packages/dust/node_modules/dust/docs/syntax.md diff --git a/packages/dust/dustjs/index.html b/packages/dust/node_modules/dust/index.html similarity index 100% rename from packages/dust/dustjs/index.html rename to packages/dust/node_modules/dust/index.html diff --git a/packages/dust/dustjs/lib/compiler.js b/packages/dust/node_modules/dust/lib/compiler.js similarity index 100% rename from packages/dust/dustjs/lib/compiler.js rename to packages/dust/node_modules/dust/lib/compiler.js diff --git a/packages/dust/dustjs/lib/dust.js b/packages/dust/node_modules/dust/lib/dust.js similarity index 100% rename from packages/dust/dustjs/lib/dust.js rename to packages/dust/node_modules/dust/lib/dust.js diff --git a/packages/dust/dustjs/lib/parser.js b/packages/dust/node_modules/dust/lib/parser.js similarity index 100% rename from packages/dust/dustjs/lib/parser.js rename to packages/dust/node_modules/dust/lib/parser.js diff --git a/packages/dust/dustjs/lib/server.js b/packages/dust/node_modules/dust/lib/server.js similarity index 100% rename from packages/dust/dustjs/lib/server.js rename to packages/dust/node_modules/dust/lib/server.js diff --git a/packages/dust/dustjs/package.json b/packages/dust/node_modules/dust/package.json similarity index 100% rename from packages/dust/dustjs/package.json rename to packages/dust/node_modules/dust/package.json diff --git a/packages/dust/dustjs/src/build.js b/packages/dust/node_modules/dust/src/build.js similarity index 100% rename from packages/dust/dustjs/src/build.js rename to packages/dust/node_modules/dust/src/build.js diff --git a/packages/dust/dustjs/src/dust.pegjs b/packages/dust/node_modules/dust/src/dust.pegjs similarity index 100% rename from packages/dust/dustjs/src/dust.pegjs rename to packages/dust/node_modules/dust/src/dust.pegjs diff --git a/packages/dust/dustjs/test/core.js b/packages/dust/node_modules/dust/test/core.js similarity index 100% rename from packages/dust/dustjs/test/core.js rename to packages/dust/node_modules/dust/test/core.js diff --git a/packages/dust/dustjs/test/examples.js b/packages/dust/node_modules/dust/test/examples.js similarity index 100% rename from packages/dust/dustjs/test/examples.js rename to packages/dust/node_modules/dust/test/examples.js diff --git a/packages/dust/dustjs/test/server.js b/packages/dust/node_modules/dust/test/server.js similarity index 100% rename from packages/dust/dustjs/test/server.js rename to packages/dust/node_modules/dust/test/server.js diff --git a/packages/dust/dustjs/test/uutest.js b/packages/dust/node_modules/dust/test/uutest.js similarity index 100% rename from packages/dust/dustjs/test/uutest.js rename to packages/dust/node_modules/dust/test/uutest.js diff --git a/packages/dust/dustjs/vendor/beautify.js b/packages/dust/node_modules/dust/vendor/beautify.js similarity index 100% rename from packages/dust/dustjs/vendor/beautify.js rename to packages/dust/node_modules/dust/vendor/beautify.js diff --git a/packages/dust/dustjs/vendor/ecma.js b/packages/dust/node_modules/dust/vendor/ecma.js similarity index 100% rename from packages/dust/dustjs/vendor/ecma.js rename to packages/dust/node_modules/dust/vendor/ecma.js diff --git a/packages/dust/dustjs/vendor/hijs.js b/packages/dust/node_modules/dust/vendor/hijs.js similarity index 100% rename from packages/dust/dustjs/vendor/hijs.js rename to packages/dust/node_modules/dust/vendor/hijs.js diff --git a/packages/dust/dustjs/vendor/jquery.min.js b/packages/dust/node_modules/dust/vendor/jquery.min.js similarity index 100% rename from packages/dust/dustjs/vendor/jquery.min.js rename to packages/dust/node_modules/dust/vendor/jquery.min.js diff --git a/packages/dust/dustjs/vendor/jsdump.js b/packages/dust/node_modules/dust/vendor/jsdump.js similarity index 100% rename from packages/dust/dustjs/vendor/jsdump.js rename to packages/dust/node_modules/dust/vendor/jsdump.js diff --git a/packages/dust/dustjs/vendor/showdown.js b/packages/dust/node_modules/dust/vendor/showdown.js similarity index 100% rename from packages/dust/dustjs/vendor/showdown.js rename to packages/dust/node_modules/dust/vendor/showdown.js diff --git a/packages/dust/node_modules/kanso-utils/attachments.js b/packages/dust/node_modules/kanso-utils/attachments.js new file mode 100644 index 0000000..330cc45 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/attachments.js @@ -0,0 +1,116 @@ +/** + * Functions related to the loading and manipulation of attachments in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + mime = require('mime'), + async = require('async'), + fs = require('fs'); + + +/** + * + * @param {Object} doc + * @param {String} path + * @param {Buffer} content + * @returns {Object} + */ + +exports.add = function (doc, ddoc_path, original_path, content) { + if (!doc._attachments) { + doc._attachments = {}; + } + doc._attachments[ddoc_path] = { + 'content_type': mime.lookup(original_path), + 'data': content.toString('base64'), + // custom addition removed in cleanup postprocessor + '_original_path': original_path + }; + return doc; +}; + + +/** + * Searchs a path for attachments, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a file or directory + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads an attachment file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + exports.add(doc, rel, p, content); + callback() + }); +}; + + +/** + * Find all attachments below or at a given path, recursing through + * subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for attachments. This function omits + * hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + return true; + }; +}; diff --git a/packages/dust/node_modules/kanso-utils/index.js b/packages/dust/node_modules/kanso-utils/index.js new file mode 100644 index 0000000..0b79a79 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/index.js @@ -0,0 +1,5 @@ +module.exports = { + attachments: require('./attachments'), + modules: require('./modules'), + utils: require('./utils') +}; diff --git a/packages/dust/node_modules/kanso-utils/modules.js b/packages/dust/node_modules/kanso-utils/modules.js new file mode 100644 index 0000000..4324d02 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/modules.js @@ -0,0 +1,289 @@ +/** + * Functions related to the loading and manipulation of CommonJS Modules in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + async = require('async'), + path = require('path'), + fs = require('fs'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +// As modules are added, their original file paths are added to this object +// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...} +exports.originalPaths = {}; + + +/** + * Add the module source to the document in the correct location for requiring + * server-side, then add the path to the _modules property for use by the + * modules plugin postprocessor (when creating the kanso.js attachment) + * + * Returns the updated document. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.add = function (doc, path, src) { + var curr = utils.getPropertyPath(doc, path, true); + if (curr !== undefined) { + var paths = utils.getPropertyPaths(path, curr); + throw new Error( + 'Adding ' + path + ' would overwrite:\n' + + ' ' + paths.join('\n ') + '\n' + + '\n' + + 'This error often occurs because there is a module with the\n' + + 'same name as a directory containing modules. There is no way\n' + + 'to map this structure in the design doc.\n' + ); + } + utils.setPropertyPath(doc, path, src); + if (!doc._modules) { + doc._modules = {}; + } + doc._modules[path] = null; + return doc; +}; + + +/** + * Wraps module source code with useful comments and module cache boilerplate + * code. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.wrap = function (path, src) { + return '/********** ' + path + ' **********/\n\n' + + 'kanso.moduleCache["' + path.replace('"', '\\"') + '"] = ' + + '{load: (function (module, exports, require) {\n\n' + src + '\n\n})};' + + '\n\n'; +}; + + +/** + * Searchs a path for commonjs modules, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a module file or directory of modules + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads a module file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + var module_path = rel.replace(/\.js$/, ''); + var src = content.toString(); + exports.add(doc, module_path, src); + utils.setPropertyPath(exports.originalPaths, rel, p); + callback() + }); +}; + + +/** + * Find all modules below or at a given path, recursing through subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for module files. This function tests + * for a .js extension and omits hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + // should have a .js extension + if (!/\.js$/.test(f)) { + return false; + } + return true; + }; +}; + + +/** + * Parses the exports.originalPaths object to return an array of filenames + */ + +exports.getFilenames = function (obj) { + var names = []; + for (var k in obj) { + if (typeof obj[k] === 'object') { + names.concat(exports.getFilenames(obj[k]).map(function (n) { + return k + '/' + n; + })); + } + else { + names.push(k); + } + } + return names; +}; + + +/** + * Loads a commonjs module from the loaded design document, returning + * the exported properties. The current_dir and target parameters are not the + * path of the module on the filesystem, but rather the path of the module + * within couchdb, root ('/') being the design doc itself. + * + * @param {Object} module_cache + * @param {Object} doc + * @param {String} current_dir + * @param {String} target + * @param {Object} context - optional, extends sandbox object + */ + +exports.require = function (module_cache, doc, current, target, context) { + var current_dir = path.dirname(current); + if (target.charAt(0) !== '.') { + current_dir = '/'; + } + var p = path.normalize(path.join(current_dir, target)); + if (module_cache[p]) { + return module_cache[p]; + } + + var nodes = p.split('/').slice(1); + var content = nodes.reduce(function (a, x) { + if (a[x] === undefined) { + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ') - ' + + 'Module not found' + ); + } + a = a[x]; + return a; + }, doc); + + var filename = utils.getPropertyPath( + exports.originalPaths, p.substr(1), true + ); + + // if you attempt to require + if (typeof filename === 'object') { + var filenames = exports.getFilenames(filename); + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ')\n\n' + + 'It\'s not possible to require directories of modules in CouchDB,\n' + + 'you have to specify one of the following sub-modules directly:\n' + + filenames.map(function (f) { + return ' ' + p.replace(/^\//, '') + '/' + f; + }).join('\n') + '\n' + ); + } + + var module = { + id: p.substr(1), + exports: {}, + // TODO: this property is not provided by couchdb, but is by node: + //filename: filename, + // TODO: this property is not provided by couchdb, but is by node: + //require: async.apply(exports.require, module_cache, doc, p) + // TODO: module properties provided by couchdb, but not by kanso + // * current + // * parent + }; + var sandbox = { + module: module, + exports: module.exports, + //require: module.require, + require: async.apply(exports.require, module_cache, doc, p), + log: function () { + console.log.apply(console, arguments); + } + }; + + // copy context into sandbox + if (context) { + Object.keys(context).forEach(function (k) { + sandbox[k] = context[k]; + }); + } + + // Create a placeholder for this module's exports so circular requires + // are possible. TODO: node.js uses a loaded = false attribute on the + // cached module object to mark this as a placeholder. + module_cache[p] = {}; + + try { + var s = new Script(content, filename).runInNewContext(sandbox); + } + catch (e) { + if (e instanceof SyntaxError && filename) { + // gives a better syntax error than runInNewContext + // with filename and line number + require(filename); + } + if (!e.got_filename) { + e.message = 'Error loading: ' + filename + '\n' + e.message; + e.got_filename = true; + } + throw e; + } + module_cache[p] = sandbox.module.exports; + return module_cache[p]; +}; diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/LICENSE b/packages/dust/node_modules/kanso-utils/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/dust/node_modules/kanso-utils/node_modules/mime/README.md b/packages/dust/node_modules/kanso-utils/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/mime.js b/packages/dust/node_modules/kanso-utils/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/package.json b/packages/dust/node_modules/kanso-utils/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/test.js b/packages/dust/node_modules/kanso-utils/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/types/mime.types b/packages/dust/node_modules/kanso-utils/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/dust/node_modules/kanso-utils/node_modules/mime/types/node.types b/packages/dust/node_modules/kanso-utils/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/dust/node_modules/kanso-utils/package.json b/packages/dust/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/dust/node_modules/kanso-utils/utils.js b/packages/dust/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/dust/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; diff --git a/packages/dust/node_modules/underscore/.npmignore b/packages/dust/node_modules/underscore/.npmignore new file mode 100644 index 0000000..2ce2684 --- /dev/null +++ b/packages/dust/node_modules/underscore/.npmignore @@ -0,0 +1,3 @@ +test/ +Rakefile +docs/ \ No newline at end of file diff --git a/packages/dust/node_modules/underscore/LICENSE b/packages/dust/node_modules/underscore/LICENSE new file mode 100644 index 0000000..58c73b9 --- /dev/null +++ b/packages/dust/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Jeremy Ashkenas, DocumentCloud + +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. \ No newline at end of file diff --git a/packages/dust/node_modules/underscore/README b/packages/dust/node_modules/underscore/README new file mode 100644 index 0000000..408145a --- /dev/null +++ b/packages/dust/node_modules/underscore/README @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ +/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ +\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://documentcloud.github.com/underscore/ + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/packages/dust/node_modules/underscore/index.html b/packages/dust/node_modules/underscore/index.html new file mode 100644 index 0000000..7453112 --- /dev/null +++ b/packages/dust/node_modules/underscore/index.html @@ -0,0 +1,1777 @@ + + + + + + Underscore.js + + + + +
+ +

Underscore.js

+ +

+ Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux. +

+ +

+ Underscore provides 60-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

+ +

+ A complete Test & Benchmark Suite + is included for your perusal. +

+ +

+ You may also read through the annotated source code. +

+ +

+ The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

+ +

+ Underscore is an open-source component of DocumentCloud. +

+ +

Downloads (Right-click, and use "Save As")

+ + + + + + + + + + +
Development Version (1.2.3)34kb, Uncompressed with Comments
Production Version (1.2.3)< 4kb, Minified and Gzipped
+ +

Table of Contents

+ + Object-Oriented and Functional Styles + +

+ Collections +
+ each, map, + reduce, reduceRight, + find, filter, + reject, all, + any, include, + invoke, pluck, + max, min, + sortBy, groupBy, + sortedIndex, shuffle, + toArray, size +

+ +

+ Arrays +
+ first, initial, last, rest, + compact, flatten, without, + union, intersection, difference, + uniq, zip, indexOf, + lastIndexOf, range +

+ +

+ Functions +
+ bind, bindAll, + memoize, delay, defer, + throttle, debounce, + once, after, wrap, compose +

+ +

+ Objects +
+ keys, values, + functions, extend, defaults, clone, tap, + isEqual, isEmpty, isElement, + isArray, isArguments, isFunction, isString, + isNumber, isBoolean, isDate, isRegExp, + isNaN, isNull, + isUndefined + +

+ +

+ Utility +
+ noConflict, + identity, times, + mixin, uniqueId, + escape, template +

+ +

+ Chaining +
+ chain, value +

+ +
+ +

Object-Oriented and Functional Styles

+ +

+ You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

+ +
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });
+ +

+ Using the object-oriented style allows you to chain together methods. Calling + chain on a wrapped object will cause all future method calls to + return wrapped objects as well. When you've finished the computation, + use value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

+ +
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_(lyrics).chain()
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+}, {}).value();
+
+=> {lumberjack : 2, all : 4, night : 2 ... }
+ +

+ In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

+ +

Collection Functions (Arrays or Objects)

+ +

+ each_.each(list, iterator, [context]) + Alias: forEach +
+ Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

+
+_.each([1, 2, 3], function(num){ alert(num); });
+=> alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
+=> alerts each number in turn...
+ +

+ map_.map(list, iterator, [context]) +
+ Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

+
+_.map([1, 2, 3], function(num){ return num * 3; });
+=> [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=> [3, 6, 9]
+ +

+ reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
+ Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. +

+
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=> 6
+
+ +

+ reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
+ The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

+
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=> [4, 5, 2, 3, 0, 1]
+
+ +

+ find_.find(list, iterator, [context]) + Alias: detect +
+ Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

+
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> 2
+
+ +

+ filter_.filter(list, iterator, [context]) + Alias: select +
+ Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

+
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [2, 4, 6]
+
+ +

+ reject_.reject(list, iterator, [context]) +
+ Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

+
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [1, 3, 5]
+
+ +

+ all_.all(list, iterator, [context]) + Alias: every +
+ Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

+
+_.all([true, 1, null, 'yes'], _.identity);
+=> false
+
+ +

+ any_.any(list, [iterator], [context]) + Alias: some +
+ Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

+
+_.any([null, 0, 'yes', false]);
+=> true
+
+ +

+ include_.include(list, value) + Alias: contains +
+ Returns true if the value is present in the list, using + === to test equality. Uses indexOf internally, if list + is an Array. +

+
+_.include([1, 2, 3], 3);
+=> true
+
+ +

+ invoke_.invoke(list, methodName, [*arguments]) +
+ Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

+
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=> [[1, 5, 7], [1, 2, 3]]
+
+ +

+ pluck_.pluck(list, propertyName) +
+ A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=> ["moe", "larry", "curly"]
+
+ +

+ max_.max(list, [iterator], [context]) +
+ Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=> {name : 'curly', age : 60};
+
+ +

+ min_.min(list, [iterator], [context]) +
+ Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=> 2
+
+ +

+ sortBy_.sortBy(list, iterator, [context]) +
+ Returns a sorted copy of list, ranked by the results of running + each value through iterator. +

+
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=> [5, 4, 6, 3, 1, 2]
+
+ +

+ groupBy_.groupBy(list, iterator) +
+ Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

+
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=> {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=> {3: ["one", "two"], 5: ["three"]}
+
+ +

+ sortedIndex_.sortedIndex(list, value, [iterator]) +
+ Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value. +

+
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=> 3
+
+ +

+ shuffle_.shuffle(list) +
+ Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

+
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=> [4, 1, 6, 3, 5, 2]
+
+ +

+ toArray_.toArray(list) +
+ Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

+
+(function(){ return _.toArray(arguments).slice(0); })(1, 2, 3);
+=> [1, 2, 3]
+
+ +

+ size_.size(list) +
+ Return the number of values in the list. +

+
+_.size({one : 1, two : 2, three : 3});
+=> 3
+
+ +

Array Functions

+ +

+ Note: All array functions will also work on the arguments object. +

+ +

+ first_.first(array, [n]) + Alias: head +
+ Returns the first element of an array. Passing n will + return the first n elements of the array. +

+
+_.first([5, 4, 3, 2, 1]);
+=> 5
+
+ +

+ initial_.initial(array, [n]) +
+ Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

+
+_.initial([5, 4, 3, 2, 1]);
+=> [5, 4, 3, 2]
+
+ +

+ last_.last(array, [n]) +
+ Returns the last element of an array. Passing n will return + the last n elements of the array. +

+
+_.last([5, 4, 3, 2, 1]);
+=> 1
+
+ +

+ rest_.rest(array, [index]) + Alias: tail +
+ Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

+
+_.rest([5, 4, 3, 2, 1]);
+=> [4, 3, 2, 1]
+
+ +

+ compact_.compact(array) +
+ Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

+
+_.compact([0, 1, false, 2, '', 3]);
+=> [1, 2, 3]
+
+ +

+ flatten_.flatten(array) +
+ Flattens a nested array (the nesting can be to any depth). +

+
+_.flatten([1, [2], [3, [[[4]]]]]);
+=> [1, 2, 3, 4];
+
+ +

+ without_.without(array, [*values]) +
+ Returns a copy of the array with all instances of the values + removed. === is used for the equality test. +

+
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=> [2, 3, 4]
+
+ +

+ union_.union(*arrays) +
+ Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

+
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2, 3, 101, 10]
+
+ +

+ intersection_.intersection(*arrays) +
+ Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

+
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2]
+
+ +

+ difference_.difference(array, *others) +
+ Similar to without, but returns the values from array that + are not present in the other arrays. +

+
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=> [1, 3, 4]
+
+ +

+ uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
+ Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

+
+_.uniq([1, 2, 1, 3, 1, 4]);
+=> [1, 2, 3, 4]
+
+ +

+ zip_.zip(*arrays) +
+ Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

+
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+
+ +

+ indexOf_.indexOf(array, value, [isSorted]) +
+ Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search. +

+
+_.indexOf([1, 2, 3], 2);
+=> 1
+
+ +

+ lastIndexOf_.lastIndexOf(array, value) +
+ Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. +

+
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=> 4
+
+ +

+ range_.range([start], stop, [step]) +
+ A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

+
+_.range(10);
+=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=> [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=> []
+
+ +

Function (uh, ahem) Functions

+ +

+ bind_.bind(function, object, [*arguments]) +
+ Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, bind arguments to the function to pre-fill them, + also known as currying. +

+
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=> 'hi: moe'
+
+ +

+ bindAll_.bindAll(object, [*methodNames]) +
+ Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

+
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=> When the button is clicked, this.label will have the correct value...
+
+ +

+ memoize_.memoize(function, [hashFunction]) +
+ Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

+
+var fibonacci = _.memoize(function(n) {
+  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+
+ +

+ delay_.delay(function, wait, [*arguments]) +
+ Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

+
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=> 'logged later' // Appears after one second.
+
+ +

+ defer_.defer(function) +
+ Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. +

+
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+
+ +

+ throttle_.throttle(function, wait) +
+ Returns a throttled version of the function, that, when invoked repeatedly, + will only actually call the wrapped function at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

+
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+
+ +

+ debounce_.debounce(function, wait) +
+ Calling a debounced function will postpone its execution until after + wait milliseconds have elapsed since the last time the function + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized... +

+
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+
+ +

+ once_.once(function) +
+ Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

+
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+
+ +

+ after_.after(count, function) +
+ Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

+
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes}); 
+});
+// renderNotes is run once, after all notes have saved.
+
+ +

+ wrap_.wrap(function, wrapper) +
+ Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

+
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=> 'before, hello: moe, after'
+
+ +

+ compose_.compose(*functions) +
+ Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

+
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=> 'hi: moe!'
+
+ +

Object Functions

+ +

+ keys_.keys(object) +
+ Retrieve all the names of the object's properties. +

+
+_.keys({one : 1, two : 2, three : 3});
+=> ["one", "two", "three"]
+
+ +

+ values_.values(object) +
+ Return all of the values of the object's properties. +

+
+_.values({one : 1, two : 2, three : 3});
+=> [1, 2, 3]
+
+ +

+ functions_.functions(object) + Alias: methods +
+ Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

+
+_.functions(_);
+=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+
+ +

+ extend_.extend(destination, *sources) +
+ Copy all of the properties in the source objects over to the + destination object. It's in-order, so the last source will override + properties of the same name in previous arguments. +

+
+_.extend({name : 'moe'}, {age : 50});
+=> {name : 'moe', age : 50}
+
+ +

+ defaults_.defaults(object, *defaults) +
+ Fill in missing properties in object with default values from the + defaults objects. As soon as the property is filled, further defaults + will have no effect. +

+
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=> {flavor : "chocolate", sprinkles : "lots"}
+
+ +

+ clone_.clone(object) +
+ Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

+
+_.clone({name : 'moe'});
+=> {name : 'moe'};
+
+ +

+ tap_.tap(object, interceptor) +
+ Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

+
+_([1,2,3,200]).chain().
+  filter(function(num) { return num % 2 == 0; }).
+  tap(console.log).
+  map(function(num) { return num * num }).
+  value();
+=> [2, 200]
+=> [4, 40000]
+
+ +

+ isEqual_.isEqual(object, other) +
+ Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

+
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=> false
+_.isEqual(moe, clone);
+=> true
+
+ +

+ isEmpty_.isEmpty(object) +
+ Returns true if object contains no values. +

+
+_.isEmpty([1, 2, 3]);
+=> false
+_.isEmpty({});
+=> true
+
+ +

+ isElement_.isElement(object) +
+ Returns true if object is a DOM element. +

+
+_.isElement(jQuery('body')[0]);
+=> true
+
+ +

+ isArray_.isArray(object) +
+ Returns true if object is an Array. +

+
+(function(){ return _.isArray(arguments); })();
+=> false
+_.isArray([1,2,3]);
+=> true
+
+ +

+ isArguments_.isArguments(object) +
+ Returns true if object is an Arguments object. +

+
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=> true
+_.isArguments([1,2,3]);
+=> false
+
+ +

+ isFunction_.isFunction(object) +
+ Returns true if object is a Function. +

+
+_.isFunction(alert);
+=> true
+
+ +

+ isString_.isString(object) +
+ Returns true if object is a String. +

+
+_.isString("moe");
+=> true
+
+ +

+ isNumber_.isNumber(object) +
+ Returns true if object is a Number. +

+
+_.isNumber(8.4 * 5);
+=> true
+
+ +

+ isBoolean_.isBoolean(object) +
+ Returns true if object is either true or false. +

+
+_.isBoolean(null);
+=> false
+
+ +

+ isDate_.isDate(object) +
+ Returns true if object is a Date. +

+
+_.isDate(new Date());
+=> true
+
+ +

+ isRegExp_.isRegExp(object) +
+ Returns true if object is a RegExp. +

+
+_.isRegExp(/moe/);
+=> true
+
+ +

+ isNaN_.isNaN(object) +
+ Returns true if object is NaN.
Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

+
+_.isNaN(NaN);
+=> true
+isNaN(undefined);
+=> true
+_.isNaN(undefined);
+=> false
+
+ +

+ isNull_.isNull(object) +
+ Returns true if the value of object is null. +

+
+_.isNull(null);
+=> true
+_.isNull(undefined);
+=> false
+
+ +

+ isUndefined_.isUndefined(variable) +
+ Returns true if variable is undefined. +

+
+_.isUndefined(window.missingVariable);
+=> true
+
+ +

Utility Functions

+ +

+ noConflict_.noConflict() +
+ Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

+
+var underscore = _.noConflict();
+ +

+ identity_.identity(value) +
+ Returns the same value that is used as the argument. In math: + f(x) = x
+ This function looks useless, but is used throughout Underscore as + a default iterator. +

+
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=> true
+ +

+ times_.times(n, iterator) +
+ Invokes the given iterator function n times. +

+
+_(3).times(function(){ genie.grantWish(); });
+ +

+ mixin_.mixin(object) +
+ Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

+
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=> "Fabio"
+
+ +

+ uniqueId_.uniqueId([prefix]) +
+ Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. +

+
+_.uniqueId('contact_');
+=> 'contact_104'
+ +

+ escape_.escape(string) +
+ Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

+
+_.escape('Curly, Larry & Moe');
+=> "Curly, Larry &amp; Moe"
+ +

+ template_.template(templateString, [context]) +
+ Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using
+ <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + context object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the context + object as the second parameter to template in order to render + immediately instead of returning a template function. +

+
+var compiled = _.template("hello: <%= name %>");
+compiled({name : 'moe'});
+=> "hello: moe"
+
+var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=> "<li>moe</li><li>curly</li><li>larry</li>"
+
+var template = _.template("<b><%- value %></b>");
+template({value : '<script>'});
+=> "<b>&lt;script&gt;</b>"
+ +

+ You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

+ +
+var compiled = _.template("<% print('Hello ' + epithet); %>");
+compiled({epithet: "stooge"});
+=> "Hello stooge."
+ +

+ If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex, and an (optional) evaluate regex + to match expressions that should be inserted and evaluated, respectively. + If no evaluate regex is provided, your templates will only be + capable of interpolating values. + For example, to perform + Mustache.js + style templating: +

+ +
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=> "Hello Mustache!"
+ +

Chaining

+ +

+ chain_(obj).chain() +
+ Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. ( + A more realistic example.) +

+
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _(stooges).chain()
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=> "moe is 21"
+
+ +

+ value_(obj).value() +
+ Extracts the value of a wrapped object. +

+
+_([1, 2, 3]).value();
+=> [1, 2, 3]
+
+ +

Links & Suggested Reading

+ +

+ Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays, also + available on GitHub. +

+ +

+ Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

+ +

+ Ruby's Enumerable module. +

+ +

+ Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

+ +

+ Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

+ +

+ Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

+ +

+ Python's itertools. +

+ +

Change Log

+ +

+ 1.2.3Dec. 7, 2011
+

    +
  • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
  • +
  • + Sparse array support of _.indexOf, _.lastIndexOf. +
  • +
  • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
  • +
+

+ +

+ 1.2.2Nov. 14, 2011
+

    +
  • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
  • +
  • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
  • +
  • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
  • +
  • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
  • +
+

+ +

+ 1.2.1Oct. 24, 2011
+

    +
  • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
  • +
  • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
  • +
  • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
  • +
  • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
  • +
  • + Most of the _.is[Type] checks no longer ducktype. +
  • +
  • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
  • +
  • + _.clone no longer wraps non-object types in Objects. +
  • +
  • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
  • +
+

+ +

+ 1.2.0Oct. 5, 2011
+

    +
  • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
  • +
  • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
  • +
  • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
  • +
  • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
  • +
  • + _.last now takes an optional argument which will return the last + N elements of the list. +
  • +
  • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
  • +
+

+ +

+ 1.1.7July 13, 2011
+ Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

+ +

+ 1.1.6April 18, 2011
+ Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

+ +

+ 1.1.5Mar 20, 2011
+ Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

+ +

+ 1.1.4Jan 9, 2011
+ Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

+ +

+ 1.1.3Dec 1, 2010
+ In CommonJS, Underscore may now be required with just:
+ var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

+ +

+ 1.1.2
+ Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

+ +

+ 1.1.1
+ Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

+ +

+ 1.1.0
+ The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

+ +

+ 1.0.4
+ Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

+ +

+ 1.0.3
+ Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

+ +

+ 1.0.2
+ Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

+ +

+ 1.0.1
+ Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

+ +

+ 1.0.0
+ Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

+ +

+ 0.6.0
+ Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

+ +

+ 0.5.8
+ Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

+ +

+ 0.5.7
+ A safer implementation of _.isArguments, and a + faster _.isNumber,
thanks to + Jed Schmidt. +

+ +

+ 0.5.6
+ Customizable delimiters for _.template, contributed by + Noah Sloan. +

+ +

+ 0.5.5
+ Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

+ +

+ 0.5.4
+ Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

+ +

+ 0.5.2
+ New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

+ +

+ 0.5.1
+ Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

+ +

+ 0.5.0
+ [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

+ +

+ 0.4.7
+ Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

+ +

+ 0.4.6
+ Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

+ +

+ 0.4.5
+ Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

+ +

+ 0.4.4
+ Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

+ +

+ 0.4.3
+ Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

+ +

+ 0.4.2
+ Renamed the unwrapping function to value, for clarity. +

+ +

+ 0.4.1
+ Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

+ +

+ 0.4.0
+ All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

+ +

+ 0.3.3
+ Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

+ +

+ 0.3.2
+ Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

+ +

+ 0.3.1
+ All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

+ +

+ 0.3.0
+ Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

+ +

+ 0.2.0
+ Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

+ +

+ 0.1.1
+ Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

+ +

+ 0.1.0
+ Initial release of Underscore.js. +

+ +

+ + A DocumentCloud Project + +

+ +
+ +
+ + + + + + diff --git a/packages/dust/node_modules/underscore/index.js b/packages/dust/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/packages/dust/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/packages/dust/node_modules/underscore/package.json b/packages/dust/node_modules/underscore/package.json new file mode 100644 index 0000000..eda11ad --- /dev/null +++ b/packages/dust/node_modules/underscore/package.json @@ -0,0 +1,12 @@ +{ + "name" : "underscore", + "description" : "JavaScript's functional programming helper library.", + "homepage" : "http://documentcloud.github.com/underscore/", + "keywords" : ["util", "functional", "server", "client", "browser"], + "author" : "Jeremy Ashkenas ", + "contributors" : [], + "dependencies" : [], + "repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"}, + "main" : "underscore.js", + "version" : "1.2.3" +} diff --git a/packages/dust/node_modules/underscore/underscore-min.js b/packages/dust/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..a2a40e4 --- /dev/null +++ b/packages/dust/node_modules/underscore/underscore-min.js @@ -0,0 +1,30 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, +h)&&!f--)break;g=!f}}d.pop();return g}var s=this,F=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.concat,H=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&& +define.amd?define("underscore",function(){return b}):s._=b;b.VERSION="1.2.3";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(x&&a.reduce===x)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(y&&a.reduceRight===y)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g, +c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;D(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.filter===z)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(A&&a.every===A)return a.every(c, +b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var D=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(B&&a.some===B)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=D(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a, +d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex= +function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after= +function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments, +1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a=== +Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)== +"[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),function(c){J(c, +b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g, +"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var u=function(a,c){return c?b(a).chain():a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return u(c.apply(b, +a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped,arguments);return u(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return u(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/packages/dust/node_modules/underscore/underscore.js b/packages/dust/node_modules/underscore/underscore.js new file mode 100644 index 0000000..b6b2813 --- /dev/null +++ b/packages/dust/node_modules/underscore/underscore.js @@ -0,0 +1,981 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // 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 slice = ArrayProto.slice, + concat = ArrayProto.concat, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js** and **"CommonJS"**, with + // backwards-compatibility for the old `require()` API. If we're not in + // CommonJS, add `_` to the global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore', function() { + return _; + }); + } else { + // Exported as a string, for Closure Compiler "advanced" mode. + root['_'] = _; + } + + // Current version. + _.VERSION = '1.2.3'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (method.call ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 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. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // 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, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + 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)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // 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(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // 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 (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // 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(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // 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. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // 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 function() { + var args = concat.apply([func], arguments); + return wrapper.apply(this, args); + }; + }; + + // 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 funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // 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 = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (source[prop] !== void 0) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // 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; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // 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._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (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; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') 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`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (hasOwnProperty.call(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // 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 (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; + return true; + }; + + // 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) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && hasOwnProperty.call(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return 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 a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // 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; + }; + + // 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 iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // 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 + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape, function(match, code) { + return "',_.escape(" + code.replace(/\\'/g, "'") + "),'"; + }) + .replace(c.interpolate, function(match, code) { + return "'," + code.replace(/\\'/g, "'") + ",'"; + }) + .replace(c.evaluate || null, function(match, code) { + return "');" + code.replace(/\\'/g, "'") + .replace(/[\r\n\t]/g, ' ') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // The OOP Wrapper + // --------------- + + // 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. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // 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]; + wrapper.prototype[name] = function() { + method.apply(this._wrapped, arguments); + return result(this._wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/packages/modules/build/add.js b/packages/modules/build/add.js index 0ef9174..52fa1be 100644 --- a/packages/modules/build/add.js +++ b/packages/modules/build/add.js @@ -1,5 +1,5 @@ -var modules = require('kanso/modules'), - async = require('async'); +var async = require('async'), + modules = require('kanso-utils/modules'); /** diff --git a/packages/modules/build/attachment.js b/packages/modules/build/attachment.js index 1af4ed1..81196c2 100644 --- a/packages/modules/build/attachment.js +++ b/packages/modules/build/attachment.js @@ -1,10 +1,21 @@ +// this is because some require paths changed in the npm-compatible version +// of kanso, we want this package to support older installs too +var tryRequire = function (a, b) { + try { + return require(a); + } + catch (e) { + // throw if this one fails + return require(b); + } +}; + var fs = require('fs'), - mime = require('node-mime/mime'), - jsp = require('UglifyJS/lib/parse-js'), - pro = require('UglifyJS/lib/process'), - modules = require('kanso/modules'), - logger = require('kanso/logger'), - utils = require('kanso/utils'); + mime = require('mime'), + jsp = require('uglify-js/lib/parse-js'), + pro = require('uglify-js/lib/process'), + modules = require('kanso-utils/modules'), + utils = require('kanso-utils/utils'); function minify(src) { @@ -45,7 +56,7 @@ module.exports = function (root, path, settings, doc, callback) { var data = content.toString() + (wrapped_modules || ''); if (settings.minify) { - logger.info('compressing', 'modules.js'); + console.log('Compressing modules.js'); data = minify(data); } diff --git a/packages/modules/kanso.json b/packages/modules/kanso.json index 7e8c45e..11b7dc4 100644 --- a/packages/modules/kanso.json +++ b/packages/modules/kanso.json @@ -1,6 +1,6 @@ { "name": "modules", - "version": "0.0.8", + "version": "0.0.10", "categories": ["build-tools"], "description": "Loads CommonJS modules from the filesystem and adds to a design doc", "preprocessors": { diff --git a/packages/modules/node_modules/.bin/uglifyjs b/packages/modules/node_modules/.bin/uglifyjs new file mode 100755 index 0000000..2005b3e --- /dev/null +++ b/packages/modules/node_modules/.bin/uglifyjs @@ -0,0 +1,323 @@ +#! /usr/bin/env node +// -*- js -*- + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var options = { + ast: false, + mangle: true, + mangle_toplevel: false, + no_mangle_functions: false, + squeeze: true, + make_seqs: true, + dead_code: true, + verbose: false, + show_copyright: true, + out_same_file: false, + max_line_length: 32 * 1024, + unsafe: false, + reserved_names: null, + defines: { }, + lift_vars: false, + codegen_options: { + ascii_only: false, + beautify: false, + indent_level: 4, + indent_start: 0, + quote_keys: false, + space_colon: false, + inline_script: false + }, + make: false, + output: true // stdout +}; + +var args = jsp.slice(process.argv, 2); +var filename; + +out: while (args.length > 0) { + var v = args.shift(); + switch (v) { + case "-b": + case "--beautify": + options.codegen_options.beautify = true; + break; + case "-i": + case "--indent": + options.codegen_options.indent_level = args.shift(); + break; + case "-q": + case "--quote-keys": + options.codegen_options.quote_keys = true; + break; + case "-mt": + case "--mangle-toplevel": + options.mangle_toplevel = true; + break; + case "-nmf": + case "--no-mangle-functions": + options.no_mangle_functions = true; + break; + case "--no-mangle": + case "-nm": + options.mangle = false; + break; + case "--no-squeeze": + case "-ns": + options.squeeze = false; + break; + case "--no-seqs": + options.make_seqs = false; + break; + case "--no-dead-code": + options.dead_code = false; + break; + case "--no-copyright": + case "-nc": + options.show_copyright = false; + break; + case "-o": + case "--output": + options.output = args.shift(); + break; + case "--overwrite": + options.out_same_file = true; + break; + case "-v": + case "--verbose": + options.verbose = true; + break; + case "--ast": + options.ast = true; + break; + case "--unsafe": + options.unsafe = true; + break; + case "--max-line-len": + options.max_line_length = parseInt(args.shift(), 10); + break; + case "--reserved-names": + options.reserved_names = args.shift().split(","); + break; + case "--lift-vars": + options.lift_vars = true; + break; + case "-d": + case "--define": + var defarg = args.shift(); + try { + var defsym = function(sym) { + // KEYWORDS_ATOM doesn't include NaN or Infinity - should we check + // for them too ?? We don't check reserved words and the like as the + // define values are only substituted AFTER parsing + if (jsp.KEYWORDS_ATOM.hasOwnProperty(sym)) { + throw "Don't define values for inbuilt constant '"+sym+"'"; + } + return sym; + }, + defval = function(v) { + if (v.match(/^"(.*)"$/) || v.match(/^'(.*)'$/)) { + return [ "string", RegExp.$1 ]; + } + else if (!isNaN(parseFloat(v))) { + return [ "num", parseFloat(v) ]; + } + else if (v.match(/^[a-z\$_][a-z\$_0-9]*$/i)) { + return [ "name", v ]; + } + else if (!v.match(/"/)) { + return [ "string", v ]; + } + else if (!v.match(/'/)) { + return [ "string", v ]; + } + throw "Can't understand the specified value: "+v; + }; + if (defarg.match(/^([a-z_\$][a-z_\$0-9]*)(=(.*))?$/i)) { + var sym = defsym(RegExp.$1), + val = RegExp.$2 ? defval(RegExp.$2.substr(1)) : [ 'name', 'true' ]; + options.defines[sym] = val; + } + else { + throw "The --define option expects SYMBOL[=value]"; + } + } catch(ex) { + sys.print("ERROR: In option --define "+defarg+"\n"+ex+"\n"); + process.exit(1); + } + break; + case "--define-from-module": + var defmodarg = args.shift(), + defmodule = require(defmodarg), + sym, + val; + for (sym in defmodule) { + if (defmodule.hasOwnProperty(sym)) { + options.defines[sym] = function(val) { + if (typeof val == "string") + return [ "string", val ]; + if (typeof val == "number") + return [ "num", val ]; + if (val === true) + return [ 'name', 'true' ]; + if (val === false) + return [ 'name', 'false' ]; + if (val === null) + return [ 'name', 'null' ]; + if (val === undefined) + return [ 'name', 'undefined' ]; + sys.print("ERROR: In option --define-from-module "+defmodarg+"\n"); + sys.print("ERROR: Unknown object type for: "+sym+"="+val+"\n"); + process.exit(1); + return null; + }(defmodule[sym]); + } + } + break; + case "--ascii": + options.codegen_options.ascii_only = true; + break; + case "--make": + options.make = true; + break; + case "--inline-script": + options.codegen_options.inline_script = true; + break; + default: + filename = v; + break out; + } +} + +if (options.verbose) { + pro.set_logger(function(msg){ + sys.debug(msg); + }); +} + +jsp.set_logger(function(msg){ + sys.debug(msg); +}); + +if (options.make) { + options.out_same_file = false; // doesn't make sense in this case + var makefile = JSON.parse(fs.readFileSync(filename || "Makefile.uglify.js").toString()); + output(makefile.files.map(function(file){ + var code = fs.readFileSync(file.name); + if (file.module) { + code = "!function(exports, global){global = this;\n" + code + "\n;this." + file.module + " = exports;}({})"; + } + else if (file.hide) { + code = "(function(){" + code + "}());"; + } + return squeeze_it(code); + }).join("\n")); +} +else if (filename) { + fs.readFile(filename, "utf8", function(err, text){ + if (err) throw err; + output(squeeze_it(text)); + }); +} +else { + var stdin = process.openStdin(); + stdin.setEncoding("utf8"); + var text = ""; + stdin.on("data", function(chunk){ + text += chunk; + }); + stdin.on("end", function() { + output(squeeze_it(text)); + }); +} + +function output(text) { + var out; + if (options.out_same_file && filename) + options.output = filename; + if (options.output === true) { + out = process.stdout; + } else { + out = fs.createWriteStream(options.output, { + flags: "w", + encoding: "utf8", + mode: 0644 + }); + } + out.write(text.replace(/;*$/, ";")); + if (options.output !== true) { + out.end(); + } +}; + +// --------- main ends here. + +function show_copyright(comments) { + var ret = ""; + for (var i = 0; i < comments.length; ++i) { + var c = comments[i]; + if (c.type == "comment1") { + ret += "//" + c.value + "\n"; + } else { + ret += "/*" + c.value + "*/"; + } + } + return ret; +}; + +function squeeze_it(code) { + var result = ""; + if (options.show_copyright) { + var tok = jsp.tokenizer(code), c; + c = tok(); + result += show_copyright(c.comments_before); + } + try { + var ast = time_it("parse", function(){ return jsp.parse(code); }); + if (options.lift_vars) { + ast = time_it("lift", function(){ return pro.ast_lift_variables(ast); }); + } + if (options.mangle) ast = time_it("mangle", function(){ + return pro.ast_mangle(ast, { + toplevel : options.mangle_toplevel, + defines : options.defines, + except : options.reserved_names, + no_functions : options.no_mangle_functions + }); + }); + if (options.squeeze) ast = time_it("squeeze", function(){ + ast = pro.ast_squeeze(ast, { + make_seqs : options.make_seqs, + dead_code : options.dead_code, + keep_comps : !options.unsafe + }); + if (options.unsafe) + ast = pro.ast_squeeze_more(ast); + return ast; + }); + if (options.ast) + return sys.inspect(ast, null, null); + result += time_it("generate", function(){ return pro.gen_code(ast, options.codegen_options) }); + if (!options.codegen_options.beautify && options.max_line_length) { + result = time_it("split", function(){ return pro.split_lines(result, options.max_line_length) }); + } + return result; + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + process.exit(1); + } +}; + +function time_it(name, cont) { + if (!options.verbose) + return cont(); + var t1 = new Date().getTime(); + try { return cont(); } + finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } +}; diff --git a/packages/modules/node_modules/async/LICENSE b/packages/modules/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/modules/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/modules/node_modules/async/Makefile b/packages/modules/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/modules/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/modules/node_modules/async/README.md b/packages/modules/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/modules/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/modules/node_modules/async/deps/nodeunit.css b/packages/modules/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/modules/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/modules/node_modules/async/deps/nodeunit.js b/packages/modules/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/modules/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/modules/node_modules/async/index.js b/packages/modules/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/modules/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/modules/node_modules/async/lib/async.js b/packages/modules/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/modules/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/modules/node_modules/async/nodelint.cfg b/packages/modules/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/modules/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/modules/node_modules/async/package.json b/packages/modules/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/modules/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/modules/node_modules/async/test/test-async.js b/packages/modules/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/modules/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/modules/node_modules/async/test/test.html b/packages/modules/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/modules/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/modules/node_modules/kanso-utils/attachments.js b/packages/modules/node_modules/kanso-utils/attachments.js new file mode 100644 index 0000000..330cc45 --- /dev/null +++ b/packages/modules/node_modules/kanso-utils/attachments.js @@ -0,0 +1,116 @@ +/** + * Functions related to the loading and manipulation of attachments in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + mime = require('mime'), + async = require('async'), + fs = require('fs'); + + +/** + * + * @param {Object} doc + * @param {String} path + * @param {Buffer} content + * @returns {Object} + */ + +exports.add = function (doc, ddoc_path, original_path, content) { + if (!doc._attachments) { + doc._attachments = {}; + } + doc._attachments[ddoc_path] = { + 'content_type': mime.lookup(original_path), + 'data': content.toString('base64'), + // custom addition removed in cleanup postprocessor + '_original_path': original_path + }; + return doc; +}; + + +/** + * Searchs a path for attachments, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a file or directory + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads an attachment file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + exports.add(doc, rel, p, content); + callback() + }); +}; + + +/** + * Find all attachments below or at a given path, recursing through + * subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for attachments. This function omits + * hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + return true; + }; +}; diff --git a/packages/modules/node_modules/kanso-utils/index.js b/packages/modules/node_modules/kanso-utils/index.js new file mode 100644 index 0000000..0b79a79 --- /dev/null +++ b/packages/modules/node_modules/kanso-utils/index.js @@ -0,0 +1,5 @@ +module.exports = { + attachments: require('./attachments'), + modules: require('./modules'), + utils: require('./utils') +}; diff --git a/packages/modules/node_modules/kanso-utils/modules.js b/packages/modules/node_modules/kanso-utils/modules.js new file mode 100644 index 0000000..4324d02 --- /dev/null +++ b/packages/modules/node_modules/kanso-utils/modules.js @@ -0,0 +1,289 @@ +/** + * Functions related to the loading and manipulation of CommonJS Modules in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + async = require('async'), + path = require('path'), + fs = require('fs'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +// As modules are added, their original file paths are added to this object +// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...} +exports.originalPaths = {}; + + +/** + * Add the module source to the document in the correct location for requiring + * server-side, then add the path to the _modules property for use by the + * modules plugin postprocessor (when creating the kanso.js attachment) + * + * Returns the updated document. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.add = function (doc, path, src) { + var curr = utils.getPropertyPath(doc, path, true); + if (curr !== undefined) { + var paths = utils.getPropertyPaths(path, curr); + throw new Error( + 'Adding ' + path + ' would overwrite:\n' + + ' ' + paths.join('\n ') + '\n' + + '\n' + + 'This error often occurs because there is a module with the\n' + + 'same name as a directory containing modules. There is no way\n' + + 'to map this structure in the design doc.\n' + ); + } + utils.setPropertyPath(doc, path, src); + if (!doc._modules) { + doc._modules = {}; + } + doc._modules[path] = null; + return doc; +}; + + +/** + * Wraps module source code with useful comments and module cache boilerplate + * code. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.wrap = function (path, src) { + return '/********** ' + path + ' **********/\n\n' + + 'kanso.moduleCache["' + path.replace('"', '\\"') + '"] = ' + + '{load: (function (module, exports, require) {\n\n' + src + '\n\n})};' + + '\n\n'; +}; + + +/** + * Searchs a path for commonjs modules, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a module file or directory of modules + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads a module file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + var module_path = rel.replace(/\.js$/, ''); + var src = content.toString(); + exports.add(doc, module_path, src); + utils.setPropertyPath(exports.originalPaths, rel, p); + callback() + }); +}; + + +/** + * Find all modules below or at a given path, recursing through subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for module files. This function tests + * for a .js extension and omits hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + // should have a .js extension + if (!/\.js$/.test(f)) { + return false; + } + return true; + }; +}; + + +/** + * Parses the exports.originalPaths object to return an array of filenames + */ + +exports.getFilenames = function (obj) { + var names = []; + for (var k in obj) { + if (typeof obj[k] === 'object') { + names.concat(exports.getFilenames(obj[k]).map(function (n) { + return k + '/' + n; + })); + } + else { + names.push(k); + } + } + return names; +}; + + +/** + * Loads a commonjs module from the loaded design document, returning + * the exported properties. The current_dir and target parameters are not the + * path of the module on the filesystem, but rather the path of the module + * within couchdb, root ('/') being the design doc itself. + * + * @param {Object} module_cache + * @param {Object} doc + * @param {String} current_dir + * @param {String} target + * @param {Object} context - optional, extends sandbox object + */ + +exports.require = function (module_cache, doc, current, target, context) { + var current_dir = path.dirname(current); + if (target.charAt(0) !== '.') { + current_dir = '/'; + } + var p = path.normalize(path.join(current_dir, target)); + if (module_cache[p]) { + return module_cache[p]; + } + + var nodes = p.split('/').slice(1); + var content = nodes.reduce(function (a, x) { + if (a[x] === undefined) { + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ') - ' + + 'Module not found' + ); + } + a = a[x]; + return a; + }, doc); + + var filename = utils.getPropertyPath( + exports.originalPaths, p.substr(1), true + ); + + // if you attempt to require + if (typeof filename === 'object') { + var filenames = exports.getFilenames(filename); + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ')\n\n' + + 'It\'s not possible to require directories of modules in CouchDB,\n' + + 'you have to specify one of the following sub-modules directly:\n' + + filenames.map(function (f) { + return ' ' + p.replace(/^\//, '') + '/' + f; + }).join('\n') + '\n' + ); + } + + var module = { + id: p.substr(1), + exports: {}, + // TODO: this property is not provided by couchdb, but is by node: + //filename: filename, + // TODO: this property is not provided by couchdb, but is by node: + //require: async.apply(exports.require, module_cache, doc, p) + // TODO: module properties provided by couchdb, but not by kanso + // * current + // * parent + }; + var sandbox = { + module: module, + exports: module.exports, + //require: module.require, + require: async.apply(exports.require, module_cache, doc, p), + log: function () { + console.log.apply(console, arguments); + } + }; + + // copy context into sandbox + if (context) { + Object.keys(context).forEach(function (k) { + sandbox[k] = context[k]; + }); + } + + // Create a placeholder for this module's exports so circular requires + // are possible. TODO: node.js uses a loaded = false attribute on the + // cached module object to mark this as a placeholder. + module_cache[p] = {}; + + try { + var s = new Script(content, filename).runInNewContext(sandbox); + } + catch (e) { + if (e instanceof SyntaxError && filename) { + // gives a better syntax error than runInNewContext + // with filename and line number + require(filename); + } + if (!e.got_filename) { + e.message = 'Error loading: ' + filename + '\n' + e.message; + e.got_filename = true; + } + throw e; + } + module_cache[p] = sandbox.module.exports; + return module_cache[p]; +}; diff --git a/packages/modules/node_modules/kanso-utils/package.json b/packages/modules/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/modules/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/modules/node_modules/kanso-utils/utils.js b/packages/modules/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/modules/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; diff --git a/packages/modules/node_modules/mime/LICENSE b/packages/modules/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/modules/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/modules/node_modules/mime/README.md b/packages/modules/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/modules/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/modules/node_modules/mime/mime.js b/packages/modules/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/modules/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/modules/node_modules/mime/package.json b/packages/modules/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/modules/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/modules/node_modules/mime/test.js b/packages/modules/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/modules/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/modules/node_modules/mime/types/mime.types b/packages/modules/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/modules/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/modules/node_modules/mime/types/node.types b/packages/modules/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/modules/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/modules/node_modules/uglify-js/.npmignore b/packages/modules/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..d97eaa0 --- /dev/null +++ b/packages/modules/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/packages/modules/node_modules/uglify-js/README.html b/packages/modules/node_modules/uglify-js/README.html new file mode 100644 index 0000000..5f37ac0 --- /dev/null +++ b/packages/modules/node_modules/uglify-js/README.html @@ -0,0 +1,981 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
+ +
+ +
+

UglifyJS – a JavaScript parser/compressor/beautifier

+ + +
+ +
+

1 UglifyJS — a JavaScript parser/compressor/beautifier

+
+ + +

+This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

+

+The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

+

+( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

+

+The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

+
    +
  • ability to re-generate JavaScript code from the AST. Optionally + indented—you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +
  • +
  • shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with eval() calls or with{} statements. In short, if eval() or + with{} are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +
  • +
  • various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + +
      +
    • foo["bar"] ==> foo.bar + +
    • +
    • remove block brackets {} + +
    • +
    • join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + +
    • +
    • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + +
    • +
    • consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + +
    • +
    • various optimizations for IF statements: + +
        +
      • if (foo) bar(); else baz(); ==> foo?bar():baz(); +
      • +
      • if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
      • +
      • if (foo) bar(); ==> foo&&bar(); +
      • +
      • if (!foo) bar(); ==> foo||bar(); +
      • +
      • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
      • +
      • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
      • +
      + +
    • +
    • remove some unreachable code and warn about it (code that follows a + return, throw, break or continue statement, except + function/variable declarations). + +
    • +
    • act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. +
    • +
    + +
  • +
+ + + +
+ +
+

1.1 Unsafe transformations

+
+ + +

+The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

+ +
+ +
+

1.1.1 Calls involving the global Array constructor

+
+ + +

+The following transformations occur: +

+ + + +
new Array(1, 2, 3, 4)  => [1,2,3,4]
+Array(a, b, c)         => [a,b,c]
+new Array(5)           => Array(5)
+new Array(a)           => Array(a)
+
+ + +

+These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

+

+UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

+ + + +
// case 1.  globally declared variable
+  var Array;
+  new Array(1, 2, 3);
+  Array(a, b);
+
+  // or (can be declared later)
+  new Array(1, 2, 3);
+  var Array;
+
+  // or (can be a function)
+  new Array(1, 2, 3);
+  function Array() { ... }
+
+// case 2.  declared in a function
+  (function(){
+    a = new Array(1, 2, 3);
+    b = Array(5, 6);
+    var Array;
+  })();
+
+  // or
+  (function(Array){
+    return Array(5, 6, 7);
+  })();
+
+  // or
+  (function(){
+    return new Array(1, 2, 3, 4);
+    function Array() { ... }
+  })();
+
+  // etc.
+
+ + +
+ +
+ +
+

1.1.2 obj.toString() ==> obj+“”

+
+ + +
+
+ +
+ +
+

1.2 Install (NPM)

+
+ + +

+UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

+
+ +
+ +
+

1.3 Install latest code from GitHub

+
+ + + + + +
## clone the repository
+mkdir -p /where/you/wanna/put/it
+cd /where/you/wanna/put/it
+git clone git://github.com/mishoo/UglifyJS.git
+
+## make the module available to Node
+mkdir -p ~/.node_libraries/
+cd ~/.node_libraries/
+ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
+
+## and if you want the CLI script too:
+mkdir -p ~/bin
+cd ~/bin
+ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
+  # (then add ~/bin to your $PATH if it's not there already)
+
+ + +
+ +
+ +
+

1.4 Usage

+
+ + +

+There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

+ + + +
uglifyjs [ options... ] [ filename ]
+
+ + +

+filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

+

+Supported options: +

+
    +
  • -b or --beautify — output indented code; when passed, additional + options control the beautifier: + +
      +
    • -i N or --indent N — indentation level (number of spaces) + +
    • +
    • -q or --quote-keys — quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +
    • +
    + +
  • +
  • --ascii — pass this argument to encode non-ASCII characters as + \uXXXX sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +
  • +
  • -nm or --no-mangle — don't mangle names. + +
  • +
  • -nmf or --no-mangle-functions – in case you want to mangle variable + names, but not touch function names. + +
  • +
  • -ns or --no-squeeze — don't call ast_squeeze() (which does various + optimizations that result in smaller, less readable code). + +
  • +
  • -mt or --mangle-toplevel — mangle names in the toplevel scope too + (by default we don't do this). + +
  • +
  • --no-seqs — when ast_squeeze() is called (thus, unless you pass + --no-squeeze) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass --no-seqs to disable it. + +
  • +
  • --no-dead-code — by default, UglifyJS will remove code that is + obviously unreachable (code that follows a return, throw, break or + continue statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +
  • +
  • -nc or --no-copyright — by default, uglifyjs will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +
  • +
  • -o filename or --output filename — put the result in filename. If + this isn't given, the result goes to standard output (or see next one). + +
  • +
  • --overwrite — if the code is read from a file (not from STDIN) and you + pass --overwrite then the output will be written in the same file. + +
  • +
  • --ast — pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +
  • +
  • -v or --verbose — output some notes on STDERR (for now just how long + each operation takes). + +
  • +
  • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value true, or you can specify a numeric value (such as + 1024), a quoted string value (such as ="object"= or + ='https://github.com'), or the name of another symbol or keyword (such as =null or document). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of conditional compilation + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + --define-from-module more suitable for use. + +
  • +
  • -define-from-module SOMEMODULE — will load the named module (as + per the NodeJS require() function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the --define option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of --define + options. + +
  • +
  • --unsafe — enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + +
      +
    • foo.toString() ==> foo+"" +
    • +
    • new Array(x,…) ==> [x,…] +
    • +
    • new Array(x) ==> Array(x) + +
    • +
    + +
  • +
  • --max-line-len (default 32K characters) — add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass –max-line-len 0 to disable this + safety feature. + +
  • +
  • --reserved-names — some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names require and $super + intact you'd specify –reserved-names "require,$super". + +
  • +
  • --inline-script – when you want to include the output literally in an + HTML <script> tag you can use this option to prevent </script from + showing up in the output. + +
  • +
  • --lift-vars – when you pass this, UglifyJS will apply the following + transformations (see the notes in API, ast_lift_variables): + +
      +
    • put all var declarations at the start of the scope +
    • +
    • make sure a variable is declared only once +
    • +
    • discard unused function arguments +
    • +
    • discard unused inner (named) functions +
    • +
    • finally, try to merge assignments into that one var declaration, if + possible. +
    • +
    + +
  • +
+ + + +
+ +
+

1.4.1 API

+
+ + +

+To use the library from JavaScript, you'd do the following (example for +NodeJS): +

+ + + +
var jsp = require("uglify-js").parser;
+var pro = require("uglify-js").uglify;
+
+var orig_code = "... JS code here";
+var ast = jsp.parse(orig_code); // parse code and get the initial AST
+ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+var final_code = pro.gen_code(ast); // compressed code here
+
+ + +

+The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

+

+Some of these functions take optional arguments. Here's a description: +

+
    +
  • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. + strict_semicolons is optional and defaults to false. If you pass + true then the parser will throw an error when it expects a semicolon and + it doesn't find it. For most JS code you don't want that, but it's useful + if you want to strictly sanitize your code. + +
  • +
  • pro.ast_lift_variables(ast) – merge and move var declarations to the + scop of the scope; discard unused function arguments or variables; discard + unused (named) inner functions. It also tries to merge assignments + following the var declaration into it. + +

    + If your code is very hand-optimized concerning var declarations, this + lifting variable declarations might actually increase size. For me it + helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also + note that (since it's not enabled by default) this operation isn't yet + heavily tested (please report if you find issues!). +

    +

    + Note that although it might increase the image size (on jQuery it gains + 865 bytes, 243 after gzip) it's technically more correct: in certain + situations, dead code removal might drop variable declarations, which + would not happen if the variables are lifted in advance. +

    +

    + Here's an example of what it does: +

  • +
+ + + + + +
function f(a, b, c, d, e) {
+    var q;
+    var w;
+    w = 10;
+    q = 20;
+    for (var i = 1; i < 10; ++i) {
+        var boo = foo(a);
+    }
+    for (var i = 0; i < 1; ++i) {
+        var boo = bar(c);
+    }
+    function foo(){ ... }
+    function bar(){ ... }
+    function baz(){ ... }
+}
+
+// transforms into ==>
+
+function f(a, b, c) {
+    var i, boo, w = 10, q = 20;
+    for (i = 1; i < 10; ++i) {
+        boo = foo(a);
+    }
+    for (i = 0; i < 1; ++i) {
+        boo = bar(c);
+    }
+    function foo() { ... }
+    function bar() { ... }
+}
+
+ + +
    +
  • pro.ast_mangle(ast, options) – generates a new AST containing mangled + (compressed) variable and function names. It supports the following + options: + +
      +
    • toplevel – mangle toplevel names (by default we don't touch them). +
    • +
    • except – an array of names to exclude from compression. +
    • +
    • defines – an object with properties named after symbols to + replace (see the --define option for the script) and the values + representing the AST replacement value. + +
    • +
    + +
  • +
  • pro.ast_squeeze(ast, options) – employs further optimizations designed + to reduce the size of the code that gen_code would generate from the + AST. Returns a new AST. options can be a hash; the supported options + are: + +
      +
    • make_seqs (default true) which will cause consecutive statements in a + block to be merged using the "sequence" (comma) operator + +
    • +
    • dead_code (default true) which will remove unreachable code. + +
    • +
    + +
  • +
  • pro.gen_code(ast, options) – generates JS code from the AST. By + default it's minified, but using the options argument you can get nicely + formatted output. options is, well, optional :-) and if you pass it it + must be an object and supports the following properties (below you can see + the default values): + +
      +
    • beautify: false – pass true if you want indented output +
    • +
    • indent_start: 0 (only applies when beautify is true) – initial + indentation in spaces +
    • +
    • indent_level: 4 (only applies when beautify is true) -- + indentation level, in spaces (pass an even number) +
    • +
    • quote_keys: false – if you pass true it will quote all keys in + literal objects +
    • +
    • space_colon: false (only applies when beautify is true) – wether + to put a space before the colon in object literals +
    • +
    • ascii_only: false – pass true if you want to encode non-ASCII + characters as \uXXXX. +
    • +
    • inline_script: false – pass true to escape occurrences of + </script in strings +
    • +
    + +
  • +
+ + +
+ +
+ +
+

1.4.2 Beautifier shortcoming – no more comments

+
+ + +

+The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

+

+In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

+
+ +
+ +
+

1.4.3 Use as a code pre-processor

+
+ + +

+The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

+

+The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

+ + + +
CLAUSE1: if (typeof DEVMODE === 'undefined') {
+    DEVMODE = true;
+}
+
+CLAUSE2: function init() {
+    if (DEVMODE) {
+        console.log("init() called");
+    }
+    ....
+    DEVMODE &amp;&amp; console.log("init() complete");
+}
+
+CLAUSE3: function reportDeviceStatus(device) {
+    var DEVMODE = device.mode, DEVNAME = device.name;
+    if (DEVMODE === 'open') {
+        ....
+    }
+}
+
+ + +

+When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

+

+If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

+

+And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

+

+In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

+

+It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

+
+
+ +
+ +
+

1.5 Compression – how good is it?

+
+ + +

+Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

+

+We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

+ + ++ + + + + + + + + + +
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
+ + +
+ +
+ +
+

1.6 Bugs?

+
+ + +

+Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

+

+DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

+

+Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

+
+ +
+ +
+

1.7 Links

+
+ + + + + +
+ +
+ +
+

1.8 License

+
+ + +

+UglifyJS is released under the BSD license: +

+ + + +
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above
+      copyright notice, this list of conditions and the following
+      disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+ + +
+

Footnotes:

+
+

1 I even reported a few bugs and suggested some fixes in the original + parse-js library, and Marijn pushed fixes literally in minutes. +

+
+
+ +
+
+
+ +
+

Date: 2011-12-09 14:59:08 EET

+

Author: Mihai Bazon

+

Org version 7.7 with Emacs version 23

+Validate XHTML 1.0 + +
+ + diff --git a/packages/modules/node_modules/uglify-js/README.org b/packages/modules/node_modules/uglify-js/README.org new file mode 100644 index 0000000..4d01fdf --- /dev/null +++ b/packages/modules/node_modules/uglify-js/README.org @@ -0,0 +1,574 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML = + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css b/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js b/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/index.js b/packages/properties/node_modules/kanso-utils/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/lib/async.js b/packages/properties/node_modules/kanso-utils/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/nodelint.cfg b/packages/properties/node_modules/kanso-utils/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/package.json b/packages/properties/node_modules/kanso-utils/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/test/test-async.js b/packages/properties/node_modules/kanso-utils/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/properties/node_modules/kanso-utils/node_modules/async/test/test.html b/packages/properties/node_modules/kanso-utils/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/LICENSE b/packages/properties/node_modules/kanso-utils/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/properties/node_modules/kanso-utils/node_modules/mime/README.md b/packages/properties/node_modules/kanso-utils/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/mime.js b/packages/properties/node_modules/kanso-utils/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/package.json b/packages/properties/node_modules/kanso-utils/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/test.js b/packages/properties/node_modules/kanso-utils/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/types/mime.types b/packages/properties/node_modules/kanso-utils/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/properties/node_modules/kanso-utils/node_modules/mime/types/node.types b/packages/properties/node_modules/kanso-utils/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/properties/node_modules/kanso-utils/package.json b/packages/properties/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/properties/node_modules/kanso-utils/utils.js b/packages/properties/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/properties/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; diff --git a/packages/properties/node_modules/underscore/.npmignore b/packages/properties/node_modules/underscore/.npmignore new file mode 100644 index 0000000..2ce2684 --- /dev/null +++ b/packages/properties/node_modules/underscore/.npmignore @@ -0,0 +1,3 @@ +test/ +Rakefile +docs/ \ No newline at end of file diff --git a/packages/properties/node_modules/underscore/LICENSE b/packages/properties/node_modules/underscore/LICENSE new file mode 100644 index 0000000..58c73b9 --- /dev/null +++ b/packages/properties/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Jeremy Ashkenas, DocumentCloud + +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. \ No newline at end of file diff --git a/packages/properties/node_modules/underscore/README b/packages/properties/node_modules/underscore/README new file mode 100644 index 0000000..408145a --- /dev/null +++ b/packages/properties/node_modules/underscore/README @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ +/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ +\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://documentcloud.github.com/underscore/ + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/packages/properties/node_modules/underscore/index.html b/packages/properties/node_modules/underscore/index.html new file mode 100644 index 0000000..7453112 --- /dev/null +++ b/packages/properties/node_modules/underscore/index.html @@ -0,0 +1,1777 @@ + + + + + + Underscore.js + + + + +
+ +

Underscore.js

+ +

+ Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux. +

+ +

+ Underscore provides 60-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

+ +

+ A complete Test & Benchmark Suite + is included for your perusal. +

+ +

+ You may also read through the annotated source code. +

+ +

+ The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

+ +

+ Underscore is an open-source component of DocumentCloud. +

+ +

Downloads (Right-click, and use "Save As")

+ + + + + + + + + + +
Development Version (1.2.3)34kb, Uncompressed with Comments
Production Version (1.2.3)< 4kb, Minified and Gzipped
+ +

Table of Contents

+ + Object-Oriented and Functional Styles + +

+ Collections +
+ each, map, + reduce, reduceRight, + find, filter, + reject, all, + any, include, + invoke, pluck, + max, min, + sortBy, groupBy, + sortedIndex, shuffle, + toArray, size +

+ +

+ Arrays +
+ first, initial, last, rest, + compact, flatten, without, + union, intersection, difference, + uniq, zip, indexOf, + lastIndexOf, range +

+ +

+ Functions +
+ bind, bindAll, + memoize, delay, defer, + throttle, debounce, + once, after, wrap, compose +

+ +

+ Objects +
+ keys, values, + functions, extend, defaults, clone, tap, + isEqual, isEmpty, isElement, + isArray, isArguments, isFunction, isString, + isNumber, isBoolean, isDate, isRegExp, + isNaN, isNull, + isUndefined + +

+ +

+ Utility +
+ noConflict, + identity, times, + mixin, uniqueId, + escape, template +

+ +

+ Chaining +
+ chain, value +

+ +
+ +

Object-Oriented and Functional Styles

+ +

+ You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

+ +
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });
+ +

+ Using the object-oriented style allows you to chain together methods. Calling + chain on a wrapped object will cause all future method calls to + return wrapped objects as well. When you've finished the computation, + use value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

+ +
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_(lyrics).chain()
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+}, {}).value();
+
+=> {lumberjack : 2, all : 4, night : 2 ... }
+ +

+ In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

+ +

Collection Functions (Arrays or Objects)

+ +

+ each_.each(list, iterator, [context]) + Alias: forEach +
+ Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

+
+_.each([1, 2, 3], function(num){ alert(num); });
+=> alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
+=> alerts each number in turn...
+ +

+ map_.map(list, iterator, [context]) +
+ Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

+
+_.map([1, 2, 3], function(num){ return num * 3; });
+=> [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=> [3, 6, 9]
+ +

+ reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
+ Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. +

+
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=> 6
+
+ +

+ reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
+ The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

+
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=> [4, 5, 2, 3, 0, 1]
+
+ +

+ find_.find(list, iterator, [context]) + Alias: detect +
+ Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

+
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> 2
+
+ +

+ filter_.filter(list, iterator, [context]) + Alias: select +
+ Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

+
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [2, 4, 6]
+
+ +

+ reject_.reject(list, iterator, [context]) +
+ Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

+
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [1, 3, 5]
+
+ +

+ all_.all(list, iterator, [context]) + Alias: every +
+ Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

+
+_.all([true, 1, null, 'yes'], _.identity);
+=> false
+
+ +

+ any_.any(list, [iterator], [context]) + Alias: some +
+ Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

+
+_.any([null, 0, 'yes', false]);
+=> true
+
+ +

+ include_.include(list, value) + Alias: contains +
+ Returns true if the value is present in the list, using + === to test equality. Uses indexOf internally, if list + is an Array. +

+
+_.include([1, 2, 3], 3);
+=> true
+
+ +

+ invoke_.invoke(list, methodName, [*arguments]) +
+ Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

+
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=> [[1, 5, 7], [1, 2, 3]]
+
+ +

+ pluck_.pluck(list, propertyName) +
+ A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=> ["moe", "larry", "curly"]
+
+ +

+ max_.max(list, [iterator], [context]) +
+ Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=> {name : 'curly', age : 60};
+
+ +

+ min_.min(list, [iterator], [context]) +
+ Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

+
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=> 2
+
+ +

+ sortBy_.sortBy(list, iterator, [context]) +
+ Returns a sorted copy of list, ranked by the results of running + each value through iterator. +

+
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=> [5, 4, 6, 3, 1, 2]
+
+ +

+ groupBy_.groupBy(list, iterator) +
+ Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

+
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=> {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=> {3: ["one", "two"], 5: ["three"]}
+
+ +

+ sortedIndex_.sortedIndex(list, value, [iterator]) +
+ Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value. +

+
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=> 3
+
+ +

+ shuffle_.shuffle(list) +
+ Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

+
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=> [4, 1, 6, 3, 5, 2]
+
+ +

+ toArray_.toArray(list) +
+ Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

+
+(function(){ return _.toArray(arguments).slice(0); })(1, 2, 3);
+=> [1, 2, 3]
+
+ +

+ size_.size(list) +
+ Return the number of values in the list. +

+
+_.size({one : 1, two : 2, three : 3});
+=> 3
+
+ +

Array Functions

+ +

+ Note: All array functions will also work on the arguments object. +

+ +

+ first_.first(array, [n]) + Alias: head +
+ Returns the first element of an array. Passing n will + return the first n elements of the array. +

+
+_.first([5, 4, 3, 2, 1]);
+=> 5
+
+ +

+ initial_.initial(array, [n]) +
+ Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

+
+_.initial([5, 4, 3, 2, 1]);
+=> [5, 4, 3, 2]
+
+ +

+ last_.last(array, [n]) +
+ Returns the last element of an array. Passing n will return + the last n elements of the array. +

+
+_.last([5, 4, 3, 2, 1]);
+=> 1
+
+ +

+ rest_.rest(array, [index]) + Alias: tail +
+ Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

+
+_.rest([5, 4, 3, 2, 1]);
+=> [4, 3, 2, 1]
+
+ +

+ compact_.compact(array) +
+ Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

+
+_.compact([0, 1, false, 2, '', 3]);
+=> [1, 2, 3]
+
+ +

+ flatten_.flatten(array) +
+ Flattens a nested array (the nesting can be to any depth). +

+
+_.flatten([1, [2], [3, [[[4]]]]]);
+=> [1, 2, 3, 4];
+
+ +

+ without_.without(array, [*values]) +
+ Returns a copy of the array with all instances of the values + removed. === is used for the equality test. +

+
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=> [2, 3, 4]
+
+ +

+ union_.union(*arrays) +
+ Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

+
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2, 3, 101, 10]
+
+ +

+ intersection_.intersection(*arrays) +
+ Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

+
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=> [1, 2]
+
+ +

+ difference_.difference(array, *others) +
+ Similar to without, but returns the values from array that + are not present in the other arrays. +

+
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=> [1, 3, 4]
+
+ +

+ uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
+ Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

+
+_.uniq([1, 2, 1, 3, 1, 4]);
+=> [1, 2, 3, 4]
+
+ +

+ zip_.zip(*arrays) +
+ Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

+
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+
+ +

+ indexOf_.indexOf(array, value, [isSorted]) +
+ Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search. +

+
+_.indexOf([1, 2, 3], 2);
+=> 1
+
+ +

+ lastIndexOf_.lastIndexOf(array, value) +
+ Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. +

+
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=> 4
+
+ +

+ range_.range([start], stop, [step]) +
+ A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

+
+_.range(10);
+=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=> [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=> []
+
+ +

Function (uh, ahem) Functions

+ +

+ bind_.bind(function, object, [*arguments]) +
+ Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, bind arguments to the function to pre-fill them, + also known as currying. +

+
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=> 'hi: moe'
+
+ +

+ bindAll_.bindAll(object, [*methodNames]) +
+ Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

+
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=> When the button is clicked, this.label will have the correct value...
+
+ +

+ memoize_.memoize(function, [hashFunction]) +
+ Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

+
+var fibonacci = _.memoize(function(n) {
+  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+
+ +

+ delay_.delay(function, wait, [*arguments]) +
+ Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

+
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=> 'logged later' // Appears after one second.
+
+ +

+ defer_.defer(function) +
+ Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. +

+
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+
+ +

+ throttle_.throttle(function, wait) +
+ Returns a throttled version of the function, that, when invoked repeatedly, + will only actually call the wrapped function at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

+
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+
+ +

+ debounce_.debounce(function, wait) +
+ Calling a debounced function will postpone its execution until after + wait milliseconds have elapsed since the last time the function + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized... +

+
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+
+ +

+ once_.once(function) +
+ Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

+
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+
+ +

+ after_.after(count, function) +
+ Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

+
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes}); 
+});
+// renderNotes is run once, after all notes have saved.
+
+ +

+ wrap_.wrap(function, wrapper) +
+ Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

+
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=> 'before, hello: moe, after'
+
+ +

+ compose_.compose(*functions) +
+ Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

+
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=> 'hi: moe!'
+
+ +

Object Functions

+ +

+ keys_.keys(object) +
+ Retrieve all the names of the object's properties. +

+
+_.keys({one : 1, two : 2, three : 3});
+=> ["one", "two", "three"]
+
+ +

+ values_.values(object) +
+ Return all of the values of the object's properties. +

+
+_.values({one : 1, two : 2, three : 3});
+=> [1, 2, 3]
+
+ +

+ functions_.functions(object) + Alias: methods +
+ Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

+
+_.functions(_);
+=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+
+ +

+ extend_.extend(destination, *sources) +
+ Copy all of the properties in the source objects over to the + destination object. It's in-order, so the last source will override + properties of the same name in previous arguments. +

+
+_.extend({name : 'moe'}, {age : 50});
+=> {name : 'moe', age : 50}
+
+ +

+ defaults_.defaults(object, *defaults) +
+ Fill in missing properties in object with default values from the + defaults objects. As soon as the property is filled, further defaults + will have no effect. +

+
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=> {flavor : "chocolate", sprinkles : "lots"}
+
+ +

+ clone_.clone(object) +
+ Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

+
+_.clone({name : 'moe'});
+=> {name : 'moe'};
+
+ +

+ tap_.tap(object, interceptor) +
+ Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

+
+_([1,2,3,200]).chain().
+  filter(function(num) { return num % 2 == 0; }).
+  tap(console.log).
+  map(function(num) { return num * num }).
+  value();
+=> [2, 200]
+=> [4, 40000]
+
+ +

+ isEqual_.isEqual(object, other) +
+ Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

+
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=> false
+_.isEqual(moe, clone);
+=> true
+
+ +

+ isEmpty_.isEmpty(object) +
+ Returns true if object contains no values. +

+
+_.isEmpty([1, 2, 3]);
+=> false
+_.isEmpty({});
+=> true
+
+ +

+ isElement_.isElement(object) +
+ Returns true if object is a DOM element. +

+
+_.isElement(jQuery('body')[0]);
+=> true
+
+ +

+ isArray_.isArray(object) +
+ Returns true if object is an Array. +

+
+(function(){ return _.isArray(arguments); })();
+=> false
+_.isArray([1,2,3]);
+=> true
+
+ +

+ isArguments_.isArguments(object) +
+ Returns true if object is an Arguments object. +

+
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=> true
+_.isArguments([1,2,3]);
+=> false
+
+ +

+ isFunction_.isFunction(object) +
+ Returns true if object is a Function. +

+
+_.isFunction(alert);
+=> true
+
+ +

+ isString_.isString(object) +
+ Returns true if object is a String. +

+
+_.isString("moe");
+=> true
+
+ +

+ isNumber_.isNumber(object) +
+ Returns true if object is a Number. +

+
+_.isNumber(8.4 * 5);
+=> true
+
+ +

+ isBoolean_.isBoolean(object) +
+ Returns true if object is either true or false. +

+
+_.isBoolean(null);
+=> false
+
+ +

+ isDate_.isDate(object) +
+ Returns true if object is a Date. +

+
+_.isDate(new Date());
+=> true
+
+ +

+ isRegExp_.isRegExp(object) +
+ Returns true if object is a RegExp. +

+
+_.isRegExp(/moe/);
+=> true
+
+ +

+ isNaN_.isNaN(object) +
+ Returns true if object is NaN.
Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

+
+_.isNaN(NaN);
+=> true
+isNaN(undefined);
+=> true
+_.isNaN(undefined);
+=> false
+
+ +

+ isNull_.isNull(object) +
+ Returns true if the value of object is null. +

+
+_.isNull(null);
+=> true
+_.isNull(undefined);
+=> false
+
+ +

+ isUndefined_.isUndefined(variable) +
+ Returns true if variable is undefined. +

+
+_.isUndefined(window.missingVariable);
+=> true
+
+ +

Utility Functions

+ +

+ noConflict_.noConflict() +
+ Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

+
+var underscore = _.noConflict();
+ +

+ identity_.identity(value) +
+ Returns the same value that is used as the argument. In math: + f(x) = x
+ This function looks useless, but is used throughout Underscore as + a default iterator. +

+
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=> true
+ +

+ times_.times(n, iterator) +
+ Invokes the given iterator function n times. +

+
+_(3).times(function(){ genie.grantWish(); });
+ +

+ mixin_.mixin(object) +
+ Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

+
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=> "Fabio"
+
+ +

+ uniqueId_.uniqueId([prefix]) +
+ Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. +

+
+_.uniqueId('contact_');
+=> 'contact_104'
+ +

+ escape_.escape(string) +
+ Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

+
+_.escape('Curly, Larry & Moe');
+=> "Curly, Larry &amp; Moe"
+ +

+ template_.template(templateString, [context]) +
+ Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using
+ <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + context object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the context + object as the second parameter to template in order to render + immediately instead of returning a template function. +

+
+var compiled = _.template("hello: <%= name %>");
+compiled({name : 'moe'});
+=> "hello: moe"
+
+var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=> "<li>moe</li><li>curly</li><li>larry</li>"
+
+var template = _.template("<b><%- value %></b>");
+template({value : '<script>'});
+=> "<b>&lt;script&gt;</b>"
+ +

+ You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

+ +
+var compiled = _.template("<% print('Hello ' + epithet); %>");
+compiled({epithet: "stooge"});
+=> "Hello stooge."
+ +

+ If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex, and an (optional) evaluate regex + to match expressions that should be inserted and evaluated, respectively. + If no evaluate regex is provided, your templates will only be + capable of interpolating values. + For example, to perform + Mustache.js + style templating: +

+ +
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=> "Hello Mustache!"
+ +

Chaining

+ +

+ chain_(obj).chain() +
+ Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. ( + A more realistic example.) +

+
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _(stooges).chain()
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=> "moe is 21"
+
+ +

+ value_(obj).value() +
+ Extracts the value of a wrapped object. +

+
+_([1, 2, 3]).value();
+=> [1, 2, 3]
+
+ +

Links & Suggested Reading

+ +

+ Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

+ +

+ Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays, also + available on GitHub. +

+ +

+ Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

+ +

+ Ruby's Enumerable module. +

+ +

+ Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

+ +

+ Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

+ +

+ Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

+ +

+ Python's itertools. +

+ +

Change Log

+ +

+ 1.2.3Dec. 7, 2011
+

    +
  • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
  • +
  • + Sparse array support of _.indexOf, _.lastIndexOf. +
  • +
  • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
  • +
+

+ +

+ 1.2.2Nov. 14, 2011
+

    +
  • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
  • +
  • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
  • +
  • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
  • +
  • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
  • +
+

+ +

+ 1.2.1Oct. 24, 2011
+

    +
  • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
  • +
  • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
  • +
  • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
  • +
  • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
  • +
  • + Most of the _.is[Type] checks no longer ducktype. +
  • +
  • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
  • +
  • + _.clone no longer wraps non-object types in Objects. +
  • +
  • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
  • +
+

+ +

+ 1.2.0Oct. 5, 2011
+

    +
  • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
  • +
  • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
  • +
  • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
  • +
  • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
  • +
  • + _.last now takes an optional argument which will return the last + N elements of the list. +
  • +
  • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
  • +
+

+ +

+ 1.1.7July 13, 2011
+ Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

+ +

+ 1.1.6April 18, 2011
+ Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

+ +

+ 1.1.5Mar 20, 2011
+ Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

+ +

+ 1.1.4Jan 9, 2011
+ Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

+ +

+ 1.1.3Dec 1, 2010
+ In CommonJS, Underscore may now be required with just:
+ var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

+ +

+ 1.1.2
+ Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

+ +

+ 1.1.1
+ Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

+ +

+ 1.1.0
+ The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

+ +

+ 1.0.4
+ Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

+ +

+ 1.0.3
+ Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

+ +

+ 1.0.2
+ Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

+ +

+ 1.0.1
+ Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

+ +

+ 1.0.0
+ Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

+ +

+ 0.6.0
+ Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

+ +

+ 0.5.8
+ Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

+ +

+ 0.5.7
+ A safer implementation of _.isArguments, and a + faster _.isNumber,
thanks to + Jed Schmidt. +

+ +

+ 0.5.6
+ Customizable delimiters for _.template, contributed by + Noah Sloan. +

+ +

+ 0.5.5
+ Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

+ +

+ 0.5.4
+ Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

+ +

+ 0.5.2
+ New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

+ +

+ 0.5.1
+ Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

+ +

+ 0.5.0
+ [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

+ +

+ 0.4.7
+ Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

+ +

+ 0.4.6
+ Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

+ +

+ 0.4.5
+ Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

+ +

+ 0.4.4
+ Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

+ +

+ 0.4.3
+ Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

+ +

+ 0.4.2
+ Renamed the unwrapping function to value, for clarity. +

+ +

+ 0.4.1
+ Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

+ +

+ 0.4.0
+ All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

+ +

+ 0.3.3
+ Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

+ +

+ 0.3.2
+ Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

+ +

+ 0.3.1
+ All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

+ +

+ 0.3.0
+ Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

+ +

+ 0.2.0
+ Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

+ +

+ 0.1.1
+ Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

+ +

+ 0.1.0
+ Initial release of Underscore.js. +

+ +

+ + A DocumentCloud Project + +

+ +
+ +
+ + + + + + diff --git a/packages/properties/node_modules/underscore/index.js b/packages/properties/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/packages/properties/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/packages/properties/node_modules/underscore/package.json b/packages/properties/node_modules/underscore/package.json new file mode 100644 index 0000000..eda11ad --- /dev/null +++ b/packages/properties/node_modules/underscore/package.json @@ -0,0 +1,12 @@ +{ + "name" : "underscore", + "description" : "JavaScript's functional programming helper library.", + "homepage" : "http://documentcloud.github.com/underscore/", + "keywords" : ["util", "functional", "server", "client", "browser"], + "author" : "Jeremy Ashkenas ", + "contributors" : [], + "dependencies" : [], + "repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"}, + "main" : "underscore.js", + "version" : "1.2.3" +} diff --git a/packages/properties/node_modules/underscore/underscore-min.js b/packages/properties/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..a2a40e4 --- /dev/null +++ b/packages/properties/node_modules/underscore/underscore-min.js @@ -0,0 +1,30 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, +h)&&!f--)break;g=!f}}d.pop();return g}var s=this,F=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.concat,H=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&& +define.amd?define("underscore",function(){return b}):s._=b;b.VERSION="1.2.3";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(x&&a.reduce===x)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(y&&a.reduceRight===y)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g, +c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;D(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.filter===z)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(A&&a.every===A)return a.every(c, +b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var D=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(B&&a.some===B)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=D(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a, +d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex= +function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after= +function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments, +1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a=== +Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)== +"[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),function(c){J(c, +b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g, +"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var u=function(a,c){return c?b(a).chain():a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return u(c.apply(b, +a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped,arguments);return u(this._wrapped,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return u(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/packages/properties/node_modules/underscore/underscore.js b/packages/properties/node_modules/underscore/underscore.js new file mode 100644 index 0000000..b6b2813 --- /dev/null +++ b/packages/properties/node_modules/underscore/underscore.js @@ -0,0 +1,981 @@ +// Underscore.js 1.2.3 +// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // 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 slice = ArrayProto.slice, + concat = ArrayProto.concat, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js** and **"CommonJS"**, with + // backwards-compatibility for the old `require()` API. If we're not in + // CommonJS, add `_` to the global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore', function() { + return _; + }); + } else { + // Exported as a string, for Closure Compiler "advanced" mode. + root['_'] = _; + } + + // Current version. + _.VERSION = '1.2.3'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (method.call ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 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. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // 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, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + 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)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // 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(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // 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 (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // 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(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // 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. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // 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 function() { + var args = concat.apply([func], arguments); + return wrapper.apply(this, args); + }; + }; + + // 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 funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // 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 = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (source[prop] !== void 0) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // 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; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // 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._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (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; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') 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`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (hasOwnProperty.call(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // 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 (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; + return true; + }; + + // 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) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && hasOwnProperty.call(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return 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 a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // 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; + }; + + // 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 iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // 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 + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape, function(match, code) { + return "',_.escape(" + code.replace(/\\'/g, "'") + "),'"; + }) + .replace(c.interpolate, function(match, code) { + return "'," + code.replace(/\\'/g, "'") + ",'"; + }) + .replace(c.evaluate || null, function(match, code) { + return "');" + code.replace(/\\'/g, "'") + .replace(/[\r\n\t]/g, ' ') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // The OOP Wrapper + // --------------- + + // 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. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // 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]; + wrapper.prototype[name] = function() { + method.apply(this._wrapped, arguments); + return result(this._wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/packages/settings/build/add.js b/packages/settings/build/add.js index 9339587..556e010 100644 --- a/packages/settings/build/add.js +++ b/packages/settings/build/add.js @@ -1,37 +1,14 @@ -var modules = require('kanso/modules'); +var utils = require('./utils'); -/** - * Wraps the settings JSON as a CommonJS Module and includes in the document - * so package config is easily available in the CommonJS environment. - */ - -function add_settings(root, doc, settings, name) { - name = name || 'packages/' + settings.name; - var json = JSON.stringify(settings); - var path = 'settings/' + name; - var src = 'module.exports = ' + json + ';'; - modules.add(doc, path, src); - if (root) { - if (doc.settings.root) { - // root settings already defined - throw new Error('Root settings conflict'); - } - modules.add(doc, 'settings/root', 'module.exports = require("' + - path.replace('"', '\\"') + - '");'); - } - return doc; -} module.exports = function (root, path, settings, doc, callback) { - if (!doc.settings) { - doc.settings = {}; - } - if (!doc.settings.packages) { - doc.settings.packages = {}; + if (root) { + // the root settings are added by the post processor + return callback(null, doc); } + utils.prepareDoc(doc); try { - add_settings(root, doc, settings); + utils.addSettings(root, doc, settings); } catch (e) { return callback(e); diff --git a/packages/settings/build/add_root.js b/packages/settings/build/add_root.js new file mode 100644 index 0000000..e7241af --- /dev/null +++ b/packages/settings/build/add_root.js @@ -0,0 +1,13 @@ +var utils = require('./utils'); + + +module.exports = function (root, path, settings, doc, callback) { + utils.prepareDoc(doc); + try { + utils.addSettings(root, doc, settings); + } + catch (e) { + return callback(e); + } + callback(null, doc); +}; diff --git a/packages/settings/build/utils.js b/packages/settings/build/utils.js new file mode 100644 index 0000000..47ce14e --- /dev/null +++ b/packages/settings/build/utils.js @@ -0,0 +1,40 @@ +var modules = require('kanso-utils/modules'); + + +/** + * Ensure expected properties exist on doc + */ + +exports.prepareDoc = function (doc) { + if (!doc.settings) { + doc.settings = {}; + } + if (!doc.settings.packages) { + doc.settings.packages = {}; + } + return doc; +}; + + +/** + * Wraps the settings JSON as a CommonJS Module and includes in the document + * so package config is easily available in the CommonJS environment. + */ + +exports.addSettings = function (root, doc, settings, name) { + name = name || 'packages/' + settings.name; + var json = JSON.stringify(settings); + var path = 'settings/' + name; + var src = 'module.exports = ' + json + ';'; + modules.add(doc, path, src); + if (root) { + if (doc.settings.root) { + // root settings already defined + throw new Error('Root settings conflict'); + } + modules.add(doc, 'settings/root', 'module.exports = require("' + + path.replace('"', '\\"') + + '");'); + } + return doc; +}; diff --git a/packages/settings/kanso.json b/packages/settings/kanso.json index 66fd0f7..97daa6d 100644 --- a/packages/settings/kanso.json +++ b/packages/settings/kanso.json @@ -1,9 +1,12 @@ { "name": "settings", - "version": "0.0.8", + "version": "0.0.10", "categories": ["build-tools"], "description": "Uploads the kanso.json file as a CommonJS module under the 'settings' directory. Useful for packages that need access to these values after deployment.", "preprocessors": { "add": "build/add" + }, + "postprocessors": { + "root": "build/add_root" } } diff --git a/packages/settings/node_modules/kanso-utils/attachments.js b/packages/settings/node_modules/kanso-utils/attachments.js new file mode 100644 index 0000000..330cc45 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/attachments.js @@ -0,0 +1,116 @@ +/** + * Functions related to the loading and manipulation of attachments in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + mime = require('mime'), + async = require('async'), + fs = require('fs'); + + +/** + * + * @param {Object} doc + * @param {String} path + * @param {Buffer} content + * @returns {Object} + */ + +exports.add = function (doc, ddoc_path, original_path, content) { + if (!doc._attachments) { + doc._attachments = {}; + } + doc._attachments[ddoc_path] = { + 'content_type': mime.lookup(original_path), + 'data': content.toString('base64'), + // custom addition removed in cleanup postprocessor + '_original_path': original_path + }; + return doc; +}; + + +/** + * Searchs a path for attachments, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a file or directory + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads an attachment file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + exports.add(doc, rel, p, content); + callback() + }); +}; + + +/** + * Find all attachments below or at a given path, recursing through + * subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for attachments. This function omits + * hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + return true; + }; +}; diff --git a/packages/settings/node_modules/kanso-utils/index.js b/packages/settings/node_modules/kanso-utils/index.js new file mode 100644 index 0000000..0b79a79 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/index.js @@ -0,0 +1,5 @@ +module.exports = { + attachments: require('./attachments'), + modules: require('./modules'), + utils: require('./utils') +}; diff --git a/packages/settings/node_modules/kanso-utils/modules.js b/packages/settings/node_modules/kanso-utils/modules.js new file mode 100644 index 0000000..4324d02 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/modules.js @@ -0,0 +1,289 @@ +/** + * Functions related to the loading and manipulation of CommonJS Modules in + * Kanso apps. + * + * @module + */ + +var utils = require('./utils'), + async = require('async'), + path = require('path'), + fs = require('fs'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +// As modules are added, their original file paths are added to this object +// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...} +exports.originalPaths = {}; + + +/** + * Add the module source to the document in the correct location for requiring + * server-side, then add the path to the _modules property for use by the + * modules plugin postprocessor (when creating the kanso.js attachment) + * + * Returns the updated document. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.add = function (doc, path, src) { + var curr = utils.getPropertyPath(doc, path, true); + if (curr !== undefined) { + var paths = utils.getPropertyPaths(path, curr); + throw new Error( + 'Adding ' + path + ' would overwrite:\n' + + ' ' + paths.join('\n ') + '\n' + + '\n' + + 'This error often occurs because there is a module with the\n' + + 'same name as a directory containing modules. There is no way\n' + + 'to map this structure in the design doc.\n' + ); + } + utils.setPropertyPath(doc, path, src); + if (!doc._modules) { + doc._modules = {}; + } + doc._modules[path] = null; + return doc; +}; + + +/** + * Wraps module source code with useful comments and module cache boilerplate + * code. + * + * @param {Object} doc + * @param {String} path + * @param {String} src + * @returns {Object} + */ + +exports.wrap = function (path, src) { + return '/********** ' + path + ' **********/\n\n' + + 'kanso.moduleCache["' + path.replace('"', '\\"') + '"] = ' + + '{load: (function (module, exports, require) {\n\n' + src + '\n\n})};' + + '\n\n'; +}; + + +/** + * Searchs a path for commonjs modules, adding them to the document. + * + * @param {String} pkgdir - path to the source package + * @param {String} p - path to a module file or directory of modules + * @param {Object} doc - the document to extend + * @param {Function} callback + */ + +exports.addPath = function (pkgdir, p, doc, callback) { + p = utils.abspath(p, pkgdir); + exports.find(p, function (err, files) { + if (err) { + return callback(err); + } + async.forEach(files, function (f, cb) { + exports.addFile(pkgdir, f, doc, cb); + }, callback); + }); +}; + + +/** + * Loads a module file and adds its contents to the document + * + * @param {String} pkgdir + * @param {String} p + * @param {Object} doc + * @param {Function} callback + */ + +exports.addFile = function (pkgdir, p, doc, callback) { + fs.readFile(p, function (err, content) { + if (err) { + return callback(err); + } + var rel = utils.relpath(p, pkgdir); + var module_path = rel.replace(/\.js$/, ''); + var src = content.toString(); + exports.add(doc, module_path, src); + utils.setPropertyPath(exports.originalPaths, rel, p); + callback() + }); +}; + + +/** + * Find all modules below or at a given path, recursing through subdirectories + * + * @param {String} p - the path to search + * @param {Function} callback + */ + +exports.find = async.memoize(function (p, callback) { + utils.find(p, exports.filenameFilter(p), callback); +}); + + +/** + * Creates a filter used when searching for module files. This function tests + * for a .js extension and omits hidden dot-preceeded filenames. + * + * @param {String} p - the path to the directory being searched + * @returns {Function} + */ + +exports.filenameFilter = function (p) { + return function (f) { + if (f === p) { + return true; + } + var relpath = utils.relpath(f, p); + // should not start with a '.' + if (/^\.[^\/]?/.test(relpath)) { + return false; + } + // should not contain a file or folder starting with a '.' + if (/\/\./.test(relpath)) { + return false; + } + // should have a .js extension + if (!/\.js$/.test(f)) { + return false; + } + return true; + }; +}; + + +/** + * Parses the exports.originalPaths object to return an array of filenames + */ + +exports.getFilenames = function (obj) { + var names = []; + for (var k in obj) { + if (typeof obj[k] === 'object') { + names.concat(exports.getFilenames(obj[k]).map(function (n) { + return k + '/' + n; + })); + } + else { + names.push(k); + } + } + return names; +}; + + +/** + * Loads a commonjs module from the loaded design document, returning + * the exported properties. The current_dir and target parameters are not the + * path of the module on the filesystem, but rather the path of the module + * within couchdb, root ('/') being the design doc itself. + * + * @param {Object} module_cache + * @param {Object} doc + * @param {String} current_dir + * @param {String} target + * @param {Object} context - optional, extends sandbox object + */ + +exports.require = function (module_cache, doc, current, target, context) { + var current_dir = path.dirname(current); + if (target.charAt(0) !== '.') { + current_dir = '/'; + } + var p = path.normalize(path.join(current_dir, target)); + if (module_cache[p]) { + return module_cache[p]; + } + + var nodes = p.split('/').slice(1); + var content = nodes.reduce(function (a, x) { + if (a[x] === undefined) { + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ') - ' + + 'Module not found' + ); + } + a = a[x]; + return a; + }, doc); + + var filename = utils.getPropertyPath( + exports.originalPaths, p.substr(1), true + ); + + // if you attempt to require + if (typeof filename === 'object') { + var filenames = exports.getFilenames(filename); + throw new Error( + //'Could not require module: ' + target + ' ' + + 'Could not require module: ' + p.replace(/^\//, '') + ' ' + + '(from: ' + current.replace(/^\//, '') + ')\n\n' + + 'It\'s not possible to require directories of modules in CouchDB,\n' + + 'you have to specify one of the following sub-modules directly:\n' + + filenames.map(function (f) { + return ' ' + p.replace(/^\//, '') + '/' + f; + }).join('\n') + '\n' + ); + } + + var module = { + id: p.substr(1), + exports: {}, + // TODO: this property is not provided by couchdb, but is by node: + //filename: filename, + // TODO: this property is not provided by couchdb, but is by node: + //require: async.apply(exports.require, module_cache, doc, p) + // TODO: module properties provided by couchdb, but not by kanso + // * current + // * parent + }; + var sandbox = { + module: module, + exports: module.exports, + //require: module.require, + require: async.apply(exports.require, module_cache, doc, p), + log: function () { + console.log.apply(console, arguments); + } + }; + + // copy context into sandbox + if (context) { + Object.keys(context).forEach(function (k) { + sandbox[k] = context[k]; + }); + } + + // Create a placeholder for this module's exports so circular requires + // are possible. TODO: node.js uses a loaded = false attribute on the + // cached module object to mark this as a placeholder. + module_cache[p] = {}; + + try { + var s = new Script(content, filename).runInNewContext(sandbox); + } + catch (e) { + if (e instanceof SyntaxError && filename) { + // gives a better syntax error than runInNewContext + // with filename and line number + require(filename); + } + if (!e.got_filename) { + e.message = 'Error loading: ' + filename + '\n' + e.message; + e.got_filename = true; + } + throw e; + } + module_cache[p] = sandbox.module.exports; + return module_cache[p]; +}; diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/LICENSE b/packages/settings/node_modules/kanso-utils/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 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/packages/settings/node_modules/kanso-utils/node_modules/async/Makefile b/packages/settings/node_modules/kanso-utils/node_modules/async/Makefile new file mode 100644 index 0000000..00f07ea --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/Makefile @@ -0,0 +1,21 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +BUILDDIR = dist + +all: build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + uglifyjs lib/async.js > $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/README.md b/packages/settings/node_modules/kanso-utils/node_modules/async/README.md new file mode 100644 index 0000000..f3c44ac --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/README.md @@ -0,0 +1,1009 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions on which they depend. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css b/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js b/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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 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 = exports; + +// 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.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// 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);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.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; + // 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 (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _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 _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 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*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/index.js b/packages/settings/node_modules/kanso-utils/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/lib/async.js b/packages/settings/node_modules/kanso-utils/node_modules/async/lib/async.js new file mode 100644 index 0000000..c862008 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/lib/async.js @@ -0,0 +1,690 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + iterator(arr[started], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + started += 1; + running += 1; + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + 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 { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + 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 = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + q.tasks.push({data: data, callback: callback}); + if(q.saturated && q.tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(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 || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + } + }; + +}()); diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/nodelint.cfg b/packages/settings/node_modules/kanso-utils/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/package.json b/packages/settings/node_modules/kanso-utils/node_modules/async/package.json new file mode 100644 index 0000000..6198943 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/package.json @@ -0,0 +1,16 @@ +{ "name": "async" +, "description": "Higher-order functions and common patterns for asynchronous code" +, "main": "./index" +, "author": "Caolan McMahon" +, "version": "0.1.15" +, "repository" : + { "type" : "git" + , "url" : "http://github.com/caolan/async.git" + } +, "bugs" : { "url" : "http://github.com/caolan/async/issues" } +, "licenses" : + [ { "type" : "MIT" + , "url" : "http://github.com/caolan/async/raw/master/LICENSE" + } + ] +} diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/test/test-async.js b/packages/settings/node_modules/kanso-utils/node_modules/async/test/test-async.js new file mode 100644 index 0000000..d3eeddc --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/test/test-async.js @@ -0,0 +1,1577 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto results'] = function(test){ + var callOrder = []; + async.auto({ + task1: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + setTimeout(function(){ + callOrder.push('task1'); + callback(null, 'task1a', 'task1b'); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(null, 'task2'); + }, 50); + }, + task3: ['task2', function(callback, results){ + test.same(results.task2, 'task2'); + callOrder.push('task3'); + callback(null); + }], + task4: ['task1', 'task2', function(callback, results){ + test.same(results.task1, ['task1a','task1b']); + test.same(results.task2, 'task2'); + callOrder.push('task4'); + callback(null, 'task4'); + }] + }, + function(err, results){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.same(results, {task1: ['task1a','task1b'], task2: 'task2', task3: undefined, task4: 'task4'}); + test.done(); + }); +}; + + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 100); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 25); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachLimit'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 2, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit empty array'] = function(test){ + test.expect(1); + async.forEachLimit([], 2, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit limit exceeds size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 20, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit limit equal size'] = function(test){ + var args = []; + var arr = [0,1,2,3,4,5,6,7,8,9]; + async.forEachLimit(arr, 10, function(x,callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*5); + }, function(err){ + test.same(args, arr); + test.done(); + }); +}; + +exports['forEachLimit zero limit'] = function(test){ + test.expect(1); + async.forEachLimit([0,1,2,3,4,5], 0, function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachLimit error'] = function(test){ + test.expect(2); + var arr = [0,1,2,3,4,5,6,7,8,9]; + var call_order = []; + + async.forEachLimit(arr, 3, function(x, callback){ + call_order.push(x); + if (x === 2) { + callback('error'); + } + }, function(err){ + test.same(call_order, [0,1,2]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 25); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detect - mulitple matches'] = function(test){ + var call_order = []; + async.detect([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',2,2,3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['detectSeries - multiple matches'] = function(test){ + var call_order = []; + async.detectSeries([3,2,2,1,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['unmemoize'] = function(test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + var fn3 = async.unmemoize(fn2); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn3(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',1,2], ['fn',2,2]]); + + test.done(); +} + +exports['unmemoize a not memoized function'] = function(test) { + test.expect(1); + + var fn = function (arg1, arg2, callback) { + callback(null, arg1 + arg2); + }; + + var fn2 = async.unmemoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 3); + }); + + test.done(); +} + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize multiple calls'] = function (test) { + test.expect(3); + var fn = function (arg1, arg2, callback) { + test.ok(true); + setTimeout(function(){ + callback(null, arg1, arg2); + }, 10); + }; + var fn2 = async.memoize(fn); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + }); + fn2(1, 2, function(err, result) { + test.equal(result, 1, 2); + test.done(); + }); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.equal(results.length, 4); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/packages/settings/node_modules/kanso-utils/node_modules/async/test/test.html b/packages/settings/node_modules/kanso-utils/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

Async.js Test Suite

+ + + diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/LICENSE b/packages/settings/node_modules/kanso-utils/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/packages/settings/node_modules/kanso-utils/node_modules/mime/README.md b/packages/settings/node_modules/kanso-utils/node_modules/mime/README.md new file mode 100644 index 0000000..a157de1 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/README.md @@ -0,0 +1,50 @@ +# mime + +Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so: + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.txt'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) - lookup the default extension for type + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() - map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Customizing + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). +### mime.define() - Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) - Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/mime.js b/packages/settings/node_modules/kanso-utils/node_modules/mime/mime.js new file mode 100644 index 0000000..5fac753 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/mime.js @@ -0,0 +1,92 @@ +var path = require('path'), + fs = require('fs'); + +var mime = module.exports = { + /** Map of extension to mime type */ + types: {}, + + /** Map of mime type to extension */ + extensions :{}, + + /** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ + define: function(map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + mime.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!mime.extensions[type]) { + mime.extensions[type] = exts[0]; + } + } + }, + + /** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ + load: function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line, lineno) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + mime.define(map); + }, + + /** + * Lookup a mime type based on extension + */ + lookup: function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + return mime.types[ext] || fallback || mime.default_type; + }, + + /** + * Return file extension associated with a mime type + */ + extension: function(mimeType) { + return mime.extensions[mimeType]; + }, + + /** + * Lookup a charset based on mime type. + */ + charsets: { + lookup: function (mimeType, fallback) { + // Assume text types are utf8. Modify mime logic as needed. + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } + } +}; + +// Load our local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Overlay enhancements submitted by the node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Set the default type +mime.default_type = mime.types.bin; diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/package.json b/packages/settings/node_modules/kanso-utils/node_modules/mime/package.json new file mode 100644 index 0000000..85277b0 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/package.json @@ -0,0 +1,22 @@ +{ + "author": { + "name": "Robert Kieffer", + "url": "http://github.com/broofa", + "email": "robert@broofa.com" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "url": "http://github.com/bentomas", + "email": "benjamin@benjaminthomas.org" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {"async_testing": ""}, + "keywords": ["util", "mime"], + "main": "mime.js", + "name": "mime", + "repository": {"url": "http://github.com/bentomas/node-mime", "type": "git"}, + "version": "1.2.4" +} diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/test.js b/packages/settings/node_modules/kanso-utils/node_modules/mime/test.js new file mode 100644 index 0000000..b904895 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/test.js @@ -0,0 +1,79 @@ +/** + * Requires the async_testing module + * + * Usage: node test.js + */ +var mime = require('./mime'); +exports["test mime lookup"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('text.txt')); + + // hidden file or multiple periods + test.equal('text/plain', mime.lookup('.text.txt')); + + // just an extension + test.equal('text/plain', mime.lookup('.txt')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('txt')); + + // default + test.equal('application/octet-stream', mime.lookup('text.nope')); + + // fallback + test.equal('fallback', mime.lookup('text.fallback', 'fallback')); + + test.finish(); +}; + +exports["test extension lookup"] = function(test) { + // easy + test.equal('txt', mime.extension(mime.types.text)); + test.equal('html', mime.extension(mime.types.htm)); + test.equal('bin', mime.extension('application/octet-stream')); + + test.finish(); +}; + +exports["test mime lookup uppercase"] = function(test) { + // easy + test.equal('text/plain', mime.lookup('TEXT.TXT')); + + // just an extension + test.equal('text/plain', mime.lookup('.TXT')); + + // just an extension without a dot + test.equal('text/plain', mime.lookup('TXT')); + + // default + test.equal('application/octet-stream', mime.lookup('TEXT.NOPE')); + + // fallback + test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback')); + + test.finish(); +}; + +exports["test custom types"] = function(test) { + test.equal('application/octet-stream', mime.lookup('file.buffer')); + test.equal('audio/mp4', mime.lookup('file.m4a')); + + test.finish(); +}; + +exports["test charset lookup"] = function(test) { + // easy + test.equal('UTF-8', mime.charsets.lookup('text/plain')); + + // none + test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined'); + + // fallback + test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + + test.finish(); +}; + +if (module == require.main) { + require('async_testing').run(__filename, process.ARGV); +} diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/types/mime.types b/packages/settings/node_modules/kanso-utils/node_modules/mime/types/mime.types new file mode 100644 index 0000000..6a90929 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/types/mime.types @@ -0,0 +1,1479 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/packages/settings/node_modules/kanso-utils/node_modules/mime/types/node.types b/packages/settings/node_modules/kanso-utils/node_modules/mime/types/node.types new file mode 100644 index 0000000..fdabaa4 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/node_modules/mime/types/node.types @@ -0,0 +1,43 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts diff --git a/packages/settings/node_modules/kanso-utils/package.json b/packages/settings/node_modules/kanso-utils/package.json new file mode 100644 index 0000000..d9892e5 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/package.json @@ -0,0 +1,17 @@ +{ + "name": "kanso-utils", + "description": "NPM package which provides some common utility functions used by build-steps in Kanso packages", + "maintainers": [ + {"name": "Caolan McMahon", "web": "https://github.com/caolan"} + ], + "dependencies": { + "async": "0.1.15", + "mime": "1.2.4" + }, + "version": "0.1.2", + "repository": { + "type": "git", + "url": "http://github.com/kanso/kanso-utils.git" + }, + "bugs": {"url": "http://github.com/kanso/kanso-utils/issues"} +} diff --git a/packages/settings/node_modules/kanso-utils/utils.js b/packages/settings/node_modules/kanso-utils/utils.js new file mode 100644 index 0000000..6d9b3d0 --- /dev/null +++ b/packages/settings/node_modules/kanso-utils/utils.js @@ -0,0 +1,512 @@ +/** + * Module dependencies + */ + +var path = require('path'), + url = require('url'), + fs = require('fs'), + async = require('async'), + urlFormat = require('url').format, + urlParse = require('url').parse, + child_process = require('child_process'), + evals = process.binding('evals'), + Script = evals.Script || evals.NodeScript; + + +/** + * Converts a relative file path to properties on an object, and assigns a + * value to that property. SIDE EFFECTS: modifies original 'obj' argument! + * + * Examples: some/test/file.js => {some: {test: {file: ...} } } + * + * @param {Object} obj + * @param {String} p + * @param val + * @return val + * @see getPropertyPath + * @api public + */ + +exports.setPropertyPath = function (obj, p, val) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + var curr = []; + + // loop through all parts of the path except the last, creating the + // properties if they don't exist + var prop = parts.slice(0, parts.length - 1).reduce(function (a, x) { + curr.push(x); + if (a[x] === undefined) { + a[x] = {}; + } + if (typeof a[x] === 'object' && !Array.isArray(a[x])) { + a = a[x]; + } + else { + throw new Error( + 'Updating "' + p + '" would overwrite "' + + curr.join('/') + '"\n' + + '\n' + + 'This can sometimes happen when a file has the same name as\n' + + 'a directory and both paths are added to the design doc.\n' + + 'There is no way to map this structure in the design doc.\n' + ); + } + return a; + }, obj); + + // set the final property to the given value + prop[path.basename(parts[parts.length - 1], '.js')] = val; + + return val; +}; + +/** + * Returns an array of file-like paths from an object, prepending the 'root' + * path provided to each + * + * eg, getPropertyPath('foo', {a: '', b: {c: ''}}) => ['foo/a', 'foo/b/c'] + */ + +exports.getPropertyPaths = function (root, obj) { + if (typeof obj === 'object' && !Array.isArray(obj)) { + var paths = []; + for (var k in obj) { + paths = paths.concat( + exports.getPropertyPaths(root + '/' + k, obj[k]) + ); + } + return paths; + } + return [root]; +}; + +/** + * Converts a relative file path to properties on an object, and returns + * the value of that property. If invalid argument is set to true, invalid + * paths return undefined instead of throwing an error. + * + * @param {Object} obj + * @param {String} p + * @param {Boolean} invalid + * @see setPropertyPath + * @api public + */ + +exports.getPropertyPath = function (obj, p, invalid) { + // normalize to remove unessecary . and .. from paths + var parts = path.normalize(p).split('/'); + + // if path is empty, return the root object + if (!p) { + return obj; + } + + // loop through all parts of the path, throwing an exception + // if a property doesn't exist + for (var i = 0; i < parts.length; i++) { + var x = parts[i]; + if (obj[x] === undefined) { + if (invalid) { + return undefined; + } + throw new Error('Invalid path: ' + p); + } + obj = obj[x]; + } + return obj; +}; + +/** + * List all files below a given path, recursing through subdirectories. + * + * @param {String} p + * @param {Function} callback + * @api public + */ + +exports.descendants = function (p, callback) { + fs.stat(p, function (err, stats) { + if (err) { + return callback(err); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return callback(err); + } + var paths = files.map(function (f) { + return path.join(p, f); + }); + async.concat(paths, exports.descendants, function (err, files) { + if (err) { + callback(err); + } + else { + callback(err, files); + } + }); + }); + } + else if (stats.isFile()) { + callback(null, p); + } + }); +}; + +/** + * Gets all descendents of a path and tests against a regular expression, + * returning all matching file paths. + * + * @param {String} p + * @param {RegExp} pattern + * @param {Function} callback + * @api public + */ + +exports.find = function (p, test, callback) { + if (test instanceof RegExp) { + var re = test; + test = function (f) { + return re.test(f); + }; + } + exports.descendants(p, function (err, files) { + if (err) { + return callback(err); + } + if (!Array.isArray(files)) { + files = files ? [files]: []; + } + var matches = files.filter(function (f) { + return test(f); + }); + callback(null, matches); + }); +}; + +/** + * Read a file from the filesystem and parse as JSON + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.readJSON = function (path, callback) { + fs.readFile(path, function (err, content) { + var val; + if (err) { + return callback(err); + } + try { + val = JSON.parse(content.toString()); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + path]); + e.stack = stack.join('\n'); + return callback(e, null); + } + callback(null, val); + }); +}; + +/** + * Returns the absolute path 'p1' relative to the absolute path 'p2'. If 'p1' + * is already relative it is returned unchanged, unless both are relative. + * + * @param {String} p1 + * @param {String} p2 + * @return {String} + * @api public + */ + +exports.relpath = function (p1, p2) { + // if both p1 and p2 are relative, change both to absolute + if (p1[0] !== '/' && p2[0] !== '/') { + p1 = exports.abspath(p1); + p2 = exports.abspath(p2); + } + // if p1 is not absolute or p2 is not absolute, return p1 unchanged + if (p1[0] !== '/' || p2[0] !== '/') { + return p1; + } + + // remove trailing slashes + p1 = exports.rmTrailingSlash(p1); + p2 = exports.rmTrailingSlash(p2); + + var p1n = path.normalize(p1).split('/'), + p2n = path.normalize(p2).split('/'); + + + while (p1n.length && p2n.length && p1n[0] === p2n[0]) { + p1n.shift(); + p2n.shift(); + } + + // if p1 is not a sub-path of p2, then we need to add some .. + for (var i = 0; i < p2n.length; i++) { + p1n.unshift('..'); + } + + return path.join.apply(null, p1n); +}; + + +/** + * Removes trailing slashes from paths. + * + * @param {String} p + * @return {String} + * @api public + */ + +exports.rmTrailingSlash = function (p) { + if (p.length > 1 && p[p.length - 1] === '/') { + return p.substr(0, p.length - 1); + } + return p; +}; + + +/** + * Evals object literals used in properties files. The code is wrapped in + * parenthesis for a more natural writing style and evaluated in a new + * context to avoid interfering with the current scope. + * + * @param {String} code + * @param {String} filename + * @api public + */ + +exports.evalSandboxed = function (code, filename) { + try { + var s = new Script('(' + code + ')', filename); + return s.runInNewContext({}); + } + catch (e) { + var stack = e.stack.split('\n').slice(0, 1); + stack = stack.concat(['\tin ' + filename]); + e.stack = stack.join('\n'); + throw e; + } +}; + +/** + * Pads a string to minlength by appending spaces. + * + * @param {String} str + * @param {Number} minlength + * @return {String} + * @api public + */ + +exports.padRight = function (str, minlength) { + while (str.length < minlength) { + str += ' '; + } + return str; +}; + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api public + */ + +exports.ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + var err_data = ''; + mkdir.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mkdir.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +exports.cp = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var cp = child_process.spawn('cp', options.concat([from, to])); + var err_data = ''; + cp.stderr.on('data', function (data) { + err_data += data.toString(); + }); + cp.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.mv = function (/* optional */options, from, to, callback) { + // options are optional + if (!callback) { + callback = to; + to = from; + from = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + var mv = child_process.spawn('mv', options.concat([from, to])); + var err_data = ''; + mv.stderr.on('data', function (data) { + err_data += data.toString(); + }); + mv.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + +exports.rm = function (/* optional */options, target, callback) { + // options are optional + if (!callback) { + callback = target; + target = options; + options = []; + } + /* for options to an array */ + if (!Array.isArray(options)) { + options = [options]; + } + if (!Array.isArray(target)) { + target = [target]; + } + var rm = child_process.spawn('rm', options.concat(target)); + var err_data = ''; + rm.stderr.on('data', function (data) { + err_data += data.toString(); + }); + rm.on('exit', function (code) { + if (code !== 0) { + return callback(new Error(err_data)); + } + callback(); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +exports.abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') { + return p; + } + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + +/** + * Recurses through the properties of an object, converting all functions to + * strings representing their source code. Returns a JSON-compatible object + * that will work with JSON.stringify. + * + * @param {Object} obj + * @return {Object} + * @api public + */ + +exports.stringifyFunctions = function (obj) { + if (typeof obj === 'function' || obj instanceof Function) { + return obj.toString(); + } + if (typeof obj === 'object') { + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + obj[k] = exports.stringifyFunctions(obj[k]); + } + } + } + return obj; +}; + +exports.padRight = function (str, len) { + while (str.length < len) { + str = str + ' '; + } + return str; +}; + +exports.longest = function (arr) { + return arr.reduce(function (a, x) { + if (x.length > a) { + return x.length; + } + return a; + }, 0); +}; + +exports.ISODateString = function (d) { + function pad(n){ + return n < 10 ? '0' + n : n; + } + return d.getUTCFullYear() + '-' + + pad(d.getUTCMonth() + 1) + '-' + + pad(d.getUTCDate()) + 'T' + + pad(d.getUTCHours()) + ':' + + pad(d.getUTCMinutes()) + ':' + + pad(d.getUTCSeconds()) + 'Z'; +}; + +// tests if 'a' is a path below (or equal to) 'b' +exports.isSubPath = function (a, b) { + var na = path.normalize(a); + var nb = path.normalize(b); + var pa = na.split('/'); + var pb = nb.split('/'); + if (pa.length < pb.length) { + return false; + } + for (var i = 0; i < pb.length; i++) { + if (pa[i] !== pb[i]) { + return false; + } + } + return true; +}; + +/** + * Used by commands wanting to report a URL on the command-line without giving + * away auth info. + */ + +exports.noAuthURL = function (url) { + var parts = urlParse(url); + delete parts.auth; + delete parts.host; + return urlFormat(parts); +}; From 3af49067468dbcd9896ebd26f750f93eaf6b1c7d Mon Sep 17 00:00:00 2001 From: Milan Andric Date: Thu, 2 Feb 2012 17:44:39 -0600 Subject: [PATCH 3/3] added readme --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..85a0b3a --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Kanso Admin + +Quick CRUD interface to your Kanso CouchTypes. Push it to the database you have +your types installed on and it will introspect them. + +``` +git clone https://github.com/mandric/admin +cd admin +git push +```