From fcf182eb13e0053d7735e7b34e6e46ba79af1cfc Mon Sep 17 00:00:00 2001 From: kentwalters Date: Mon, 7 Nov 2016 20:57:22 -0600 Subject: [PATCH 001/883] docs(guide/controller): change "hides" to "shadows" "Shadows" should better convey the meaning of "overwriting the value of the property in the child scope, while leaving the parent scope intact". "Hides" could give the impression that it makes the property unavailable in the child scope and leaving "overrides" only, could give the impression that the parent scope would be affected too, especially to people not familiar with JavaScript's prototypal inheritance. Closes #15375 --- docs/content/guide/controller.ngdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/guide/controller.ngdoc b/docs/content/guide/controller.ngdoc index f4df3fb9fa64..748de9b4c2aa 100644 --- a/docs/content/guide/controller.ngdoc +++ b/docs/content/guide/controller.ngdoc @@ -253,10 +253,10 @@ scopes being created for our view: - The root scope - The `MainController` scope, which contains `timeOfDay` and `name` properties -- The `ChildController` scope, which inherits the `timeOfDay` property but overrides (hides) the `name` -property from the previous -- The `GrandChildController` scope, which overrides (hides) both the `timeOfDay` property defined in `MainController` -and the `name` property defined in `ChildController` +- The `ChildController` scope, which inherits the `timeOfDay` property but overrides (shadows) the + `name` property from the previous scope +- The `GrandChildController` scope, which overrides (shadows) both the `timeOfDay` property defined + in `MainController` and the `name` property defined in `ChildController` Inheritance works with methods in the same way as it does with properties. So in our previous examples, all of the properties could be replaced with methods that return string values. From 5419201a3c121a80c43f0f585da0214a5115bad6 Mon Sep 17 00:00:00 2001 From: Julio Borja Barra Date: Sat, 15 Oct 2016 07:15:23 +0000 Subject: [PATCH 002/883] docs(ngModel): fix example For the example to work correctly, the initial model values have to be empty strings. Closes #15272 --- src/ng/directive/ngModel.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index a74e8a4bffae..887646416faf 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -451,7 +451,7 @@ NgModelController.prototype = { * angular.module('cancel-update-example', []) * * .controller('CancelUpdateController', ['$scope', function($scope) { - * $scope.model = {}; + * $scope.model = {value1: '', value2: ''}; * * $scope.setEmpty = function(e, value, rollback) { * if (e.keyCode === 27) { @@ -466,8 +466,8 @@ NgModelController.prototype = { * * *
- *

Both of these inputs are only updated if they are blurred. Hitting escape should - * empty them. Follow these steps and observe the difference:

+ *

Both of these inputs are only updated if they are blurred. Hitting escape should + * empty them. Follow these steps and observe the difference:

*
    *
  1. Type something in the input. You will see that the model is not yet updated
  2. *
  3. Press the Escape key. @@ -484,17 +484,17 @@ NgModelController.prototype = { * *
    *
    - *

    Without $rollbackViewValue():

    - * - * value1: "{{ model.value1 }}" + *

    Without $rollbackViewValue():

    + * + * value1: "{{ model.value1 }}" *
    * *
    - *

    With $rollbackViewValue():

    - * - * value2: "{{ model.value2 }}" + *

    With $rollbackViewValue():

    + * + * value2: "{{ model.value2 }}" *
    *
    *
From 0f45adebea9bdcf0e98fed30687448a6e8729ff5 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 11 Nov 2016 19:47:28 +0000 Subject: [PATCH 003/883] chore(package.json): update to latest version of shelljs --- lib/versions/version-info.js | 10 +- npm-shrinkwrap.clean.json | 219 ++++++++----- npm-shrinkwrap.json | 595 ++++++++++++++++++++--------------- package.json | 2 +- 4 files changed, 487 insertions(+), 339 deletions(-) diff --git a/lib/versions/version-info.js b/lib/versions/version-info.js index 93eb8171c582..326141797850 100644 --- a/lib/versions/version-info.js +++ b/lib/versions/version-info.js @@ -53,7 +53,7 @@ var getGitRepoInfo = function() { * @return {String} The codename if found, otherwise null/undefined */ var getCodeName = function(tagName) { - var gitCatOutput = shell.exec('git cat-file -p ' + tagName, {silent:true}).output; + var gitCatOutput = shell.exec('git cat-file -p ' + tagName, {silent:true}).stdout; var tagMessage = gitCatOutput.match(/^.*codename.*$/mg)[0]; var codeName = tagMessage && tagMessage.match(/codename\((.*)\)/)[1]; if (!codeName) { @@ -69,7 +69,7 @@ var getCodeName = function(tagName) { * @return {String} The build segment of the version */ function getBuild() { - var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', ''); + var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).stdout.replace('\n', ''); return 'sha.' + hash; } @@ -87,7 +87,7 @@ var getTaggedVersion = function() { var gitTagResult = shell.exec('git describe --exact-match', {silent:true}); if (gitTagResult.code === 0) { - var tag = gitTagResult.output.trim(); + var tag = gitTagResult.stdout.trim(); var version = semver.parse(tag); if (version && checkBranchPattern(version.version, currentPackage.branchPattern)) { @@ -113,7 +113,7 @@ var getPreviousVersions = function() { var query = NO_REMOTE_REQUESTS ? 'git tag' : 'git ls-remote --tags ' + repo_url; var tagResults = shell.exec(query, {silent: true}); if (tagResults.code === 0) { - return _(tagResults.output.match(/v[0-9].*[0-9]$/mg)) + return _(tagResults.stdout.match(/v[0-9].*[0-9]$/mg)) .map(function(tag) { var version = semver.parse(tag); return version; @@ -159,7 +159,7 @@ var getCdnVersion = function() { {silent: true}); if (cdnResult.code === 0) { // --write-out appends its content to the general request response, so extract it - var statusCode = cdnResult.output.split('\n').pop().trim(); + var statusCode = cdnResult.stdout.split('\n').pop().trim(); if (statusCode === '200') { cdnVersion = version; } diff --git a/npm-shrinkwrap.clean.json b/npm-shrinkwrap.clean.json index a2efdf13c0d9..79340246c627 100644 --- a/npm-shrinkwrap.clean.json +++ b/npm-shrinkwrap.clean.json @@ -2463,12 +2463,12 @@ "abbrev": { "version": "1.0.9" }, - "ansi-styles": { - "version": "2.2.1" - }, "ansi-regex": { "version": "2.0.0" }, + "ansi-styles": { + "version": "2.2.1" + }, "aproba": { "version": "1.0.4" }, @@ -2484,24 +2484,24 @@ "async": { "version": "1.5.2" }, - "aws4": { - "version": "1.4.1" - }, "aws-sign2": { "version": "0.6.0" }, + "aws4": { + "version": "1.4.1" + }, "balanced-match": { "version": "0.4.2" }, "block-stream": { "version": "0.0.9" }, - "brace-expansion": { - "version": "1.1.5" - }, "boom": { "version": "2.10.1" }, + "brace-expansion": { + "version": "1.1.5" + }, "buffer-shims": { "version": "1.0.0" }, @@ -2511,74 +2511,77 @@ "chalk": { "version": "1.1.3" }, - "combined-stream": { - "version": "1.0.5" - }, "code-point-at": { "version": "1.0.0" }, + "combined-stream": { + "version": "1.0.5" + }, "commander": { "version": "2.9.0" }, "concat-map": { "version": "0.0.1" }, - "core-util-is": { - "version": "1.0.2" - }, "console-control-strings": { "version": "1.1.0" }, + "core-util-is": { + "version": "1.0.2" + }, "cryptiles": { "version": "2.0.5" }, "debug": { "version": "2.2.0" }, - "delayed-stream": { - "version": "1.0.0" - }, "deep-extend": { "version": "0.4.1" }, - "ecc-jsbn": { - "version": "0.1.1" - }, "delegates": { "version": "1.0.0" }, - "extend": { - "version": "3.0.0" + "delayed-stream": { + "version": "1.0.0" + }, + "ecc-jsbn": { + "version": "0.1.1" }, "escape-string-regexp": { "version": "1.0.5" }, + "extend": { + "version": "3.0.0" + }, "extsprintf": { "version": "1.0.2" }, - "form-data": { - "version": "1.0.0-rc4" - }, "forever-agent": { "version": "0.6.1" }, - "fstream-ignore": { - "version": "1.0.5" - }, "fs.realpath": { "version": "1.0.0" }, + "form-data": { + "version": "1.0.0-rc4" + }, "fstream": { "version": "1.0.10" }, - "generate-object-property": { - "version": "1.2.0" + "fstream-ignore": { + "version": "1.0.5" + }, + "generate-function": { + "version": "2.0.0" }, "gauge": { "version": "2.6.0" }, - "generate-function": { - "version": "2.0.0" + "generate-object-property": { + "version": "1.2.0" + }, + "glob": { + "version": "7.0.5" }, "graceful-fs": { "version": "4.1.4" @@ -2586,9 +2589,6 @@ "graceful-readlink": { "version": "1.0.1" }, - "glob": { - "version": "7.0.5" - }, "har-validator": { "version": "2.0.6" }, @@ -2598,24 +2598,27 @@ "has-color": { "version": "0.1.7" }, - "has-unicode": { - "version": "2.0.1" - }, "hawk": { "version": "3.1.3" }, + "has-unicode": { + "version": "2.0.1" + }, "hoek": { "version": "2.16.3" }, - "http-signature": { - "version": "1.1.1" - }, "inflight": { "version": "1.0.5" }, + "http-signature": { + "version": "1.1.1" + }, "inherits": { "version": "2.0.1" }, + "ini": { + "version": "1.3.4" + }, "is-fullwidth-code-point": { "version": "1.0.0" }, @@ -2625,21 +2628,18 @@ "is-property": { "version": "1.0.2" }, - "ini": { - "version": "1.3.4" - }, "is-typedarray": { "version": "1.0.0" }, "isarray": { "version": "1.0.0" }, - "isstream": { - "version": "0.1.2" - }, "jodid25519": { "version": "1.0.2" }, + "isstream": { + "version": "0.1.2" + }, "jsbn": { "version": "0.1.0" }, @@ -2652,42 +2652,42 @@ "jsonpointer": { "version": "2.0.0" }, - "mime-db": { - "version": "1.23.0" - }, "jsprim": { "version": "1.3.0" }, "mime-types": { "version": "2.1.11" }, + "mime-db": { + "version": "1.23.0" + }, "minimatch": { "version": "3.0.2" }, - "mkdirp": { - "version": "0.5.1" - }, "minimist": { "version": "0.0.8" }, + "mkdirp": { + "version": "0.5.1" + }, "ms": { "version": "0.7.1" }, "node-uuid": { "version": "1.4.7" }, - "nopt": { - "version": "3.0.6" - }, "number-is-nan": { "version": "1.0.0" }, - "oauth-sign": { - "version": "0.8.2" - }, "npmlog": { "version": "3.1.2" }, + "nopt": { + "version": "3.0.6" + }, + "oauth-sign": { + "version": "0.8.2" + }, "once": { "version": "1.3.3" }, @@ -2709,26 +2709,23 @@ "qs": { "version": "6.2.0" }, - "request": { - "version": "2.73.0" - }, "readable-stream": { "version": "2.1.4" }, + "request": { + "version": "2.73.0" + }, "rimraf": { "version": "2.5.3" }, "semver": { "version": "5.2.0" }, - "signal-exit": { - "version": "3.0.0" - }, "set-blocking": { "version": "2.0.0" }, - "string-width": { - "version": "1.0.1" + "signal-exit": { + "version": "3.0.0" }, "sntp": { "version": "1.0.9" @@ -2736,6 +2733,9 @@ "string_decoder": { "version": "0.10.31" }, + "string-width": { + "version": "1.0.1" + }, "stringstream": { "version": "0.0.5" }, @@ -2745,36 +2745,36 @@ "strip-json-comments": { "version": "1.0.4" }, - "tar-pack": { - "version": "3.1.4" - }, "supports-color": { "version": "2.0.0" }, "tar": { "version": "2.2.1" }, - "tweetnacl": { - "version": "0.13.3" + "tar-pack": { + "version": "3.1.4" }, "tough-cookie": { "version": "2.2.2" }, - "uid-number": { - "version": "0.0.6" - }, "tunnel-agent": { "version": "0.4.3" }, + "tweetnacl": { + "version": "0.13.3" + }, + "uid-number": { + "version": "0.0.6" + }, "util-deprecate": { "version": "1.0.2" }, - "wide-align": { - "version": "1.1.0" - }, "verror": { "version": "1.3.6" }, + "wide-align": { + "version": "1.1.0" + }, "wrappy": { "version": "1.0.2" }, @@ -9602,7 +9602,66 @@ } }, "shelljs": { - "version": "0.3.0" + "version": "0.7.5", + "dependencies": { + "glob": { + "version": "7.1.1", + "dependencies": { + "fs.realpath": { + "version": "1.0.0" + }, + "inflight": { + "version": "1.0.6", + "dependencies": { + "wrappy": { + "version": "1.0.2" + } + } + }, + "inherits": { + "version": "2.0.3" + }, + "minimatch": { + "version": "3.0.3", + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "dependencies": { + "balanced-match": { + "version": "0.4.2" + }, + "concat-map": { + "version": "0.0.1" + } + } + } + } + }, + "once": { + "version": "1.4.0", + "dependencies": { + "wrappy": { + "version": "1.0.2" + } + } + }, + "path-is-absolute": { + "version": "1.0.1" + } + } + }, + "interpret": { + "version": "1.0.1" + }, + "rechoir": { + "version": "0.6.2", + "dependencies": { + "resolve": { + "version": "1.1.7" + } + } + } + } }, "sorted-object": { "version": "1.0.0" diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index cbe5fc8fabd0..1d3a43db41b0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -3790,16 +3790,16 @@ "from": "abbrev@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" }, - "ansi-styles": { - "version": "2.2.1", - "from": "ansi-styles@>=2.2.1 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" - }, "ansi-regex": { "version": "2.0.0", "from": "ansi-regex@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" }, + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + }, "aproba": { "version": "1.0.4", "from": "aproba@>=1.0.3 <2.0.0", @@ -3825,16 +3825,16 @@ "from": "async@>=1.5.2 <2.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" }, - "aws4": { - "version": "1.4.1", - "from": "aws4@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" - }, "aws-sign2": { "version": "0.6.0", "from": "aws-sign2@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" }, + "aws4": { + "version": "1.4.1", + "from": "aws4@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" + }, "balanced-match": { "version": "0.4.2", "from": "balanced-match@>=0.4.1 <0.5.0", @@ -3845,16 +3845,16 @@ "from": "block-stream@*", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz" }, - "brace-expansion": { - "version": "1.1.5", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz" - }, "boom": { "version": "2.10.1", "from": "boom@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" }, + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz" + }, "buffer-shims": { "version": "1.0.0", "from": "buffer-shims@>=1.0.0 <2.0.0", @@ -3870,16 +3870,16 @@ "from": "chalk@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" }, - "combined-stream": { - "version": "1.0.5", - "from": "combined-stream@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" - }, "code-point-at": { "version": "1.0.0", "from": "code-point-at@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz" }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + }, "commander": { "version": "2.9.0", "from": "commander@>=2.9.0 <3.0.0", @@ -3890,16 +3890,16 @@ "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, "console-control-strings": { "version": "1.1.0", "from": "console-control-strings@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, "cryptiles": { "version": "2.0.5", "from": "cryptiles@>=2.0.0 <3.0.0", @@ -3910,80 +3910,85 @@ "from": "debug@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" }, - "delayed-stream": { - "version": "1.0.0", - "from": "delayed-stream@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - }, "deep-extend": { "version": "0.4.1", "from": "deep-extend@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" }, - "ecc-jsbn": { - "version": "0.1.1", - "from": "ecc-jsbn@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" - }, "delegates": { "version": "1.0.0", "from": "delegates@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" }, - "extend": { - "version": "3.0.0", - "from": "extend@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" }, "escape-string-regexp": { "version": "1.0.5", "from": "escape-string-regexp@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, "extsprintf": { "version": "1.0.2", "from": "extsprintf@1.0.2", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" }, - "form-data": { - "version": "1.0.0-rc4", - "from": "form-data@>=1.0.0-rc4 <1.1.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz" - }, "forever-agent": { "version": "0.6.1", "from": "forever-agent@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" }, - "fstream-ignore": { - "version": "1.0.5", - "from": "fstream-ignore@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz" - }, "fs.realpath": { "version": "1.0.0", "from": "fs.realpath@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" }, + "form-data": { + "version": "1.0.0-rc4", + "from": "form-data@>=1.0.0-rc4 <1.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz" + }, "fstream": { "version": "1.0.10", "from": "fstream@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz" }, - "generate-object-property": { - "version": "1.2.0", - "from": "generate-object-property@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + "fstream-ignore": { + "version": "1.0.5", + "from": "fstream-ignore@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz" + }, + "generate-function": { + "version": "2.0.0", + "from": "generate-function@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" }, "gauge": { "version": "2.6.0", "from": "gauge@>=2.6.0 <2.7.0", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz" }, - "generate-function": { - "version": "2.0.0", - "from": "generate-function@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, + "glob": { + "version": "7.0.5", + "from": "glob@>=7.0.5 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz" }, "graceful-fs": { "version": "4.1.4", @@ -3995,11 +4000,6 @@ "from": "graceful-readlink@>=1.0.0", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" }, - "glob": { - "version": "7.0.5", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz" - }, "har-validator": { "version": "2.0.6", "from": "har-validator@>=2.0.6 <2.1.0", @@ -4015,36 +4015,41 @@ "from": "has-color@>=0.1.7 <0.2.0", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz" }, - "has-unicode": { - "version": "2.0.1", - "from": "has-unicode@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" - }, "hawk": { "version": "3.1.3", "from": "hawk@>=3.1.3 <3.2.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" }, + "has-unicode": { + "version": "2.0.1", + "from": "has-unicode@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + }, "hoek": { "version": "2.16.3", "from": "hoek@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" }, - "http-signature": { - "version": "1.1.1", - "from": "http-signature@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" - }, "inflight": { "version": "1.0.5", "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz" }, + "http-signature": { + "version": "1.1.1", + "from": "http-signature@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + }, "inherits": { "version": "2.0.1", "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, + "ini": { + "version": "1.3.4", + "from": "ini@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" + }, "is-fullwidth-code-point": { "version": "1.0.0", "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", @@ -4060,11 +4065,6 @@ "from": "is-property@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" }, - "ini": { - "version": "1.3.4", - "from": "ini@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" - }, "is-typedarray": { "version": "1.0.0", "from": "is-typedarray@>=1.0.0 <1.1.0", @@ -4075,16 +4075,16 @@ "from": "isarray@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" }, - "isstream": { - "version": "0.1.2", - "from": "isstream@>=0.1.2 <0.2.0", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - }, "jodid25519": { "version": "1.0.2", "from": "jodid25519@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, "jsbn": { "version": "0.1.0", "from": "jsbn@>=0.1.0 <0.2.0", @@ -4105,11 +4105,6 @@ "from": "jsonpointer@2.0.0", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" }, - "mime-db": { - "version": "1.23.0", - "from": "mime-db@>=1.23.0 <1.24.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" - }, "jsprim": { "version": "1.3.0", "from": "jsprim@>=1.2.2 <2.0.0", @@ -4120,21 +4115,26 @@ "from": "mime-types@>=2.1.7 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz" }, + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + }, "minimatch": { "version": "3.0.2", "from": "minimatch@>=3.0.2 <4.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz" }, - "mkdirp": { - "version": "0.5.1", - "from": "mkdirp@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" - }, "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + }, "ms": { "version": "0.7.1", "from": "ms@0.7.1", @@ -4145,26 +4145,26 @@ "from": "node-uuid@>=1.4.7 <1.5.0", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" }, - "nopt": { - "version": "3.0.6", - "from": "nopt@>=3.0.1 <3.1.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" - }, "number-is-nan": { "version": "1.0.0", "from": "number-is-nan@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" }, - "oauth-sign": { - "version": "0.8.2", - "from": "oauth-sign@>=0.8.1 <0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" - }, "npmlog": { "version": "3.1.2", "from": "npmlog@>=3.1.2 <3.2.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz" }, + "nopt": { + "version": "3.0.6", + "from": "nopt@>=3.0.1 <3.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + }, + "oauth-sign": { + "version": "0.8.2", + "from": "oauth-sign@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + }, "once": { "version": "1.3.3", "from": "once@>=1.3.0 <2.0.0", @@ -4200,16 +4200,16 @@ "from": "qs@>=6.2.0 <6.3.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" }, - "request": { - "version": "2.73.0", - "from": "request@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.73.0.tgz" - }, "readable-stream": { "version": "2.1.4", "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz" }, + "request": { + "version": "2.73.0", + "from": "request@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.73.0.tgz" + }, "rimraf": { "version": "2.5.3", "from": "rimraf@>=2.5.0 <2.6.0", @@ -4220,20 +4220,15 @@ "from": "semver@>=5.2.0 <5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.2.0.tgz" }, - "signal-exit": { - "version": "3.0.0", - "from": "signal-exit@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz" - }, "set-blocking": { "version": "2.0.0", "from": "set-blocking@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" }, - "string-width": { - "version": "1.0.1", - "from": "string-width@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz" + "signal-exit": { + "version": "3.0.0", + "from": "signal-exit@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz" }, "sntp": { "version": "1.0.9", @@ -4245,6 +4240,11 @@ "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, + "string-width": { + "version": "1.0.1", + "from": "string-width@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz" + }, "stringstream": { "version": "0.0.5", "from": "stringstream@>=0.0.4 <0.1.0", @@ -4260,11 +4260,6 @@ "from": "strip-json-comments@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" }, - "tar-pack": { - "version": "3.1.4", - "from": "tar-pack@>=3.1.0 <3.2.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.4.tgz" - }, "supports-color": { "version": "2.0.0", "from": "supports-color@>=2.0.0 <3.0.0", @@ -4275,41 +4270,46 @@ "from": "tar@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz" }, - "tweetnacl": { - "version": "0.13.3", - "from": "tweetnacl@>=0.13.0 <0.14.0", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + "tar-pack": { + "version": "3.1.4", + "from": "tar-pack@>=3.1.0 <3.2.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.4.tgz" }, "tough-cookie": { "version": "2.2.2", "from": "tough-cookie@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" }, - "uid-number": { - "version": "0.0.6", - "from": "uid-number@>=0.0.6 <0.1.0", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" - }, "tunnel-agent": { "version": "0.4.3", "from": "tunnel-agent@>=0.4.1 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" }, + "tweetnacl": { + "version": "0.13.3", + "from": "tweetnacl@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + }, + "uid-number": { + "version": "0.0.6", + "from": "uid-number@>=0.0.6 <0.1.0", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" + }, "util-deprecate": { "version": "1.0.2", "from": "util-deprecate@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" }, - "wide-align": { - "version": "1.1.0", - "from": "wide-align@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz" - }, "verror": { "version": "1.3.6", "from": "verror@1.3.6", "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" }, + "wide-align": { + "version": "1.1.0", + "from": "wide-align@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz" + }, "wrappy": { "version": "1.0.2", "from": "wrappy@>=1.0.0 <2.0.0", @@ -13732,125 +13732,125 @@ }, "protractor": { "version": "4.0.10", - "from": "protractor@4.0.10", + "from": "https://registry.npmjs.org/protractor/-/protractor-4.0.10.tgz", "resolved": "https://registry.npmjs.org/protractor/-/protractor-4.0.10.tgz", "dependencies": { "@types/jasmine": { "version": "2.5.37", - "from": "@types/jasmine@>=2.5.36 <3.0.0", + "from": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.37.tgz", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.37.tgz" }, "@types/node": { "version": "6.0.46", - "from": "@types/node@>=6.0.46 <7.0.0", + "from": "https://registry.npmjs.org/@types/node/-/node-6.0.46.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.46.tgz" }, "@types/q": { "version": "0.0.32", - "from": "@types/q@>=0.0.32 <0.0.33", + "from": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz" }, "@types/selenium-webdriver": { "version": "2.53.34", - "from": "@types/selenium-webdriver@>=2.53.31 <2.54.0", + "from": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.34.tgz", "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.34.tgz" }, "adm-zip": { "version": "0.4.7", - "from": "adm-zip@0.4.7", + "from": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz" }, "chalk": { "version": "1.1.3", - "from": "chalk@>=1.1.3 <2.0.0", + "from": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "dependencies": { "ansi-styles": { "version": "2.2.1", - "from": "ansi-styles@>=2.2.1 <3.0.0", + "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" }, "escape-string-regexp": { "version": "1.0.5", - "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" }, "has-ansi": { "version": "2.0.0", - "from": "has-ansi@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "dependencies": { "ansi-regex": { "version": "2.0.0", - "from": "ansi-regex@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" } } }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.0 <4.0.0", + "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { "version": "2.0.0", - "from": "ansi-regex@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" } } }, "supports-color": { "version": "2.0.0", - "from": "supports-color@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" } } }, "glob": { "version": "7.1.1", - "from": "glob@>=7.0.3 <8.0.0", + "from": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", "dependencies": { "fs.realpath": { "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" }, "inflight": { "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", + "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "dependencies": { "wrappy": { "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" } } }, "inherits": { "version": "2.0.3", - "from": "inherits@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" }, "minimatch": { "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", + "from": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", "dependencies": { "brace-expansion": { "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", "dependencies": { "balanced-match": { "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", + "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" }, "concat-map": { "version": "0.0.1", - "from": "concat-map@0.0.1", + "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -13859,104 +13859,104 @@ }, "once": { "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", + "from": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "dependencies": { "wrappy": { "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" } } }, "path-is-absolute": { "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" } } }, "jasmine": { "version": "2.5.2", - "from": "jasmine@2.5.2", + "from": "https://registry.npmjs.org/jasmine/-/jasmine-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.5.2.tgz", "dependencies": { "exit": { "version": "0.1.2", - "from": "exit@>=0.1.2 <0.2.0", + "from": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" }, "jasmine-core": { "version": "2.5.2", - "from": "jasmine-core@>=2.5.2 <2.6.0", + "from": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.5.2.tgz" } } }, "jasminewd2": { "version": "0.0.10", - "from": "jasminewd2@0.0.10", + "from": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-0.0.10.tgz", "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-0.0.10.tgz" }, "optimist": { "version": "0.6.1", - "from": "optimist@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.3", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "q": { "version": "1.4.1", - "from": "q@1.4.1", + "from": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz" }, "saucelabs": { "version": "1.3.0", - "from": "saucelabs@>=1.3.0 <1.4.0", + "from": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.3.0.tgz", "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.3.0.tgz", "dependencies": { "https-proxy-agent": { "version": "1.0.0", - "from": "https-proxy-agent@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", "dependencies": { "agent-base": { "version": "2.0.1", - "from": "agent-base@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz", "dependencies": { "semver": { "version": "5.0.3", - "from": "semver@>=5.0.1 <5.1.0", + "from": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz" } } }, "debug": { "version": "2.2.0", - "from": "debug@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1", + "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, "extend": { "version": "3.0.0", - "from": "extend@>=3.0.0 <4.0.0", + "from": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" } } @@ -13965,68 +13965,68 @@ }, "source-map-support": { "version": "0.4.6", - "from": "source-map-support@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz", "dependencies": { "source-map": { "version": "0.5.6", - "from": "source-map@>=0.5.3 <0.6.0", + "from": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" } } }, "webdriver-manager": { "version": "10.2.6", - "from": "webdriver-manager@>=10.2.6 <11.0.0", + "from": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-10.2.6.tgz", "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-10.2.6.tgz", "dependencies": { "del": { "version": "2.2.2", - "from": "del@>=2.2.0 <3.0.0", + "from": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "dependencies": { "globby": { "version": "5.0.0", - "from": "globby@>=5.0.0 <6.0.0", + "from": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "dependencies": { "array-union": { "version": "1.0.2", - "from": "array-union@>=1.0.1 <2.0.0", + "from": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "dependencies": { "array-uniq": { "version": "1.0.3", - "from": "array-uniq@>=1.0.1 <2.0.0", + "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" } } }, "arrify": { "version": "1.0.1", - "from": "arrify@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" } } }, "is-path-cwd": { "version": "1.0.0", - "from": "is-path-cwd@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz" }, "is-path-in-cwd": { "version": "1.0.0", - "from": "is-path-in-cwd@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "dependencies": { "is-path-inside": { "version": "1.0.0", - "from": "is-path-inside@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", "dependencies": { "path-is-inside": { "version": "1.0.2", - "from": "path-is-inside@>=1.0.1 <2.0.0", + "from": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" } } @@ -14035,22 +14035,22 @@ }, "object-assign": { "version": "4.1.0", - "from": "object-assign@>=4.0.1 <5.0.0", + "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz" }, "pify": { "version": "2.3.0", - "from": "pify@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" }, "pinkie-promise": { "version": "2.0.1", - "from": "pinkie-promise@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "dependencies": { "pinkie": { "version": "2.0.4", - "from": "pinkie@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" } } @@ -14059,127 +14059,127 @@ }, "ini": { "version": "1.3.4", - "from": "ini@>=1.3.4 <2.0.0", + "from": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" }, "minimist": { "version": "1.2.0", - "from": "minimist@>=1.2.0 <2.0.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" }, "request": { "version": "2.78.0", - "from": "request@>=2.69.0 <3.0.0", + "from": "https://registry.npmjs.org/request/-/request-2.78.0.tgz", "resolved": "https://registry.npmjs.org/request/-/request-2.78.0.tgz", "dependencies": { "aws-sign2": { "version": "0.6.0", - "from": "aws-sign2@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" }, "aws4": { "version": "1.5.0", - "from": "aws4@>=1.2.1 <2.0.0", + "from": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz" }, "caseless": { "version": "0.11.0", - "from": "caseless@>=0.11.0 <0.12.0", + "from": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" }, "combined-stream": { "version": "1.0.5", - "from": "combined-stream@>=1.0.5 <1.1.0", + "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "dependencies": { "delayed-stream": { "version": "1.0.0", - "from": "delayed-stream@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" } } }, "extend": { "version": "3.0.0", - "from": "extend@>=3.0.0 <3.1.0", + "from": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" }, "forever-agent": { "version": "0.6.1", - "from": "forever-agent@>=0.6.1 <0.7.0", + "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" }, "form-data": { "version": "2.1.1", - "from": "form-data@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/form-data/-/form-data-2.1.1.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.1.tgz", "dependencies": { "asynckit": { "version": "0.4.0", - "from": "asynckit@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" } } }, "har-validator": { "version": "2.0.6", - "from": "har-validator@>=2.0.6 <2.1.0", + "from": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "dependencies": { "commander": { "version": "2.9.0", - "from": "commander@>=2.9.0 <3.0.0", + "from": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "dependencies": { "graceful-readlink": { "version": "1.0.1", - "from": "graceful-readlink@>=1.0.0", + "from": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" } } }, "is-my-json-valid": { "version": "2.15.0", - "from": "is-my-json-valid@>=2.12.4 <3.0.0", + "from": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", "dependencies": { "generate-function": { "version": "2.0.0", - "from": "generate-function@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" }, "generate-object-property": { "version": "1.2.0", - "from": "generate-object-property@>=1.1.0 <2.0.0", + "from": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "dependencies": { "is-property": { "version": "1.0.2", - "from": "is-property@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" } } }, "jsonpointer": { "version": "4.0.0", - "from": "jsonpointer@>=4.0.0 <5.0.0", + "from": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz" }, "xtend": { "version": "4.0.1", - "from": "xtend@>=4.0.0 <5.0.0", + "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } } }, "pinkie-promise": { "version": "2.0.1", - "from": "pinkie-promise@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "dependencies": { "pinkie": { "version": "2.0.4", - "from": "pinkie@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" } } @@ -14188,111 +14188,111 @@ }, "hawk": { "version": "3.1.3", - "from": "hawk@>=3.1.3 <3.2.0", + "from": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "dependencies": { "hoek": { "version": "2.16.3", - "from": "hoek@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" }, "boom": { "version": "2.10.1", - "from": "boom@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" }, "cryptiles": { "version": "2.0.5", - "from": "cryptiles@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" }, "sntp": { "version": "1.0.9", - "from": "sntp@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" } } }, "http-signature": { "version": "1.1.1", - "from": "http-signature@>=1.1.0 <1.2.0", + "from": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "dependencies": { "assert-plus": { "version": "0.2.0", - "from": "assert-plus@>=0.2.0 <0.3.0", + "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" }, "jsprim": { "version": "1.3.1", - "from": "jsprim@>=1.2.2 <2.0.0", + "from": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", "dependencies": { "extsprintf": { "version": "1.0.2", - "from": "extsprintf@1.0.2", + "from": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" }, "json-schema": { "version": "0.2.3", - "from": "json-schema@0.2.3", + "from": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" }, "verror": { "version": "1.3.6", - "from": "verror@1.3.6", + "from": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" } } }, "sshpk": { "version": "1.10.1", - "from": "sshpk@>=1.7.0 <2.0.0", + "from": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz", "dependencies": { "asn1": { "version": "0.2.3", - "from": "asn1@>=0.2.3 <0.3.0", + "from": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" }, "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" }, "dashdash": { "version": "1.14.0", - "from": "dashdash@>=1.12.0 <2.0.0", + "from": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz" }, "getpass": { "version": "0.1.6", - "from": "getpass@>=0.1.1 <0.2.0", + "from": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz" }, "jsbn": { "version": "0.1.0", - "from": "jsbn@>=0.1.0 <0.2.0", + "from": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" }, "tweetnacl": { "version": "0.14.3", - "from": "tweetnacl@>=0.14.0 <0.15.0", + "from": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz" }, "jodid25519": { "version": "1.0.2", - "from": "jodid25519@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" }, "ecc-jsbn": { "version": "0.1.1", - "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "from": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" }, "bcrypt-pbkdf": { "version": "1.0.0", - "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz" } } @@ -14301,78 +14301,78 @@ }, "is-typedarray": { "version": "1.0.0", - "from": "is-typedarray@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" }, "isstream": { "version": "0.1.2", - "from": "isstream@>=0.1.2 <0.2.0", + "from": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" }, "json-stringify-safe": { "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.1 <5.1.0", + "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, "mime-types": { "version": "2.1.12", - "from": "mime-types@>=2.1.7 <2.2.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", "dependencies": { "mime-db": { "version": "1.24.0", - "from": "mime-db@>=1.24.0 <1.25.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" } } }, "node-uuid": { "version": "1.4.7", - "from": "node-uuid@>=1.4.7 <1.5.0", + "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" }, "oauth-sign": { "version": "0.8.2", - "from": "oauth-sign@>=0.8.1 <0.9.0", + "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" }, "qs": { "version": "6.3.0", - "from": "qs@>=6.3.0 <6.4.0", + "from": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz" }, "stringstream": { "version": "0.0.5", - "from": "stringstream@>=0.0.4 <0.1.0", + "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" }, "tough-cookie": { "version": "2.3.2", - "from": "tough-cookie@>=2.3.0 <2.4.0", + "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", "dependencies": { "punycode": { "version": "1.4.1", - "from": "punycode@>=1.4.1 <2.0.0", + "from": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" } } }, "tunnel-agent": { "version": "0.4.3", - "from": "tunnel-agent@>=0.4.1 <0.5.0", + "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" } } }, "rimraf": { "version": "2.5.4", - "from": "rimraf@>=2.5.2 <3.0.0", + "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz" }, "semver": { "version": "5.3.0", - "from": "semver@>=5.3.0 <6.0.0", + "from": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" } } @@ -14789,9 +14789,98 @@ } }, "shelljs": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz" + "version": "0.7.5", + "from": "shelljs@latest", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.5.tgz", + "dependencies": { + "glob": { + "version": "7.1.1", + "from": "glob@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.6", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "minimatch": { + "version": "3.0.3", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.1", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + } + }, + "interpret": { + "version": "1.0.1", + "from": "interpret@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz" + }, + "rechoir": { + "version": "0.6.2", + "from": "rechoir@>=0.6.2 <0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "dependencies": { + "resolve": { + "version": "1.1.7", + "from": "resolve@>=1.1.6 <2.0.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" + } + } + } + } }, "sorted-object": { "version": "1.0.0", diff --git a/package.json b/package.json index 1627ba80d857..a45489b52d78 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "serve-favicon": "^2.3.0", "serve-index": "^1.8.0", "serve-static": "^1.11.1", - "shelljs": "~0.3.0", + "shelljs": "^0.7.5", "sorted-object": "^1.0.0", "stringmap": "^0.2.2" }, From ce49edc08b3d642f3768f4282d391062d2f83037 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 11 Nov 2016 19:45:02 +0000 Subject: [PATCH 004/883] chore(docs): improve version picker Closes #15385 --- Gruntfile.js | 2 +- docs/app/src/app.js | 1 - docs/app/src/docs.js | 10 +- docs/app/src/versions.js | 63 ++++++----- docs/app/test/docsSpec.js | 9 +- docs/config/processors/versions-data.js | 106 +++++++++++++++--- docs/config/services/deployments/debug.js | 3 +- docs/config/services/deployments/default.js | 3 +- docs/config/services/deployments/jquery.js | 3 +- .../config/services/deployments/production.js | 3 +- .../templates/angular-service.template.js | 4 + docs/config/templates/indexPage.template.html | 8 +- .../templates/versions-data.template.js | 6 - 13 files changed, 150 insertions(+), 71 deletions(-) create mode 100644 docs/config/templates/angular-service.template.js delete mode 100644 docs/config/templates/versions-data.template.js diff --git a/Gruntfile.js b/Gruntfile.js index 47d30f509c5f..032039096aea 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -346,7 +346,7 @@ module.exports = function(grunt) { grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']); grunt.registerTask('webserver', ['connect:devserver']); - grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']); + grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'write', 'docs', 'copy', 'compress']); grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'eslint']); grunt.registerTask('default', ['package']); }; diff --git a/docs/app/src/app.js b/docs/app/src/app.js index 607cc0f0e1ec..df6272b0bf0b 100644 --- a/docs/app/src/app.js +++ b/docs/app/src/app.js @@ -6,7 +6,6 @@ angular.module('docsApp', [ 'ngSanitize', 'ngAnimate', 'DocsController', - 'versionsData', 'pagesData', 'navData', 'directives', diff --git a/docs/app/src/docs.js b/docs/app/src/docs.js index cb06ec646c45..e2bd613a0f90 100644 --- a/docs/app/src/docs.js +++ b/docs/app/src/docs.js @@ -1,12 +1,12 @@ 'use strict'; -angular.module('DocsController', []) +angular.module('DocsController', ['currentVersionData']) .controller('DocsController', [ '$scope', '$rootScope', '$location', '$window', '$cookies', - 'NG_PAGES', 'NG_NAVIGATION', 'NG_VERSION', + 'NG_PAGES', 'NG_NAVIGATION', 'CURRENT_NG_VERSION', function($scope, $rootScope, $location, $window, $cookies, - NG_PAGES, NG_NAVIGATION, NG_VERSION) { + NG_PAGES, NG_NAVIGATION, CURRENT_NG_VERSION) { $scope.navClass = function(navItem) { return { @@ -58,8 +58,8 @@ angular.module('DocsController', []) Initialize ***********************************/ - $scope.versionNumber = NG_VERSION.full; - $scope.version = NG_VERSION.full + ' ' + NG_VERSION.codeName; + $scope.versionNumber = CURRENT_NG_VERSION.full; + $scope.version = CURRENT_NG_VERSION.full + ' ' + CURRENT_NG_VERSION.codeName; $scope.loading = 0; diff --git a/docs/app/src/versions.js b/docs/app/src/versions.js index 04abeedc5615..9f0d3dc0c5c4 100644 --- a/docs/app/src/versions.js +++ b/docs/app/src/versions.js @@ -1,37 +1,42 @@ 'use strict'; +/* global console */ -angular.module('versions', []) +angular.module('versions', ['currentVersionData', 'allVersionsData']) -.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) { - $scope.docs_version = NG_VERSIONS[0]; - $scope.docs_versions = NG_VERSIONS; +.directive('versionPicker', function() { + return { + restrict: 'E', + scope: true, + controllerAs: '$ctrl', + controller: ['$location', '$window', 'CURRENT_NG_VERSION', 'ALL_NG_VERSIONS', + /** @this VersionPickerController */ + function VersionPickerController($location, $window, CURRENT_NG_VERSION, ALL_NG_VERSIONS) { - for (var i = 0, minor = NaN; i < NG_VERSIONS.length; i++) { - var version = NG_VERSIONS[i]; - if (version.isSnapshot) { - version.isLatest = true; - continue; - } - // NaN will give false here - if (minor <= version.minor) { - continue; - } - version.isLatest = true; - minor = version.minor; - } + var versionStr = CURRENT_NG_VERSION.isSnapshot ? 'snapshot' : CURRENT_NG_VERSION.version; - $scope.getGroupName = function(v) { - return v.isLatest ? 'Latest' : ('v' + v.major + '.' + v.minor + '.x'); + this.versions = ALL_NG_VERSIONS; + this.selectedVersion = find(ALL_NG_VERSIONS, function(value) { return value.version.version === versionStr; }); + + this.jumpToDocsVersion = function(value) { + var currentPagePath = $location.path().replace(/\/$/, ''); + $window.location = value.docsUrl + currentPagePath; + }; + }], + template: + '
' + + ' ' + + '
' }; - $scope.jumpToDocsVersion = function(version) { - var currentPagePath = $location.path().replace(/\/$/, ''), - url = ''; - if (version.isOldDocsUrl) { - url = version.docsUrl; - } else { - url = version.docsUrl + currentPagePath; + function find(collection, matcherFn) { + for (var i = 0, ii = collection.length; i < ii; ++i) { + if (matcherFn(collection[i])) { + return collection[i]; + } } - $window.location = url; - }; -}]); + } +}); diff --git a/docs/app/test/docsSpec.js b/docs/app/test/docsSpec.js index 905a6d511181..d5424ef2ff79 100644 --- a/docs/app/test/docsSpec.js +++ b/docs/app/test/docsSpec.js @@ -6,8 +6,13 @@ describe('DocsController', function() { angular.module('fake', []) .value('$cookies', {}) .value('NG_PAGES', {}) - .value('NG_NAVIGATION', {}) - .value('NG_VERSION', {}); + .value('NG_NAVIGATION', {}); + + angular.module('currentVersionData', []) + .value('CURRENT_NG_VERSION', {}); + + angular.module('allVersionsData', []) + .value('ALL_NG_VERSIONS', {}); beforeEach(module('fake', 'DocsController')); beforeEach(inject(function($rootScope, $controller) { diff --git a/docs/config/processors/versions-data.js b/docs/config/processors/versions-data.js index 5e0fa94cb7e0..8b8d0fd52d36 100644 --- a/docs/config/processors/versions-data.js +++ b/docs/config/processors/versions-data.js @@ -1,6 +1,7 @@ 'use strict'; -var _ = require('lodash'); +var exec = require('shelljs').exec; +var semver = require('semver'); /** * @dgProcessor generateVersionDocProcessor @@ -12,23 +13,96 @@ module.exports = function generateVersionDocProcessor(gitData) { return { $runAfter: ['generatePagesDataProcessor'], $runBefore: ['rendering-docs'], + // the blacklist is to remove rogue builds that are in npm but not on code.angularjs.org + blacklist: ['1.3.4-build.3588'], $process: function(docs) { - var versionDoc = { - docType: 'versions-data', - id: 'versions-data', - template: 'versions-data.template.js', - outputPath: 'js/versions-data.js', - currentVersion: gitData.version - }; - - versionDoc.versions = _(gitData.versions) - .filter(function(version) { return version.major > 0; }) - .push(gitData.version) - .reverse() - .value(); - - docs.push(versionDoc); + var blacklist = this.blacklist; + var currentVersion = require('../../../build/version.json'); + var output = exec('npm info angular versions --json', { silent: true }).stdout; + var allVersions = processAllVersionsResponse(JSON.parse(output)); + + docs.push({ + docType: 'current-version-data', + id: 'current-version-data', + template: 'angular-service.template.js', + outputPath: 'js/current-version-data.js', + ngModuleName: 'currentVersionData', + serviceName: 'CURRENT_NG_VERSION', + serviceValue: currentVersion + }); + + docs.push({ + docType: 'allversions-data', + id: 'allversions-data', + template: 'angular-service.template.js', + outputPath: 'js/all-versions-data.js', + ngModuleName: 'allVersionsData', + serviceName: 'ALL_NG_VERSIONS', + serviceValue: allVersions + }); + + + function processAllVersionsResponse(versions) { + + var latestMap = {}; + + versions = versions + .filter(function(versionStr) { + return blacklist.indexOf(versionStr) === -1; + }) + .map(function(versionStr) { + return semver.parse(versionStr); + }) + .filter(function(version) { + return version && version.major > 0; + }) + .map(function(version) { + var key = version.major + '.' + version.minor; + var latest = latestMap[key]; + if (!latest || version.compare(latest) > 0) { + latestMap[key] = version; + } + return version; + }) + .map(function(version) { + return makeOption(version); + }) + .reverse(); + + var latest = sortObject(latestMap, reverse(semver.compare)) + .map(function(version) { return makeOption(version, 'Latest'); }); + + return [makeOption({version: 'snapshot'}, 'Latest', 'master')] + .concat(latest) + .concat(versions); + } + + function makeOption(version, group, label) { + return { + version: version, + label: label || 'v' + version.raw, + group: group || 'v' + version.major + '.' + version.minor, + docsUrl: createDocsUrl(version) + }; + } + + function createDocsUrl(version) { + var url = 'https://code.angularjs.org/' + version.version + '/docs'; + // Versions before 1.0.2 had a different docs folder name + if (version.major === 1 && version.minor === 0 && version.patch < 2) { + url += '-' + version.version; + } + return url; + } + + function reverse(fn) { + return function(left, right) { return -fn(left, right); }; + } + + function sortObject(obj, cmp) { + return Object.keys(obj).map(function(key) { return obj[key]; }).sort(cmp); + } } }; }; diff --git a/docs/config/services/deployments/debug.js b/docs/config/services/deployments/debug.js index 991474c47ea0..f7381b129697 100644 --- a/docs/config/services/deployments/debug.js +++ b/docs/config/services/deployments/debug.js @@ -22,7 +22,8 @@ module.exports = function debugDeployment(getVersion) { 'components/lunr.js-' + getVersion('lunr.js') + '/lunr.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js', - 'js/versions-data.js', + 'js/current-version-data.js', + 'js/all-versions-data.js', 'js/pages-data.js', 'js/nav-data.js', 'js/docs.js' diff --git a/docs/config/services/deployments/default.js b/docs/config/services/deployments/default.js index 5a10e4dbddf0..c489946d8884 100644 --- a/docs/config/services/deployments/default.js +++ b/docs/config/services/deployments/default.js @@ -22,7 +22,8 @@ module.exports = function defaultDeployment(getVersion) { 'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js', - 'js/versions-data.js', + 'js/current-version-data.js', + 'js/all-versions-data.js', 'js/pages-data.js', 'js/nav-data.js', 'js/docs.min.js' diff --git a/docs/config/services/deployments/jquery.js b/docs/config/services/deployments/jquery.js index b480b9f50056..b224830af43a 100644 --- a/docs/config/services/deployments/jquery.js +++ b/docs/config/services/deployments/jquery.js @@ -26,7 +26,8 @@ module.exports = function jqueryDeployment(getVersion) { 'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js', - 'js/versions-data.js', + 'js/current-version-data.js', + 'js/all-versions-data.js', 'js/pages-data.js', 'js/nav-data.js', 'js/docs.min.js' diff --git a/docs/config/services/deployments/production.js b/docs/config/services/deployments/production.js index 112d20889520..2e090bf3d5a9 100644 --- a/docs/config/services/deployments/production.js +++ b/docs/config/services/deployments/production.js @@ -39,7 +39,8 @@ module.exports = function productionDeployment(getVersion) { 'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js', 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js', - 'js/versions-data.js', + 'js/current-version-data.js', + 'https://code.angularjs.org/snapshot/docs/js/all-versions-data.js', 'js/pages-data.js', 'js/nav-data.js', 'js/docs.min.js' diff --git a/docs/config/templates/angular-service.template.js b/docs/config/templates/angular-service.template.js new file mode 100644 index 000000000000..c44925dcde96 --- /dev/null +++ b/docs/config/templates/angular-service.template.js @@ -0,0 +1,4 @@ +'use strict'; + +angular.module('{$ doc.ngModuleName $}', []) + .value('{$ doc.serviceName $}', {$ doc.serviceValue | json $}); diff --git a/docs/config/templates/indexPage.template.html b/docs/config/templates/indexPage.template.html index a97fc9e6ed55..884763dcc838 100644 --- a/docs/config/templates/indexPage.template.html +++ b/docs/config/templates/indexPage.template.html @@ -165,13 +165,7 @@

{{ key }}

-
- -
+
* * @param {boolean=} flag Enable or disable SVG support in the sanitizer. - * @returns {boolean|ng.$sanitizeProvider} Returns the currently configured value if called + * @returns {boolean|$sanitizeProvider} Returns the currently configured value if called * without an argument or self for chaining otherwise. */ this.enableSvg = function(enableSvg) { @@ -199,6 +202,105 @@ function $SanitizeProvider() { } }; + + /** + * @ngdoc method + * @name $sanitizeProvider#addValidElements + * @kind function + * + * @description + * Extends the built-in lists of valid HTML/SVG elements, i.e. elements that are considered safe + * and are not stripped off during sanitization. You can extend the following lists of elements: + * + * - `htmlElements`: A list of elements (tag names) to extend the current list of safe HTML + * elements. HTML elements considered safe will not be removed during sanitization. All other + * elements will be stripped off. + * + * - `htmlVoidElements`: This is similar to `htmlElements`, but marks the elements as + * "void elements" (similar to HTML + * [void elements](https://rawgit.com/w3c/html/html5.1-2/single-page.html#void-elements)). These + * elements have no end tag and cannot have content. + * + * - `svgElements`: This is similar to `htmlElements`, but for SVG elements. This list is only + * taken into account if SVG is {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for + * `$sanitize`. + * + *
+ * This method must be called during the {@link angular.Module#config config} phase. Once the + * `$sanitize` service has been instantiated, this method has no effect. + *
+ * + *
+ * Keep in mind that extending the built-in lists of elements may expose your app to XSS or + * other vulnerabilities. Be very mindful of the elements you add. + *
+ * + * @param {Array|Object} elements - A list of valid HTML elements or an object with one or + * more of the following properties: + * - **htmlElements** - `{Array}` - A list of elements to extend the current list of + * HTML elements. + * - **htmlVoidElements** - `{Array}` - A list of elements to extend the current list of + * void HTML elements; i.e. elements that do not have an end tag. + * - **svgElements** - `{Array}` - A list of elements to extend the current list of SVG + * elements. The list of SVG elements is only taken into account if SVG is + * {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for `$sanitize`. + * + * Passing an array (`[...]`) is equivalent to passing `{htmlElements: [...]}`. + * + * @return {$sanitizeProvider} Returns self for chaining. + */ + this.addValidElements = function(elements) { + if (!hasBeenInstantiated) { + if (isArray(elements)) { + elements = {htmlElements: elements}; + } + + addElementsTo(svgElements, elements.svgElements); + addElementsTo(voidElements, elements.htmlVoidElements); + addElementsTo(validElements, elements.htmlVoidElements); + addElementsTo(validElements, elements.htmlElements); + } + + return this; + }; + + + /** + * @ngdoc method + * @name $sanitizeProvider#addValidAttrs + * @kind function + * + * @description + * Extends the built-in list of valid attributes, i.e. attributes that are considered safe and are + * not stripped off during sanitization. + * + * **Note**: + * The new attributes will not be treated as URI attributes, which means their values will not be + * sanitized as URIs using `$compileProvider`'s + * {@link ng.$compileProvider#aHrefSanitizationWhitelist aHrefSanitizationWhitelist} and + * {@link ng.$compileProvider#imgSrcSanitizationWhitelist imgSrcSanitizationWhitelist}. + * + *
+ * This method must be called during the {@link angular.Module#config config} phase. Once the + * `$sanitize` service has been instantiated, this method has no effect. + *
+ * + *
+ * Keep in mind that extending the built-in list of attributes may expose your app to XSS or + * other vulnerabilities. Be very mindful of the attributes you add. + *
+ * + * @param {Array} attrs - A list of valid attributes. + * + * @returns {$sanitizeProvider} Returns self for chaining. + */ + this.addValidAttrs = function(attrs) { + if (!hasBeenInstantiated) { + extend(validAttrs, arrayToMap(attrs, true)); + } + return this; + }; + ////////////////////////////////////////////////////////////////////////////////////////////////// // Private stuff ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -206,6 +308,7 @@ function $SanitizeProvider() { bind = angular.bind; extend = angular.extend; forEach = angular.forEach; + isArray = angular.isArray; isDefined = angular.isDefined; lowercase = angular.$$lowercase; noop = angular.noop; @@ -230,23 +333,23 @@ function $SanitizeProvider() { // Safe Void Elements - HTML5 // http://dev.w3.org/html5/spec/Overview.html#void-elements - var voidElements = toMap('area,br,col,hr,img,wbr'); + var voidElements = stringToMap('area,br,col,hr,img,wbr'); // Elements that you can, intentionally, leave open (and which close themselves) // http://dev.w3.org/html5/spec/Overview.html#optional-tags - var optionalEndTagBlockElements = toMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'), - optionalEndTagInlineElements = toMap('rp,rt'), + var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'), + optionalEndTagInlineElements = stringToMap('rp,rt'), optionalEndTagElements = extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements); // Safe Block Elements - HTML5 - var blockElements = extend({}, optionalEndTagBlockElements, toMap('address,article,' + + var blockElements = extend({}, optionalEndTagBlockElements, stringToMap('address,article,' + 'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + 'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul')); // Inline Elements - HTML5 - var inlineElements = extend({}, optionalEndTagInlineElements, toMap('a,abbr,acronym,b,' + + var inlineElements = extend({}, optionalEndTagInlineElements, stringToMap('a,abbr,acronym,b,' + 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' + 'samp,small,span,strike,strong,sub,sup,time,tt,u,var')); @@ -254,12 +357,12 @@ function $SanitizeProvider() { // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. // They can potentially allow for arbitrary javascript to be executed. See #11290 - var svgElements = toMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' + + var svgElements = stringToMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' + 'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' + 'radialGradient,rect,stop,svg,switch,text,title,tspan'); // Blocked Elements (will be stripped) - var blockedElements = toMap('script,style'); + var blockedElements = stringToMap('script,style'); var validElements = extend({}, voidElements, @@ -268,9 +371,9 @@ function $SanitizeProvider() { optionalEndTagElements); //Attributes that have href and hence need to be sanitized - var uriAttrs = toMap('background,cite,href,longdesc,src,xlink:href,xml:base'); + var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base'); - var htmlAttrs = toMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + + var htmlAttrs = stringToMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + @@ -278,7 +381,7 @@ function $SanitizeProvider() { // SVG attributes (without "id" and "name" attributes) // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes - var svgAttrs = toMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + + var svgAttrs = stringToMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + @@ -299,14 +402,24 @@ function $SanitizeProvider() { svgAttrs, htmlAttrs); - function toMap(str, lowercaseKeys) { - var obj = {}, items = str.split(','), i; + function stringToMap(str, lowercaseKeys) { + return arrayToMap(str.split(','), lowercaseKeys); + } + + function arrayToMap(items, lowercaseKeys) { + var obj = {}, i; for (i = 0; i < items.length; i++) { obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true; } return obj; } + function addElementsTo(elementsMap, newElements) { + if (newElements && newElements.length) { + extend(elementsMap, arrayToMap(newElements)); + } + } + /** * Create an inert document that contains the dirty HTML that needs sanitizing * Depending upon browser support we use one of three strategies for doing this. diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js index 69cb6abc9fda..a047be989642 100644 --- a/test/ngSanitize/sanitizeSpec.js +++ b/test/ngSanitize/sanitizeSpec.js @@ -293,10 +293,56 @@ describe('HTML', function() { expect(doc).toEqual('

'); })); + describe('Custom white-list support', function() { + + var $sanitizeProvider; + beforeEach(module(function(_$sanitizeProvider_) { + $sanitizeProvider = _$sanitizeProvider_; + + $sanitizeProvider.addValidElements(['foo']); + $sanitizeProvider.addValidElements({ + htmlElements: ['foo-button', 'foo-video'], + htmlVoidElements: ['foo-input'], + svgElements: ['foo-svg'] + }); + $sanitizeProvider.addValidAttrs(['foo']); + })); + + it('should allow custom white-listed element', function() { + expectHTML('').toEqual(''); + expectHTML('').toEqual(''); + expectHTML('').toEqual(''); + }); + + it('should allow custom white-listed void element', function() { + expectHTML('').toEqual(''); + }); + + it('should allow custom white-listed void element to be used with closing tag', function() { + expectHTML('').toEqual(''); + }); + + it('should allow custom white-listed attribute', function() { + expectHTML('').toEqual(''); + }); + + it('should ignore custom white-listed SVG element if SVG disabled', function() { + expectHTML('').toEqual(''); + }); + + it('should not allow add custom element after service has been instantiated', inject(function($sanitize) { + $sanitizeProvider.addValidElements(['bar']); + expectHTML('').toEqual(''); + })); + }); + describe('SVG support', function() { beforeEach(module(function($sanitizeProvider) { $sanitizeProvider.enableSvg(true); + $sanitizeProvider.addValidElements({ + svgElements: ['font-face-uri'] + }); })); it('should accept SVG tags', function() { @@ -314,6 +360,10 @@ describe('HTML', function() { }); + it('should allow custom white-listed SVG element', function() { + expectHTML('').toEqual(''); + }); + it('should sanitize SVG xlink:href attribute values', function() { expectHTML('') .toBeOneOf('', From 02f4ca4887f337e87ce668f657c32f49e18beec8 Mon Sep 17 00:00:00 2001 From: frederikprijck Date: Mon, 30 Jan 2017 22:46:22 +0100 Subject: [PATCH 511/883] docs(ngClass): add docs regarding animation for `ngClassEven` and `ngClassOdd` Previously, the documentation has no information regarding using `ngAnimate` together with the `ngClassEven` and `ngClassOdd` directives. This commit adds the same docs used by the `ngClass` directive to the `ngClassEven` and `ngClassOdd` docs and adds an extra example for both `ngClassEven` and `ngClassOdd` that showcases animations. Closes #15654 --- docs/content/guide/animations.ngdoc | 7 +- src/ng/directive/ngClass.js | 124 ++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 3 deletions(-) diff --git a/docs/content/guide/animations.ngdoc b/docs/content/guide/animations.ngdoc index a13661a36a68..22e4df094839 100644 --- a/docs/content/guide/animations.ngdoc +++ b/docs/content/guide/animations.ngdoc @@ -229,11 +229,12 @@ triggered: | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | | {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave | | {@link ng.directive:ngClass#animations ngClass / {{class}​}} | add and remove | -| {@link ng.directive:ngClass#animations ngClassEven / ngClassOdd} | add and remove | +| {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove | +| {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove | | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) | | {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) | -| {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | -| {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | +| {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | +| {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) | For a full breakdown of the steps involved during each animation event, refer to the diff --git a/src/ng/directive/ngClass.js b/src/ng/directive/ngClass.js index e38c7c141938..7b1ca13b2915 100644 --- a/src/ng/directive/ngClass.js +++ b/src/ng/directive/ngClass.js @@ -338,6 +338,12 @@ var ngClassDirective = classDirective('', true); * This directive can be applied only within the scope of an * {@link ng.directive:ngRepeat ngRepeat}. * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#addClass addClass} | just before the class is applied to the element | + * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element | + * * @element ANY * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result * of the evaluation can be a string representing space delimited class names or an array. @@ -370,6 +376,62 @@ var ngClassDirective = classDirective('', true); }); + * + *
+ * @example + * An example on how to implement animations using `ngClassOdd`: + * + + +
+ +
+ + + + +
{{ item }}
+
+
+ + .odd { + background: rgba(255, 255, 0, 0.25); + } + + .odd-add, .odd-remove { + transition: 1.5s; + } + + + it('should add new entries to the beginning of the list', function() { + var button = element(by.buttonText('Add item')); + var rows = element.all(by.repeater('item in items')); + + expect(rows.count()).toBe(4); + expect(rows.get(0).getText()).toBe('Item 3'); + expect(rows.get(1).getText()).toBe('Item 2'); + + button.click(); + + expect(rows.count()).toBe(5); + expect(rows.get(0).getText()).toBe('Item 4'); + expect(rows.get(1).getText()).toBe('Item 3'); + }); + + it('should add odd class to odd entries', function() { + var button = element(by.buttonText('Add item')); + var rows = element.all(by.repeater('item in items')); + + expect(rows.get(0).getAttribute('class')).toMatch(/odd/); + expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/); + + button.click(); + + expect(rows.get(0).getAttribute('class')).toMatch(/odd/); + expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/); + }); + +
*/ var ngClassOddDirective = classDirective('Odd', 0); @@ -386,6 +448,12 @@ var ngClassOddDirective = classDirective('Odd', 0); * This directive can be applied only within the scope of an * {@link ng.directive:ngRepeat ngRepeat}. * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#addClass addClass} | just before the class is applied to the element | + * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element | + * * @element ANY * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The * result of the evaluation can be a string representing space delimited class names or an array. @@ -418,5 +486,61 @@ var ngClassOddDirective = classDirective('Odd', 0); }); + * + *
+ * @example + * An example on how to implement animations using `ngClassEven`: + * + + +
+ +
+ + + + +
{{ item }}
+
+
+ + .even { + background: rgba(255, 255, 0, 0.25); + } + + .even-add, .even-remove { + transition: 1.5s; + } + + + it('should add new entries to the beginning of the list', function() { + var button = element(by.buttonText('Add item')); + var rows = element.all(by.repeater('item in items')); + + expect(rows.count()).toBe(4); + expect(rows.get(0).getText()).toBe('Item 3'); + expect(rows.get(1).getText()).toBe('Item 2'); + + button.click(); + + expect(rows.count()).toBe(5); + expect(rows.get(0).getText()).toBe('Item 4'); + expect(rows.get(1).getText()).toBe('Item 3'); + }); + + it('should add even class to even entries', function() { + var button = element(by.buttonText('Add item')); + var rows = element.all(by.repeater('item in items')); + + expect(rows.get(0).getAttribute('class')).not.toMatch(/even/); + expect(rows.get(1).getAttribute('class')).toMatch(/even/); + + button.click(); + + expect(rows.get(0).getAttribute('class')).not.toMatch(/even/); + expect(rows.get(1).getAttribute('class')).toMatch(/even/); + }); + +
*/ var ngClassEvenDirective = classDirective('Even', 1); From e4e2024d1c0860b142a915fab3f7beff975aa048 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 8 Feb 2018 17:59:36 +0100 Subject: [PATCH 512/883] chore(code.angularjs.org): increase the cache duration This is already set, but wasn't checked in --- scripts/code.angularjs.org-firebase/functions/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/code.angularjs.org-firebase/functions/index.js b/scripts/code.angularjs.org-firebase/functions/index.js index 90f02fc786eb..33f7ba04df7d 100644 --- a/scripts/code.angularjs.org-firebase/functions/index.js +++ b/scripts/code.angularjs.org-firebase/functions/index.js @@ -6,8 +6,8 @@ const path = require('path'); const gcsBucketId = `${process.env.GCLOUD_PROJECT}.appspot.com`; -const BROWSER_CACHE_DURATION = 300; -const CDN_CACHE_DURATION = 600; +const BROWSER_CACHE_DURATION = 60 * 10; +const CDN_CACHE_DURATION = 60 * 60 * 12; function sendStoredFile(request, response) { let filePathSegments = request.path.split('/').filter((segment) => { From 3ecb00115a95bce3add50680b452436fbf213d8c Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 5 Feb 2018 19:26:19 +0100 Subject: [PATCH 513/883] chore(docs.angularjs.org): serve xml files (sitemap) --- scripts/docs.angularjs.org-firebase/firebase.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index 5f5d70dc02d6..91f9a778b634 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -23,7 +23,7 @@ "destination": "/index-production.html" }, { - "source": "**/*!(.jpg|.jpeg|.gif|.png|.html|.js|.map|.json|.css|.svg|.ttf|.txt|.woff|.woff2|.eot)", + "source": "**/*!(.jpg|.jpeg|.gif|.png|.html|.js|.map|.json|.css|.svg|.ttf|.txt|.woff|.woff2|.eot|.xml)", "destination": "/index-production.html" } ] From 3e7a87d7d1be2afea16d0863040fe51e26326d6f Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 12 Jan 2018 13:30:05 +0100 Subject: [PATCH 514/883] fix(browserTrigger): support CompositionEvent --- src/ngMock/browserTrigger.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ngMock/browserTrigger.js b/src/ngMock/browserTrigger.js index 196772d1e3e9..eb80e15964dc 100644 --- a/src/ngMock/browserTrigger.js +++ b/src/ngMock/browserTrigger.js @@ -132,6 +132,24 @@ evnt.keyCode = eventData.keyCode; evnt.charCode = eventData.charCode; evnt.which = eventData.which; + } else if (/composition/.test(eventType)) { + try { + evnt = new window.CompositionEvent(eventType, { + data: eventData.data + }); + } catch (e) { + // Support: IE9+ + evnt = window.document.createEvent('CompositionEvent', {}); + evnt.initCompositionEvent( + eventType, + eventData.bubbles, + eventData.cancelable, + window, + eventData.data, + null + ); + } + } else { evnt = window.document.createEvent('MouseEvents'); x = x || 0; From 2789ccbcf9666b64211c08b188b168175109f563 Mon Sep 17 00:00:00 2001 From: Jae Ik Lee Date: Tue, 26 Dec 2017 03:11:51 +0900 Subject: [PATCH 515/883] fix(input): fix composition mode in IE for Korean input Fixes #6656 Closes #16273 --- src/ng/directive/input.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 7d1bec7cfe9d..3b841d25a348 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1248,6 +1248,16 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { composing = true; }); + // Support: IE9+ + element.on('compositionupdate', function(ev) { + // End composition when ev.data is empty string on 'compositionupdate' event. + // When the input de-focusses (e.g. by clicking away), IE triggers 'compositionupdate' + // instead of 'compositionend'. + if (isUndefined(ev.data) || ev.data === '') { + composing = false; + } + }); + element.on('compositionend', function() { composing = false; listener(); From c484213180470c2a8044eeb09dfdc5ef11099bc8 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 12 Jan 2018 13:30:33 +0100 Subject: [PATCH 516/883] test(input): add test for IE composition bug --- test/ng/directive/inputSpec.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 93d2184f969d..8c86b44ceada 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -134,6 +134,20 @@ describe('input', function() { browserTrigger(inputElm, 'compositionend'); expect($rootScope.name).toEqual('caitp'); }); + + + it('should end composition on "compositionupdate" when event.data is ""', function() { + // This tests a bug workaround for IE9-11 + // During composition, when an input is de-focussed by clicking away from it, + // the compositionupdate event is called with '', followed by a change event. + var inputElm = helper.compileInput(''); + browserTrigger(inputElm, 'compositionstart'); + helper.changeInputValueTo('caitp'); + expect($rootScope.name).toBeUndefined(); + browserTrigger(inputElm, 'compositionupdate', {data: ''}); + browserTrigger(inputElm, 'change'); + expect($rootScope.name).toEqual('caitp'); + }); }); From 9a0f1abddac5670a0d6efa7689f04d594bb9f274 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 8 Feb 2018 23:43:00 +0100 Subject: [PATCH 517/883] chore(docs.angularjs.org): deploy sitemap.xml Closes #16445 --- Gruntfile.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 6d5b9e09b3df..08ff823f0145 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -162,7 +162,8 @@ module.exports = function(grunt) { clean: { build: ['build'], - tmp: ['tmp'] + tmp: ['tmp'], + deploy: ['uploadDocs', 'uploadCode'] }, eslint: { @@ -326,7 +327,7 @@ module.exports = function(grunt) { files: [ // The source files are needed by the embedded examples in the docs app. { - src: 'build/angular*.{js,js.map,min.js}', + src: ['build/angular*.{js,js.map,min.js}', 'build/sitemap.xml'], dest: 'uploadDocs/', expand: true, flatten: true @@ -363,10 +364,6 @@ module.exports = function(grunt) { }, shell: { - // Travis expects the firebase.json in the repository root, but we have it in a sub-folder - 'symlink-firebase-docs': { - command: 'ln -s ./scripts/docs.angularjs.org-firebase/firebase.json ./firebase.json' - }, 'install-node-dependencies': { command: 'yarn' }, From 32b1a0c5807a6b3148543676b920543e32162c69 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 25 Jan 2018 19:35:04 +0100 Subject: [PATCH 518/883] chore(docs.angularjs.org): actually fix deployment When a file is symlinked, relative paths obviously aren't correct anymore. This error was masked because Travis didn't fail the job when Firebase couldn't find the public folder. To fix, we copy the file and adjust the folder path --- Gruntfile.js | 2 +- lib/grunt/plugins.js | 5 +++++ lib/grunt/utils.js | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 08ff823f0145..19732e7e1842 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -463,7 +463,7 @@ module.exports = function(grunt) { 'package', 'compress:deployFirebaseCode', 'copy:deployFirebaseCode', - 'shell:symlink-firebase-docs', + 'firebaseDocsJsonForTravis', 'copy:deployFirebaseDocs' ]); grunt.registerTask('default', ['package']); diff --git a/lib/grunt/plugins.js b/lib/grunt/plugins.js index 2d71b85501eb..7e5dc290b533 100644 --- a/lib/grunt/plugins.js +++ b/lib/grunt/plugins.js @@ -62,4 +62,9 @@ module.exports = function(grunt) { grunt.registerTask('collect-errors', 'Combine stripped error files', function() { util.collectErrors(); }); + + grunt.registerTask('firebaseDocsJsonForTravis', function() { + util.firebaseDocsJsonForTravis(); + }); + }; diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 52dbcde8fa5e..80e529186514 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -292,5 +292,16 @@ module.exports = { } next(); }; + }, + + // Our Firebase projects are in subfolders, but Travis expects them in the root, + // so we need to modify the upload folder path and copy the file into the root + firebaseDocsJsonForTravis: function() { + var fileName = 'scripts/docs.angularjs.org-firebase/firebase.json'; + var json = grunt.file.readJSON(fileName); + + json.hosting.public = 'uploadDocs'; + + grunt.file.write('firebase.json', JSON.stringify(json)); } }; From a7a9688962039fb5af5e073faddbc239a9479e9b Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Sun, 11 Feb 2018 18:15:23 +0200 Subject: [PATCH 519/883] fix(docs): fix `@media` breakpoints for small/extra small devices Previously, our custom styles used `@media` breakpoints for small/extra small devices that were off-by-one from [Bootstrap breakpoints](https://getbootstrap.com/docs/3.3/css/#responsive-utilities-classes) (767px vs 768px). This caused the site to not be displayed correctly on these exact sizes, which affected for example all iPad devices (whose screens are exactly 768px wide). This commit fixes it by making our breakpoints match those of Bootstrap. Fixes #16448 Closes #16449 --- docs/app/assets/css/docs.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/app/assets/css/docs.css b/docs/app/assets/css/docs.css index ba69449090eb..54d81ada753d 100644 --- a/docs/app/assets/css/docs.css +++ b/docs/app/assets/css/docs.css @@ -713,14 +713,14 @@ ul.events > li { margin-right: 5px; } -@media only screen and (min-width: 769px) { +@media only screen and (min-width: 768px) { [ng-include="partialPath"].ng-hide { display: block !important; visibility: hidden; } } -@media only screen and (min-width: 769px) and (max-width: 991px) { +@media only screen and (min-width: 768px) and (max-width: 991px) { .main-body-grid { margin-top: 160px; } @@ -729,7 +729,7 @@ ul.events > li { } } -@media only screen and (max-width : 768px) { +@media only screen and (max-width: 767px) { .picker, .picker select { width: auto; display: block; From 9f1793fd2dc92225991f9db5ec661af6f86206ca Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 12 Feb 2018 12:26:32 +0100 Subject: [PATCH 520/883] chore(eslint): allow ES6 for node scripts --- .eslintrc-node.json | 9 +++++++-- Gruntfile.js | 1 + package.json | 1 + yarn.lock | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.eslintrc-node.json b/.eslintrc-node.json index 643f345d88e0..c16a8a883837 100644 --- a/.eslintrc-node.json +++ b/.eslintrc-node.json @@ -1,8 +1,13 @@ { "extends": "./.eslintrc-base.json", - "env": { "browser": false, "node": true - } + }, + "parserOptions": { + "ecmaVersion": 2017 + }, + "plugins": [ + "promise" + ] } diff --git a/Gruntfile.js b/Gruntfile.js index 19732e7e1842..0d6dc6b956be 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -174,6 +174,7 @@ module.exports = function(grunt) { 'docs/**/*.js', 'lib/**/*.js', 'scripts/**/*.js', + '!scripts/*/*/node_modules/**', 'src/**/*.js', 'test/**/*.js', 'i18n/**/*.js', diff --git a/package.json b/package.json index 255b569f30a6..c82bb19a829f 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "cz-conventional-changelog": "1.1.4", "dgeni": "^0.4.0", "dgeni-packages": "^0.16.4", + "eslint-plugin-promise": "^3.6.0", "event-stream": "~3.1.0", "glob": "^6.0.1", "google-code-prettify": "1.0.1", diff --git a/yarn.lock b/yarn.lock index 62016649857b..f635a238b14d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1994,6 +1994,10 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-plugin-promise@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75" + eslint@^3.0.0: version "3.15.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.15.0.tgz#bdcc6a6c5ffe08160e7b93c066695362a91e30f2" From e1e2100e66acf79bafed7e07fbbdf7d865b2b035 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 9 Feb 2018 20:18:29 +0100 Subject: [PATCH 521/883] chore(code.angularjs.org): don't gzip compressed image files --- Gruntfile.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 0d6dc6b956be..5cc2dd778620 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -315,12 +315,12 @@ module.exports = function(grunt) { }, deployFirebaseCode: { files: [ - // the zip file should not be compressed again. + // copy files that are not handled by compress { - src: 'build/*.zip', + cwd: 'build', + src: '**/*.{zip,jpg,jpeg,png}', dest: 'uploadCode/' + deployVersion + '/', - expand: true, - flatten: true + expand: true } ] }, @@ -357,7 +357,8 @@ module.exports = function(grunt) { options: { mode: 'gzip' }, - src: ['**', '!*.zip'], + // Already compressed files should not be compressed again + src: ['**', '!**/*.{zip,png,jpeg,jpg}'], cwd: 'build', expand: true, dest: 'uploadCode/' + deployVersion + '/' From 9196c80c3394d0afcfc4f3ab0ec881d501190fe3 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 12 Feb 2018 10:47:42 +0100 Subject: [PATCH 522/883] chore(deploy): rename deploy folders --- .gitignore | 1 + .travis.yml | 2 +- Gruntfile.js | 17 +++++++++++------ lib/grunt/utils.js | 6 ++++-- .../docs.angularjs.org-firebase/firebase.json | 2 +- scripts/travis/build.sh | 2 +- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 2da934151e89..588beda3f172 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /build/ +/deploy/ /benchpress-build/ .DS_Store gen_docs.disable diff --git a/.travis.yml b/.travis.yml index 4c226f02fe85..3199f7718d4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,7 +94,7 @@ jobs: secret_access_key: secure: tHIFdSq55qkyZf9zT/3+VkhUrTvOTMuswxXU3KyWaBrSieZqG0UnUDyNm+n3lSfX95zEl/+rJAWbfvhVSxZi13ndOtvRF+MdI1cvow2JynP0aDSiPffEvVrZOmihD6mt2SlMfhskr5FTduQ69kZG6DfLcve1PPDaIwnbOv3phb8= bucket: code-angularjs-org-338b8.appspot.com - local-dir: uploadCode + local-dir: deploy/code detect_encoding: true # detects gzip compression on: repo: angular/angular.js diff --git a/Gruntfile.js b/Gruntfile.js index 5cc2dd778620..c42113fc2ee4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -163,7 +163,10 @@ module.exports = function(grunt) { clean: { build: ['build'], tmp: ['tmp'], - deploy: ['uploadDocs', 'uploadCode'] + deploy: [ + 'deploy/docs', + 'deploy/code' + ] }, eslint: { @@ -319,7 +322,7 @@ module.exports = function(grunt) { { cwd: 'build', src: '**/*.{zip,jpg,jpeg,png}', - dest: 'uploadCode/' + deployVersion + '/', + dest: 'deploy/code/' + deployVersion + '/', expand: true } ] @@ -329,14 +332,16 @@ module.exports = function(grunt) { // The source files are needed by the embedded examples in the docs app. { src: ['build/angular*.{js,js.map,min.js}', 'build/sitemap.xml'], - dest: 'uploadDocs/', + dest: 'deploy/docs/', expand: true, flatten: true }, { cwd: 'build/docs', src: '**', - dest: 'uploadDocs/', + dest: 'deploy/docs/', + expand: true + } expand: true } ] @@ -361,7 +366,7 @@ module.exports = function(grunt) { src: ['**', '!**/*.{zip,png,jpeg,jpg}'], cwd: 'build', expand: true, - dest: 'uploadCode/' + deployVersion + '/' + dest: 'deploy/code/' + deployVersion + '/' } }, @@ -461,7 +466,7 @@ module.exports = function(grunt) { 'merge-conflict', 'eslint' ]); - grunt.registerTask('prepareFirebaseDeploy', [ + grunt.registerTask('prepareDeploy', [ 'package', 'compress:deployFirebaseCode', 'copy:deployFirebaseCode', diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 80e529186514..c5b16946ba8d 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -297,10 +297,12 @@ module.exports = { // Our Firebase projects are in subfolders, but Travis expects them in the root, // so we need to modify the upload folder path and copy the file into the root firebaseDocsJsonForTravis: function() { - var fileName = 'scripts/docs.angularjs.org-firebase/firebase.json'; + var docsScriptFolder = 'scripts/docs.angularjs.org-firebase/'; + + var fileName = docsScriptFolder + 'firebase.json'; var json = grunt.file.readJSON(fileName); - json.hosting.public = 'uploadDocs'; + json.hosting.public = 'deploy/docs'; grunt.file.write('firebase.json', JSON.stringify(json)); } diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index 91f9a778b634..abb70329f815 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -1,6 +1,6 @@ { "hosting": { - "public": "../../uploadDocs", + "public": "../../deploy/docs", "ignore": [ "/index.html", "/index-debug.html", diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index fdf94d8f13de..980855388492 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -79,7 +79,7 @@ case "$JOB" in fi if [[ "$DEPLOY_DOCS" == true || "$DEPLOY_CODE" == true ]]; then - grunt prepareFirebaseDeploy + grunt prepareDeploy else echo "Skipping deployment build because conditions have not been met." fi From 75bf199421011466b799b2eeec5223c0a9143516 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 12 Feb 2018 10:49:19 +0100 Subject: [PATCH 523/883] chore(docs.angularjs.org): serve snapshots for googlebot This commit restores serving the plain partials (content) when a docs page is accessed with ?_escaped_fragment_=. The Google Ajax Crawler accesses these urls when the page has `` is set. During the migration to Firebase, this was lost, which resulted in Google dropping the docs almost completely from the index. We are using a Firebase cloud function to serve the partials. Since we cannot access the static hosted files from the function, we have to deploy them as part of the function directory instead, from which they can be read. Related to #16432 Related to #16417 --- Gruntfile.js | 17 +- lib/grunt/utils.js | 5 +- .../docs.angularjs.org-firebase/firebase.json | 11 +- .../functions/index.js | 49 + .../functions/package-lock.json | 4265 +++++++++++++++++ .../functions/package.json | 21 + .../readme.firebase.docs.md | 17 +- 7 files changed, 4376 insertions(+), 9 deletions(-) create mode 100644 scripts/docs.angularjs.org-firebase/functions/index.js create mode 100644 scripts/docs.angularjs.org-firebase/functions/package-lock.json create mode 100644 scripts/docs.angularjs.org-firebase/functions/package.json diff --git a/Gruntfile.js b/Gruntfile.js index c42113fc2ee4..ba5efa0d8f09 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,6 +13,8 @@ var semver = require('semver'); var exec = require('shelljs').exec; var pkg = require(__dirname + '/package.json'); +var docsScriptFolder = 'scripts/docs.angularjs.org-firebase'; + // Node.js version checks if (!semver.satisfies(process.version, pkg.engines.node)) { reportOrFail('Invalid node version (' + process.version + '). ' + @@ -165,7 +167,8 @@ module.exports = function(grunt) { tmp: ['tmp'], deploy: [ 'deploy/docs', - 'deploy/code' + 'deploy/code', + docsScriptFolder + '/functions/html' ] }, @@ -341,7 +344,17 @@ module.exports = function(grunt) { src: '**', dest: 'deploy/docs/', expand: true - } + }, + { + src: ['build/docs/index-production.html'], + dest: docsScriptFolder + '/functions/content', + expand: true, + flatten: true + }, + { + cwd: 'build/docs', + src: 'partials/**', + dest: docsScriptFolder + '/functions/content', expand: true } ] diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index c5b16946ba8d..64ddc6f185ec 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -297,12 +297,13 @@ module.exports = { // Our Firebase projects are in subfolders, but Travis expects them in the root, // so we need to modify the upload folder path and copy the file into the root firebaseDocsJsonForTravis: function() { - var docsScriptFolder = 'scripts/docs.angularjs.org-firebase/'; + var docsScriptFolder = 'scripts/docs.angularjs.org-firebase'; - var fileName = docsScriptFolder + 'firebase.json'; + var fileName = docsScriptFolder + '/firebase.json'; var json = grunt.file.readJSON(fileName); json.hosting.public = 'deploy/docs'; + json.functions.source = docsScriptFolder + '/functions'; grunt.file.write('firebase.json', JSON.stringify(json)); } diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index abb70329f815..880a5eca86de 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -23,9 +23,14 @@ "destination": "/index-production.html" }, { - "source": "**/*!(.jpg|.jpeg|.gif|.png|.html|.js|.map|.json|.css|.svg|.ttf|.txt|.woff|.woff2|.eot|.xml)", - "destination": "/index-production.html" + "source": "**/*!(.@(jpg|jpeg|gif|png|html|js|map|json|css|svg|ttf|txt|woff|woff2|eot|xml))", + "function": "sendFile" } ] + }, + "functions": { + "predeploy": [ + "npm --prefix $RESOURCE_DIR run lint" + ] } -} \ No newline at end of file +} diff --git a/scripts/docs.angularjs.org-firebase/functions/index.js b/scripts/docs.angularjs.org-firebase/functions/index.js new file mode 100644 index 000000000000..b86eb32f642a --- /dev/null +++ b/scripts/docs.angularjs.org-firebase/functions/index.js @@ -0,0 +1,49 @@ +'use strict'; + +const functions = require('firebase-functions'); +const fs = require('fs'); + +const BROWSER_CACHE_DURATION = 60 * 60; +const CDN_CACHE_DURATION = 60 * 60 * 12; + +const headers = { + 'Cache-Control': `public max-age=${BROWSER_CACHE_DURATION} s-maxage=${CDN_CACHE_DURATION}` +}; + +const buildSnapshot = data => ` + + + + + + + + ${data} + + `; + +function sendFile(request, response) { + + const snapshotRequested = typeof request.query._escaped_fragment_ !== 'undefined'; + const filePath = `content/${snapshotRequested ? `partials${request.path}` : 'index-production'}.html`; + + if (snapshotRequested) { + fs.readFile(filePath, {encoding: 'utf8'}, (error, data) => { + if (error) { + response + .status(404) + .end(); + } else { + response + .set(headers) + .send(buildSnapshot(data)); + } + }); + } else { + response + .set(headers) + .sendFile(filePath, {root: __dirname}); + } +} + +exports.sendFile = functions.https.onRequest(sendFile); diff --git a/scripts/docs.angularjs.org-firebase/functions/package-lock.json b/scripts/docs.angularjs.org-firebase/functions/package-lock.json new file mode 100644 index 000000000000..913ba90ff890 --- /dev/null +++ b/scripts/docs.angularjs.org-firebase/functions/package-lock.json @@ -0,0 +1,4265 @@ +{ + "name": "functions", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@firebase/app": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.1.8.tgz", + "integrity": "sha512-LkXMugZ2Z2S0r9zH62YNRhCscstFqJuufEjJmb/XWCTjCKzJZKdbE/6A+WNTitNSHgAkKEF0NoGsIuyhYAubkg==", + "requires": { + "@firebase/app-types": "0.1.1", + "@firebase/util": "0.1.8" + } + }, + "@firebase/app-types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.1.1.tgz", + "integrity": "sha512-0CmY/orojHIJiTyDXUqrAtCSmk2nWw7h7qamJUPcBRgAIfc3ZsjFBLo1zj0sRVzZYbTWS9cKBC8tnpFZlEMLPw==" + }, + "@firebase/database": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.1.9.tgz", + "integrity": "sha512-w7bsItAvUDMGDX7v2NTIHmt5yRYDWAdUKqC7p152dopGw6AAFgxhR5jAikq7qB2UOPB1vRy8KHlcMk3RnF6cXw==", + "requires": { + "@firebase/database-types": "0.1.1", + "@firebase/util": "0.1.8", + "faye-websocket": "0.11.1" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "requires": { + "websocket-driver": "0.7.0" + } + } + } + }, + "@firebase/database-types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.1.1.tgz", + "integrity": "sha512-LbLnwXFeQuxQrsuUccbiXX4j3wdajLPNcbivzypJhww+VU4W/4grnbVn/zPlRlMcG6jTwSyBnjdtJFKMSeNU+A==" + }, + "@firebase/util": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.1.8.tgz", + "integrity": "sha512-SfWLSfp1MXb5ItG3wGfdxxIDzFMcjq2E0iz9C7sstzD3mJ8/q55Sd8esAL3VQx5jD/hbfKUypsBczr5A0ML7Tw==" + }, + "@google-cloud/common": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.15.1.tgz", + "integrity": "sha512-cnVtHLvyiSQvb1RzXWDp7PA1sA8Jmc47+wp/xwHwdGOlQZfKog5iluZ0C/LB8iklFXpcTwlNMorqLuZ/qH0DDA==", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.8.2", + "is": "3.2.1", + "log-driver": "1.2.6", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "3.3.1", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "@google-cloud/common-grpc": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@google-cloud/common-grpc/-/common-grpc-0.5.5.tgz", + "integrity": "sha512-wgtuBcgTZ7cUMGQV9MSz4y0+FReLqdsOOgzOifu+lsnRh9qsMEZJ9sBDLB6NrRxrvcAHZc4ayiBx7B7i5cDYoA==", + "requires": { + "@google-cloud/common": "0.16.1", + "dot-prop": "4.2.0", + "duplexify": "3.5.3", + "extend": "3.0.1", + "grpc": "1.7.3", + "is": "3.2.1", + "modelo": "4.2.3", + "retry-request": "3.3.1", + "through2": "2.0.3" + }, + "dependencies": { + "@google-cloud/common": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.16.1.tgz", + "integrity": "sha512-1sufDsSfgJ7fuBLq+ux8t3TlydMlyWl9kPZx2WdLINkGtf5RjvXX6EWYZiCMKe8flJ3oC0l95j5atN2uX5n3rg==", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.9.3", + "is": "3.2.1", + "log-driver": "1.2.5", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.83.0", + "retry-request": "3.3.1", + "split-array-stream": "1.0.3", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "gcp-metadata": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.4.1.tgz", + "integrity": "sha512-yFE7v+NyoMiTOi2L6r8q87eVbiZCKooJNPKXTHhBStga8pwwgWofK9iHl00qd0XevZxcpk7ORaEL/ALuTvlaGQ==", + "requires": { + "extend": "3.0.1", + "retry-request": "3.3.1" + } + }, + "google-auto-auth": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.9.3.tgz", + "integrity": "sha512-TbOZZs0WJOolrRmdQLK5qmWdOJQFG1oPnxcIBbAwL7XCWcv3XgZ9gHJ6W4byrdEZT8TahNFgMfkHd73mqxM9dw==", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.4.1", + "google-auth-library": "0.12.0", + "request": "2.83.0" + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=" + } + } + }, + "@google-cloud/firestore": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-0.11.2.tgz", + "integrity": "sha512-Dp5Im5y6LfJ2OuuGN/PX/w7+LdKPRhKbhgNOaUjreIULo7Ya9AyRMYn/E+w8Rm+b3CZXM7fzVpkkdg9Thq8uUQ==", + "requires": { + "@google-cloud/common": "0.15.1", + "@google-cloud/common-grpc": "0.5.5", + "bun": "0.0.12", + "extend": "3.0.1", + "functional-red-black-tree": "1.0.1", + "google-gax": "0.14.5", + "is": "3.2.1", + "safe-buffer": "5.1.1", + "through2": "2.0.3" + } + }, + "@google-cloud/storage": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.5.2.tgz", + "integrity": "sha512-E97x2oZr9w0N26H0LtyjR3XLFSLYXH5D8y8HwEZRWQnNVF9sO+x16MEhdHFdFclgdx687eGeCYbDVKpP+dKb6w==", + "requires": { + "@google-cloud/common": "0.15.1", + "arrify": "1.0.1", + "async": "2.6.0", + "concat-stream": "1.6.0", + "create-error-class": "3.0.2", + "duplexify": "3.5.3", + "extend": "3.0.1", + "gcs-resumable-upload": "0.8.2", + "hash-stream-validation": "0.2.1", + "is": "3.2.1", + "mime-types": "2.1.17", + "once": "1.4.0", + "pumpify": "1.4.0", + "request": "2.83.0", + "safe-buffer": "5.1.1", + "snakeize": "0.1.0", + "stream-events": "1.0.2", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/body-parser": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.16.8.tgz", + "integrity": "sha512-BdN2PXxOFnTXFcyONPW6t0fHjz2fvRZHVMFpaS0wYr+Y8fWEaNOs4V8LEu/fpzQlMx+ahdndgTaGTwPC+J/EeA==", + "requires": { + "@types/express": "4.11.1", + "@types/node": "8.9.3" + } + }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==" + }, + "@types/express": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.11.1.tgz", + "integrity": "sha512-ttWle8cnPA5rAelauSWeWJimtY2RsUf2aspYZs7xPHiWgOlPn6nnUfBMtrkcnjFJuIHJF4gNOdVvpLK2Zmvh6g==", + "requires": { + "@types/body-parser": "1.16.8", + "@types/express-serve-static-core": "4.11.1", + "@types/serve-static": "1.13.1" + } + }, + "@types/express-serve-static-core": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.11.1.tgz", + "integrity": "sha512-EehCl3tpuqiM8RUb+0255M8PhhSwTtLfmO7zBBdv0ay/VTd/zmrqDfQdZFsa5z/PVMbH2yCMZPXsnrImpATyIw==", + "requires": { + "@types/events": "1.1.0", + "@types/node": "8.9.3" + } + }, + "@types/google-cloud__storage": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@types/google-cloud__storage/-/google-cloud__storage-1.1.7.tgz", + "integrity": "sha512-010Llp+5ze+XWWmZuLDxs0pZgFjOgtJQVt9icJ0Ed67ZFLq7PnXkYx8x/k9nwDojR5/X4XoLPNqB1F627TScdQ==", + "requires": { + "@types/node": "8.9.3" + } + }, + "@types/jsonwebtoken": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.5.tgz", + "integrity": "sha512-8CIcK1Vzq4w5TJyJYkLVhqASmCo1FSO1XIPQM1qv+Xo2nnb9RoRHxx8pkIzSZ4Tm9r3V4ZyFbF/fBewNPdclwA==", + "requires": { + "@types/node": "8.9.3" + } + }, + "@types/lodash": { + "version": "4.14.102", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.102.tgz", + "integrity": "sha512-k/SxycYmVc6sYo6kzm8cABHcbMs9MXn6jYsja1hLvZ/x9e31VHRRn+1UzWdpv6doVchphvKaOsZ0VTqbF7zvNg==" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" + }, + "@types/mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, + "@types/node": { + "version": "8.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.3.tgz", + "integrity": "sha512-wqrPE4Uvj2fmL0E5JFQiY7D/5bAKvVUfWTnQ5NEV35ULkAU0j3QuqIi9Qyrytz8M5hsrh8Kijt+FsdLQaZR+IA==" + }, + "@types/serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-jDMH+3BQPtvqZVIcsH700Dfi8Q3MIcEx16g/VdxjoqiGR/NntekB10xdBpirMKnPe9z2C5cBmL0vte0YttOr3Q==", + "requires": { + "@types/express-serve-static-core": "4.11.1", + "@types/mime": "2.0.0" + } + }, + "@types/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha512-Yrz4TPsm/xaw7c39aTISskNirnRJj2W9OVeHv8ooOR9SG8NHEfh4lwvGeN9euzxDyPfBdFkvL/VHIY3kM45OpQ==", + "requires": { + "@types/node": "8.9.3" + } + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + }, + "acorn-es7-plugin": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", + "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arguejs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/arguejs/-/arguejs-0.2.3.tgz", + "integrity": "sha1-tvk59f4OPNHz+T4qqSYkJL8xKvc=" + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.15" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "bun": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/bun/-/bun-0.0.12.tgz", + "integrity": "sha512-Toms18J9DqnT+IfWkwxVTB2EaBprHvjlMWrTIsfX4xbu3ZBqVBwrERU0em1IgtRe04wT+wJxMlKHZok24hrcSQ==", + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "3.2.0" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "call-signature": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", + "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "codecov.io": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/codecov.io/-/codecov.io-0.0.1.tgz", + "integrity": "sha1-JeorCV4enqEYcr36WEIRgTDfeLE=", + "requires": { + "request": "2.42.0", + "urlgrey": "0.4.0" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "requires": { + "hoek": "0.9.1" + } + }, + "caseless": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", + "integrity": "sha1-gWfBq4OX+1u5X5bSjlqBxQ8kesQ=" + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "optional": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + } + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "optional": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=" + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", + "integrity": "sha1-8ilW8x6nFRqCHl8vsywRPK2Ln2k=", + "optional": true + }, + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=" + }, + "request": { + "version": "2.42.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.42.0.tgz", + "integrity": "sha1-VyvQFIk4VkBArHqxSLlkI6BjMEo=", + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.6.0", + "forever-agent": "0.5.2", + "form-data": "0.1.4", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.4.0", + "qs": "1.2.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "optional": true, + "requires": { + "hoek": "0.9.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + } + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "typedarray": "0.0.6" + } + }, + "configstore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.1.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", + "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=" + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff-match-patch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", + "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=" + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.4", + "stream-shift": "1.0.0" + } + }, + "eastasianwidth": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.1.1.tgz", + "integrity": "sha1-RNZW3p2kFWlEZzNTZfsxR7hXK3w=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "requires": { + "base64url": "2.0.0", + "safe-buffer": "5.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "empower": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/empower/-/empower-1.2.3.tgz", + "integrity": "sha1-bw2nNEf07dg4/sXGAxOoi6XLhSs=", + "requires": { + "core-js": "2.5.3", + "empower-core": "0.6.2" + } + }, + "empower-core": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-0.6.2.tgz", + "integrity": "sha1-Wt71ZgiOMfuoC6CjbfR9cJQWkUQ=", + "requires": { + "call-signature": "0.0.2", + "core-js": "2.5.3" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", + "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.1", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.3", + "esquery": "1.0.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.3.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "eslint-plugin-promise": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "dev": true, + "requires": { + "acorn": "5.4.1", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "espurify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.7.0.tgz", + "integrity": "sha1-HFz2y8zDLm9jk4C9T5kfq5up0iY=", + "requires": { + "core-js": "2.5.3" + } + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.2", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.1", + "vary": "1.1.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", + "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=", + "requires": { + "websocket-driver": "0.7.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "firebase-admin": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-5.8.2.tgz", + "integrity": "sha1-TDkN87b9MlZ9jUVYrASXS+vRV0k=", + "requires": { + "@firebase/app": "0.1.8", + "@firebase/database": "0.1.9", + "@google-cloud/firestore": "0.11.2", + "@google-cloud/storage": "1.5.2", + "@types/google-cloud__storage": "1.1.7", + "@types/node": "8.9.3", + "faye-websocket": "0.9.3", + "jsonwebtoken": "8.1.0", + "node-forge": "0.7.1" + } + }, + "firebase-functions": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-0.8.1.tgz", + "integrity": "sha1-pC/m0kOGLEBq8W4cFrHQqB7CTAM=", + "requires": { + "@types/express": "4.11.1", + "@types/jsonwebtoken": "7.2.5", + "@types/lodash": "4.14.102", + "@types/sha1": "1.1.1", + "express": "4.16.2", + "jsonwebtoken": "7.4.3", + "lodash": "4.17.5", + "sha1": "1.1.1" + }, + "dependencies": { + "jsonwebtoken": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", + "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=", + "requires": { + "joi": "6.10.1", + "jws": "3.1.4", + "lodash.once": "4.1.1", + "ms": "2.1.1", + "xtend": "4.0.1" + } + } + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "gcp-metadata": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.3.1.tgz", + "integrity": "sha512-5kJPX/RXuqoLmHiOOgkSDk/LI0QaXpEvZ3pvQP4ifjGGDKZKVSOjL/GcDjXA5kLxppFCOjmmsu0Uoop9d1upaQ==", + "requires": { + "extend": "3.0.1", + "retry-request": "3.3.1" + } + }, + "gcs-resumable-upload": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.8.2.tgz", + "integrity": "sha512-PBl1OFABYxubxfYPh000I0+JLbQzBRtNqxzgxYboIQk2tdw7BvjJ2dVukk3YH4QM6GiUwqItyNqWBuxjLH8GhA==", + "requires": { + "buffer-equal": "1.0.0", + "configstore": "3.1.1", + "google-auto-auth": "0.7.2", + "pumpify": "1.4.0", + "request": "2.83.0", + "stream-events": "1.0.2", + "through2": "2.0.3" + }, + "dependencies": { + "google-auth-library": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-0.10.0.tgz", + "integrity": "sha1-bhW6vuhf0d0U2NEoopW2g41SE24=", + "requires": { + "gtoken": "1.2.3", + "jws": "3.1.4", + "lodash.noop": "3.0.1", + "request": "2.83.0" + } + }, + "google-auto-auth": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.7.2.tgz", + "integrity": "sha512-ux2n2AE2g3+vcLXwL4dP/M12SFMRX5dzCzBfhAEkTeAB7dpyGdOIEj7nmUx0BHKaCcUQrRWg9kT63X/Mmtk1+A==", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.10.0", + "request": "2.83.0" + } + } + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "google-auth-library": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-0.12.0.tgz", + "integrity": "sha512-79qCXtJ1VweBmmLr4yLq9S4clZB2p5Y+iACvuKk9gu4JitEnPc+bQFmYvtCYehVR44MQzD1J8DVmYW2w677IEw==", + "requires": { + "gtoken": "1.2.3", + "jws": "3.1.4", + "lodash.isstring": "4.0.1", + "lodash.merge": "4.6.1", + "request": "2.83.0" + } + }, + "google-auto-auth": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.8.2.tgz", + "integrity": "sha512-W91J1paFbyG45gpDWdTu9tKDxbiTDWYkOAxytNVF4oHVVgTCBV/8+lWdjj/6ldjN3eb+sEd9PKJBjm0kmCxvcw==", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.3.1", + "google-auth-library": "0.12.0", + "request": "2.83.0" + } + }, + "google-gax": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.14.5.tgz", + "integrity": "sha512-3A6KbrtLDavrqZnnzurnSydRIJnyH+2Sm56fAvXciQ/62aEnSDaR43MCgWhtReCLVjeFjBiCEIdX5zV0LVLVBg==", + "requires": { + "extend": "3.0.1", + "globby": "7.1.1", + "google-auto-auth": "0.9.3", + "google-proto-files": "0.14.2", + "grpc": "1.7.3", + "is-stream-ended": "0.1.3", + "lodash": "4.17.5", + "protobufjs": "6.8.4", + "readable-stream": "2.3.4", + "through2": "2.0.3" + }, + "dependencies": { + "gcp-metadata": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.4.1.tgz", + "integrity": "sha512-yFE7v+NyoMiTOi2L6r8q87eVbiZCKooJNPKXTHhBStga8pwwgWofK9iHl00qd0XevZxcpk7ORaEL/ALuTvlaGQ==", + "requires": { + "extend": "3.0.1", + "retry-request": "3.3.1" + } + }, + "google-auto-auth": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.9.3.tgz", + "integrity": "sha512-TbOZZs0WJOolrRmdQLK5qmWdOJQFG1oPnxcIBbAwL7XCWcv3XgZ9gHJ6W4byrdEZT8TahNFgMfkHd73mqxM9dw==", + "requires": { + "async": "2.6.0", + "gcp-metadata": "0.4.1", + "google-auth-library": "0.12.0", + "request": "2.83.0" + } + }, + "protobufjs": { + "version": "6.8.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.4.tgz", + "integrity": "sha512-d+WZqUDXKM+oZhr8yprAtQW07q08p9/V35AJ2J1fds+r903S/aH9P8uO1gmTwozOKugt2XCjdrre3OxuPRGkGg==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.9.3", + "long": "3.2.0" + } + } + } + }, + "google-p12-pem": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-0.1.2.tgz", + "integrity": "sha1-M8RqsCGqc0+gMys5YKmj/8svMXc=", + "requires": { + "node-forge": "0.7.1" + } + }, + "google-proto-files": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.14.2.tgz", + "integrity": "sha512-wwm2TIlfTgAjDbjrxAb3akznO7vBM0PRLS6Xf2QfR3L7b0p+szD3iwOW0wMSFl3B0UbLv27hUVk+clePqCVmXA==", + "requires": { + "globby": "7.1.1", + "power-assert": "1.4.4", + "prettier": "1.10.2", + "protobufjs": "6.8.4" + }, + "dependencies": { + "protobufjs": { + "version": "6.8.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.4.tgz", + "integrity": "sha512-d+WZqUDXKM+oZhr8yprAtQW07q08p9/V35AJ2J1fds+r903S/aH9P8uO1gmTwozOKugt2XCjdrre3OxuPRGkGg==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.9.3", + "long": "3.2.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grpc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.7.3.tgz", + "integrity": "sha512-7zXQJlDXMr/ZaDqdaIchgclViyoWo8GQxZSmFUAxR8GwSr28b6/BTgF221WG+2W693jpp74XJ/+I9DcPXsgt9Q==", + "requires": { + "arguejs": "0.2.3", + "lodash": "4.17.5", + "nan": "2.8.0", + "node-pre-gyp": "0.6.39", + "protobufjs": "5.0.2" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "bundled": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.1", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.17", + "bundled": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.2", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.1" + }, + "dependencies": { + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.0.9", + "osenv": "0.1.4" + } + } + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.2", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.3", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.1" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "semver": { + "version": "5.4.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.1", + "bundled": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.1.0", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "gtoken": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.3.tgz", + "integrity": "sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w==", + "requires": { + "google-p12-pem": "0.1.2", + "jws": "3.1.4", + "mime": "1.6.0", + "request": "2.83.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hash-stream-validation": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz", + "integrity": "sha1-7Mm5l7IYvluzEphii7gHhptz3NE=", + "requires": { + "through2": "2.0.3" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "http-parser-js": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.5", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", + "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream-ended": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.3.tgz", + "integrity": "sha1-oEc7Jnx1ZjVIa+7cfjNE5UnRUqw=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "requires": { + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.20.1", + "topo": "1.1.0" + }, + "dependencies": { + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonwebtoken": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", + "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "requires": { + "jws": "3.1.4", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1", + "xtend": "4.0.1" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" + }, + "lodash.noop": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-3.0.1.tgz", + "integrity": "sha1-OBiPTWUKOkdCWEObluxFsyYXEzw=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "log-driver": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.6.tgz", + "integrity": "sha512-iUHz4WAGsXwUmL1UergWrkFD2iTUrGLMsQDRYUWtS9FI+wSyM76vIL+THQt7vrQq5fZDGdrPSCFUfIlqII28tg==", + "requires": { + "codecov.io": "0.0.1" + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "requires": { + "pify": "3.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methmeth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz", + "integrity": "sha1-6AomYY5S9cQiKGG7dIUQvRDikIk=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "modelo": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz", + "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==" + }, + "moment": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-forge": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "power-assert": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.4.4.tgz", + "integrity": "sha1-kpXqdDcZb1pgH95CDwQmMRhtdRc=", + "requires": { + "define-properties": "1.1.2", + "empower": "1.2.3", + "power-assert-formatter": "1.4.1", + "universal-deep-strict-equal": "1.2.2", + "xtend": "4.0.1" + } + }, + "power-assert-context-formatter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz", + "integrity": "sha1-7bo1LT7YpgMRTWZyZazOYNaJzN8=", + "requires": { + "core-js": "2.5.3", + "power-assert-context-traversal": "1.1.1" + } + }, + "power-assert-context-reducer-ast": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.1.2.tgz", + "integrity": "sha1-SEqZ4m9Jc/+IMuXFzHVnAuYJQXQ=", + "requires": { + "acorn": "4.0.13", + "acorn-es7-plugin": "1.1.7", + "core-js": "2.5.3", + "espurify": "1.7.0", + "estraverse": "4.2.0" + } + }, + "power-assert-context-traversal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.1.1.tgz", + "integrity": "sha1-iMq8oNE7Y1nwfT0+ivppkmRXftk=", + "requires": { + "core-js": "2.5.3", + "estraverse": "4.2.0" + } + }, + "power-assert-formatter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", + "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", + "requires": { + "core-js": "2.5.3", + "power-assert-context-formatter": "1.1.1", + "power-assert-context-reducer-ast": "1.1.2", + "power-assert-renderer-assertion": "1.1.1", + "power-assert-renderer-comparison": "1.1.1", + "power-assert-renderer-diagram": "1.1.2", + "power-assert-renderer-file": "1.1.1" + } + }, + "power-assert-renderer-assertion": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.1.1.tgz", + "integrity": "sha1-y/wOd+AIao+Wrz8djme57n4ozpg=", + "requires": { + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1" + } + }, + "power-assert-renderer-base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", + "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=" + }, + "power-assert-renderer-comparison": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.1.1.tgz", + "integrity": "sha1-10Odl9hRVr5OMKAPL7WnJRTOPAg=", + "requires": { + "core-js": "2.5.3", + "diff-match-patch": "1.0.0", + "power-assert-renderer-base": "1.1.1", + "stringifier": "1.3.0", + "type-name": "2.0.2" + } + }, + "power-assert-renderer-diagram": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.1.2.tgz", + "integrity": "sha1-ZV+PcRk1qbbVQbhjJ2VHF8Y3qYY=", + "requires": { + "core-js": "2.5.3", + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.1.1", + "stringifier": "1.3.0" + } + }, + "power-assert-renderer-file": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.1.1.tgz", + "integrity": "sha1-o34rvReMys0E5427eckv40kzxec=", + "requires": { + "power-assert-renderer-base": "1.1.1" + } + }, + "power-assert-util-string-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.1.1.tgz", + "integrity": "sha1-vmWet5N/3S5smncmjar2S9W3xZI=", + "requires": { + "eastasianwidth": "0.1.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz", + "integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "protobufjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", + "integrity": "sha1-WXSNfc8D0tsiwT2p/rAk4Wq4DJE=", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "5.0.1", + "glob": "7.1.2", + "yargs": "3.32.0" + } + }, + "proxy-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", + "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.5.2" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "requires": { + "duplexify": "3.5.3", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } + }, + "retry-request": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", + "integrity": "sha512-PjAmtWIxjNj4Co/6FRtBl8afRP3CxrrIAnUzb1dzydfROd+6xt7xAebFeskgQgkfFf8NmzrXIoaB3HxmswXyxw==", + "requires": { + "request": "2.83.0", + "through2": "2.0.3" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "split": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "requires": { + "through": "2.3.8" + } + }, + "split-array-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz", + "integrity": "sha1-0rdajl4Ngk1S/eyLgiWDncLjXfo=", + "requires": { + "async": "2.6.0", + "is-stream-ended": "0.1.3" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "0.1.1" + } + }, + "stream-events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.2.tgz", + "integrity": "sha1-q/OfZsCJCk63lbyNXoWbJhW1kLI=", + "requires": { + "stubs": "3.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-format-obj": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz", + "integrity": "sha512-Mm+sROy+pHJmx0P/0Bs1uxIX6UhGJGj6xDGQZ5zh9v/SZRmLGevp+p0VJxV7lirrkAmQ2mvva/gHKpnF/pTb+Q==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringifier": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", + "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", + "requires": { + "core-js": "2.5.3", + "traverse": "0.6.6", + "type-name": "2.0.2" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.1", + "lodash": "4.17.5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "tape": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.0.tgz", + "integrity": "sha1-Df7scJIn+8yRcKvn8EaWKycUMds=", + "requires": { + "deep-equal": "0.1.2", + "defined": "0.0.0", + "inherits": "2.0.3", + "jsonify": "0.0.0", + "resumer": "0.0.0", + "split": "0.2.10", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "requires": { + "hoek": "2.16.3" + }, + "dependencies": { + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + } + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, + "type-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", + "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "universal-deep-strict-equal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", + "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", + "requires": { + "array-filter": "1.0.0", + "indexof": "0.0.1", + "object-keys": "1.0.11" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "urlgrey": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.0.tgz", + "integrity": "sha1-8GU1cED7NcOzEdTl3DZITZbb6gY=", + "requires": { + "tape": "2.3.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "requires": { + "http-parser-js": "0.4.10", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } +} diff --git a/scripts/docs.angularjs.org-firebase/functions/package.json b/scripts/docs.angularjs.org-firebase/functions/package.json new file mode 100644 index 000000000000..fdfb9cf8b46d --- /dev/null +++ b/scripts/docs.angularjs.org-firebase/functions/package.json @@ -0,0 +1,21 @@ +{ + "name": "functions", + "description": "Cloud Functions for Firebase", + "scripts": { + "lint": "./node_modules/.bin/eslint .", + "serve": "firebase serve --only functions", + "shell": "firebase experimental:functions:shell", + "start": "npm run shell", + "deploy": "firebase deploy --only functions", + "logs": "firebase functions:log" + }, + "dependencies": { + "firebase-admin": "~5.8.1", + "firebase-functions": "^0.8.1" + }, + "devDependencies": { + "eslint": "^4.12.0", + "eslint-plugin-promise": "^3.6.0" + }, + "private": true +} diff --git a/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md b/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md index d73e9a74f5d2..cd6019d77b64 100644 --- a/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md +++ b/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md @@ -1,10 +1,23 @@ Firebase for docs.angularjs.org =============================== +# Continuous integration + The docs are deployed to Google Firebase hosting via Travis deployment config, which expects -firebase.json and .firebaserc in the repository root. +firebase.json in the repository root, which is done by a Grunt task (firebaseDocsJsonForTravis) +that modifies the paths in the firebase.json and copies it into the repository root. + +See travis.yml for the complete deployment config, and scripts/travis/build.sh for the full deployment +build steps. + +# Serving locally: + +- Run `grunt:prepareDeploy`. + This copies docs content files into deploy/docs and the partials for Search Engine AJAX + Crawling into ./functions/content. -See travis.yml for the complete deployment config. +- Run `firebase serve --only functions,hosting` + Creates a server at localhost:5000 that serves from deploy/docs and uses the local function See /scripts/code.angularjs.org-firebase/readme.firebase.code.md for the firebase deployment to code.angularjs.org \ No newline at end of file From fb479188f5312310094ee8f6c7366000181d6130 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Mon, 12 Feb 2018 21:55:41 +0200 Subject: [PATCH 524/883] chore(docs.angular.js): do not break when deploying Follow-up to #16451. Closes #16452 --- lib/grunt/utils.js | 4 ++-- scripts/docs.angularjs.org-firebase/firebase.json | 5 ----- scripts/docs.angularjs.org-firebase/functions/package.json | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 64ddc6f185ec..73e8b1efc790 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -302,8 +302,8 @@ module.exports = { var fileName = docsScriptFolder + '/firebase.json'; var json = grunt.file.readJSON(fileName); - json.hosting.public = 'deploy/docs'; - json.functions.source = docsScriptFolder + '/functions'; + (json.hosting || (json.hosting = {})).public = 'deploy/docs'; + (json.functions || (json.functions = {})).source = docsScriptFolder + '/functions'; grunt.file.write('firebase.json', JSON.stringify(json)); } diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index 880a5eca86de..bf080d386fd7 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -27,10 +27,5 @@ "function": "sendFile" } ] - }, - "functions": { - "predeploy": [ - "npm --prefix $RESOURCE_DIR run lint" - ] } } diff --git a/scripts/docs.angularjs.org-firebase/functions/package.json b/scripts/docs.angularjs.org-firebase/functions/package.json index fdfb9cf8b46d..381fbc501096 100644 --- a/scripts/docs.angularjs.org-firebase/functions/package.json +++ b/scripts/docs.angularjs.org-firebase/functions/package.json @@ -2,7 +2,7 @@ "name": "functions", "description": "Cloud Functions for Firebase", "scripts": { - "lint": "./node_modules/.bin/eslint .", + "lint": "eslint .", "serve": "firebase serve --only functions", "shell": "firebase experimental:functions:shell", "start": "npm run shell", From ba140dbff9dddcdad239241fbe0240a25b29d188 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 13 Feb 2018 01:25:34 +0200 Subject: [PATCH 525/883] chore(docs.angularjs.org): install firebase dependencies before deploying Firebase is trying to execute our functions code locally in order to parse the triggers. Install npm dependencies to avoid errors like: ``` Error: Error parsing triggers: Cannot find module 'firebase-functions' ``` Closes #16453 --- .../readme.firebase.docs.md | 2 +- scripts/travis/build.sh | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md b/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md index cd6019d77b64..10da862469df 100644 --- a/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md +++ b/scripts/docs.angularjs.org-firebase/readme.firebase.docs.md @@ -20,4 +20,4 @@ build steps. Creates a server at localhost:5000 that serves from deploy/docs and uses the local function See /scripts/code.angularjs.org-firebase/readme.firebase.code.md for the firebase deployment to -code.angularjs.org \ No newline at end of file +code.angularjs.org diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index 980855388492..ed8838cc9574 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -2,6 +2,9 @@ set -e +readonly THIS_DIR=$(cd $(dirname $0); pwd) +readonly ROOT_DIR="$THIS_DIR/../.." + export BROWSER_STACK_ACCESS_KEY export SAUCE_ACCESS_KEY @@ -80,6 +83,14 @@ case "$JOB" in if [[ "$DEPLOY_DOCS" == true || "$DEPLOY_CODE" == true ]]; then grunt prepareDeploy + + if [[ "$DEPLOY_DOCS" == true ]]; then + # Install npm dependencies for Firebase functions. + ( + cd "$ROOT_DIR/scripts/docs.angularjs.org-firebase/functions" + npm install + ) + fi else echo "Skipping deployment build because conditions have not been met." fi @@ -94,4 +105,4 @@ case "$JOB" in or\ 'deploy'." ;; -esac \ No newline at end of file +esac From a126b346ff0f99562231a3721868d23a7c48495e Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 13 Feb 2018 01:52:02 +0200 Subject: [PATCH 526/883] chore(travis): fix `ROOT_DIR` path when `build.sh` is sourced --- scripts/travis/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index ed8838cc9574..9338247915a3 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -2,7 +2,7 @@ set -e -readonly THIS_DIR=$(cd $(dirname $0); pwd) +readonly THIS_DIR=$(cd $(dirname ${BASH_SOURCE[0]}); pwd) readonly ROOT_DIR="$THIS_DIR/../.." export BROWSER_STACK_ACCESS_KEY From 04ee1e781b931725cded2e40ce9bdc2674186b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Thu, 15 Feb 2018 14:28:47 +0100 Subject: [PATCH 527/883] docs(*): add CODE_OF_CONDUCT.md Closes #16456 --- CODE_OF_CONDUCT.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000000..baa757d028ae --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Contributor Code of Conduct + +The AngularJS project follows the Code of Conduct defined in [the angular/code-of-conduct repository](https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md). Please read it. From 9645a08b61bf4e0b52f3cde9567e4a12524ea488 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 13 Feb 2018 10:00:12 +0100 Subject: [PATCH 528/883] chore(docs.angularjs.org): allow robots access to js files Related to #16432 --- docs/app/assets/robots.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/app/assets/robots.txt b/docs/app/assets/robots.txt index c00cb3c20320..96b3734af696 100644 --- a/docs/app/assets/robots.txt +++ b/docs/app/assets/robots.txt @@ -1,9 +1,14 @@ User-agent: * Disallow: /examples/ -Disallow: /img/ Disallow: /partials/ Disallow: /ptore2e/ -Disallow: /*.js$ # The js files in the root are used by the embedded examples, not by the app itself -Disallow: /*.map$ # The map files in the root are used by the embedded examples, not by the app itself Disallow: /Error404.html + +# The js / map files in the root are used by the embedded examples, not by the app itself +Disallow: /*.js$ +Disallow: /*.map$ + +# (Javascript) crawlers need to access JS files +Allow: /components/*.js +Allow: /js/*.js From 3eabaab009c9b8d86759374a3b66a6b7a71dd5aa Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 15 Feb 2018 11:54:14 +0100 Subject: [PATCH 529/883] chore(docs.angularjs.org): allow crawling but not indexing of partials/ The sitemap.xml might also prevent the indexing, as the partials are not listed. Related to #16432 Closes #16457 --- docs/app/assets/robots.txt | 1 - scripts/docs.angularjs.org-firebase/firebase.json | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/app/assets/robots.txt b/docs/app/assets/robots.txt index 96b3734af696..36b7daeca859 100644 --- a/docs/app/assets/robots.txt +++ b/docs/app/assets/robots.txt @@ -1,7 +1,6 @@ User-agent: * Disallow: /examples/ -Disallow: /partials/ Disallow: /ptore2e/ Disallow: /Error404.html diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index bf080d386fd7..9e112f2ff9ee 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -26,6 +26,15 @@ "source": "**/*!(.@(jpg|jpeg|gif|png|html|js|map|json|css|svg|ttf|txt|woff|woff2|eot|xml))", "function": "sendFile" } + ], + "headers": [ + { + "source": "/partials/**", + "headers" : [{ + "key" : "X-Robots-Tag", + "value" : "noindex" + }] + } ] } } From f1c164c92f880b41fed38246baa0c1d4d914dd61 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Mon, 19 Feb 2018 19:31:43 +0000 Subject: [PATCH 530/883] docs($parse): add missing error documents --- docs/content/error/$parse/esc.ngdoc | 10 ++++++++++ docs/content/error/$parse/lval.ngdoc | 13 +++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 docs/content/error/$parse/esc.ngdoc create mode 100644 docs/content/error/$parse/lval.ngdoc diff --git a/docs/content/error/$parse/esc.ngdoc b/docs/content/error/$parse/esc.ngdoc new file mode 100644 index 000000000000..3f308b2d2fec --- /dev/null +++ b/docs/content/error/$parse/esc.ngdoc @@ -0,0 +1,10 @@ +@ngdoc error +@name $parse:esc +@fullName Value cannot be escaped +@description + +Occurs when the parser tries to escape a value that is not known. + +This should never occur in practice. If it does then that indicates a programming +error in the AngularJS `$parse` service itself and should be reported as an issue +at https://github.com/angular/angular.js/issues. \ No newline at end of file diff --git a/docs/content/error/$parse/lval.ngdoc b/docs/content/error/$parse/lval.ngdoc new file mode 100644 index 000000000000..03d23465a73d --- /dev/null +++ b/docs/content/error/$parse/lval.ngdoc @@ -0,0 +1,13 @@ +@ngdoc error +@name $parse:lval +@fullName Trying to assign a value to a non l-value +@description + +Occurs when an expression is trying to assign a value to a non-assignable expression. + +This can happen if the left side of an assigment is not a valid reference to a variable +or property. E.g. In the following snippet `1+2` is not assignable. + +``` +(1+2) = 'hello'; +``` From 56b6ba8e0b891b88687b826a9c4b2100bfd4901a Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Mon, 19 Feb 2018 19:37:26 +0000 Subject: [PATCH 531/883] docs($route): add missing error document --- docs/content/error/$route/norout.ngdoc | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 docs/content/error/$route/norout.ngdoc diff --git a/docs/content/error/$route/norout.ngdoc b/docs/content/error/$route/norout.ngdoc new file mode 100644 index 000000000000..30a12d151442 --- /dev/null +++ b/docs/content/error/$route/norout.ngdoc @@ -0,0 +1,8 @@ +@ngdoc error +@name $route:norout +@fullName Tried updating route when with no current route +@description + +Occurs when an attempt is made to update the parameters on the current route when +there is no current route. This can happen if you try to call `$route.updateParams();` +before the first route transition has completed. \ No newline at end of file From c617d6dceee5b000bfceda44ced22fc16b48b18b Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Tue, 20 Feb 2018 10:25:33 +0000 Subject: [PATCH 532/883] fix($templateRequest): give tpload error the correct namespace BREAKING CHANGE Previously the `tpload` error was namespaced to `$compile`. If you have code that matches errors of the form `[$compile:tpload]` it will no longer run. You should change the code to match `[$templateRequest:tpload]`. --- docs/content/error/$compile/tpload.ngdoc | 11 ----------- .../error/$templateRequest/tpload.ngdoc | 18 ++++++++++++++++++ src/ng/templateRequest.js | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 docs/content/error/$compile/tpload.ngdoc create mode 100644 docs/content/error/$templateRequest/tpload.ngdoc diff --git a/docs/content/error/$compile/tpload.ngdoc b/docs/content/error/$compile/tpload.ngdoc deleted file mode 100644 index b2b4fb2d0c2c..000000000000 --- a/docs/content/error/$compile/tpload.ngdoc +++ /dev/null @@ -1,11 +0,0 @@ -@ngdoc error -@name $compile:tpload -@fullName Error Loading Template -@description - -This error occurs when {@link ng.$compile `$compile`} attempts to fetch a template from some URL, and the request fails. - -To resolve this error, ensure that the URL of the template is spelled correctly and resolves to correct absolute URL. -The [Chrome Developer Tools](https://developers.google.com/chrome-developer-tools/docs/network#network_panel_overview) might also be helpful in determining why the request failed. - -If you are using {@link ng.$templateCache} to pre-load templates, ensure that the cache was populated with the template. diff --git a/docs/content/error/$templateRequest/tpload.ngdoc b/docs/content/error/$templateRequest/tpload.ngdoc new file mode 100644 index 000000000000..dba0788ce62b --- /dev/null +++ b/docs/content/error/$templateRequest/tpload.ngdoc @@ -0,0 +1,18 @@ +@ngdoc error +@name $templateRequest:tpload +@fullName Error Loading Template +@description + +This error occurs when {@link $templateRequest} attempts to fetch a template from some URL, and +the request fails. + +The template URL might be defined in a directive/component definition, an instance of `ngInclude`, +an instance of `ngMessagesInclude` or a templated route in a `$route` route definition. + +To resolve this error, ensure that the URL of the template is spelled correctly and resolves to +correct absolute URL. +The [Chrome Developer Tools](https://developers.google.com/chrome-developer-tools/docs/network#network_panel_overview) +might also be helpful in determining why the request failed. + +If you are using {@link ng.$templateCache} to pre-load templates, ensure that the cache was +populated with the template. diff --git a/src/ng/templateRequest.js b/src/ng/templateRequest.js index ff699d6cd0ef..7653b92a9126 100644 --- a/src/ng/templateRequest.js +++ b/src/ng/templateRequest.js @@ -1,6 +1,6 @@ 'use strict'; -var $templateRequestMinErr = minErr('$compile'); +var $templateRequestMinErr = minErr('$templateRequest'); /** * @ngdoc provider From b87c6a6d4d3d73fbc4d8aeecca58503d5d958d2c Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Tue, 20 Feb 2018 11:10:03 +0000 Subject: [PATCH 533/883] test(*): fix references to `tpload` minerr in tests --- test/ng/compileSpec.js | 2 +- test/ng/templateRequestSpec.js | 4 ++-- test/ngRoute/routeSpec.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index acda50470485..e65b951ff90f 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1917,7 +1917,7 @@ describe('$compile', function() { expect(function() { $httpBackend.flush(); - }).toThrowMinErr('$compile', 'tpload', 'Failed to load template: hello.html'); + }).toThrowMinErr('$templateRequest', 'tpload', 'Failed to load template: hello.html'); expect(sortedHtml(element)).toBe('
'); }) ); diff --git a/test/ng/templateRequestSpec.js b/test/ng/templateRequestSpec.js index 3ca323613103..23f05f1e8d08 100644 --- a/test/ng/templateRequestSpec.js +++ b/test/ng/templateRequestSpec.js @@ -144,9 +144,9 @@ describe('$templateRequest', function() { $templateRequest('tpl.html').catch(function(reason) { err = reason; }); $httpBackend.flush(); - expect(err).toEqualMinErr('$compile', 'tpload', + expect(err).toEqualMinErr('$templateRequest', 'tpload', 'Failed to load template: tpl.html (HTTP status: 404 Not Found)'); - expect($exceptionHandler.errors[0]).toEqualMinErr('$compile', 'tpload', + expect($exceptionHandler.errors[0]).toEqualMinErr('$templateRequest', 'tpload', 'Failed to load template: tpl.html (HTTP status: 404 Not Found)'); }); }); diff --git a/test/ngRoute/routeSpec.js b/test/ngRoute/routeSpec.js index 772bdc7bc226..36832ab57884 100644 --- a/test/ngRoute/routeSpec.js +++ b/test/ngRoute/routeSpec.js @@ -892,7 +892,7 @@ describe('$route', function() { $httpBackend.flush(); expect($exceptionHandler.errors.pop()). - toEqualMinErr('$compile', 'tpload', 'Failed to load template: r1.html'); + toEqualMinErr('$templateRequest', 'tpload', 'Failed to load template: r1.html'); $httpBackend.expectGET('r2.html').respond(''); $location.path('/r2'); From 8b399545a5098cb2576594a26a03cd7268c55fb6 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Tue, 20 Feb 2018 11:13:38 +0000 Subject: [PATCH 534/883] docs($route): fix typo in error message --- docs/content/error/$route/norout.ngdoc | 2 +- src/ngRoute/route.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/error/$route/norout.ngdoc b/docs/content/error/$route/norout.ngdoc index 30a12d151442..5dc5a9b8b7ee 100644 --- a/docs/content/error/$route/norout.ngdoc +++ b/docs/content/error/$route/norout.ngdoc @@ -1,6 +1,6 @@ @ngdoc error @name $route:norout -@fullName Tried updating route when with no current route +@fullName Tried updating route with no current route @description Occurs when an attempt is made to update the parameters on the current route when diff --git a/src/ngRoute/route.js b/src/ngRoute/route.js index 76f915b97da6..f0e6c19b9079 100644 --- a/src/ngRoute/route.js +++ b/src/ngRoute/route.js @@ -605,7 +605,7 @@ function $RouteProvider() { // interpolate modifies newParams, only query params are left $location.search(newParams); } else { - throw $routeMinErr('norout', 'Tried updating route when with no current route'); + throw $routeMinErr('norout', 'Tried updating route with no current route'); } } }; From ea0585773bb93fd891576e2271254a17e15f1ddd Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Sat, 10 Feb 2018 22:39:28 +0200 Subject: [PATCH 535/883] fix($resource): fix interceptors and success/error callbacks Previously, action-specific interceptors and `success`/`error` callbacks were executed in inconsistent relative orders and in a way that did not meet the general expectation for interceptor behavior (e.g. ability to recover from errors, performing asynchronous operations, etc). This commit fixes the behavior to make it more consistent and expected. The main differences are that `success`/`error` callbacks will now be run _after_ `response`/`responseError` interceptors complete (even if interceptors return a promise) and the correct callback will be called based on the result of the interceptor (e.g. if the `responseError` interceptor recovers from an error, the `success` callback will be called). See also https://github.com/angular/angular.js/issues/9334#issuecomment-364650642. This commit also replaces the use of `success`/`error` callbacks in the docs with using the returned promise. Fixes #6731 Fixes #9334 Closes #6865 Closes #16446 BREAKING CHANGE: If you are not using `success` or `error` callbacks with `$resource`, your app should not be affected by this change. If you are using `success` or `error` callbacks (with or without response interceptors), one (subtle) difference is that throwing an error inside the callbacks will not propagate to the returned `$promise`. Therefore, you should try to use the promises whenever possible. E.g.: ```js // Avoid User.query(function onSuccess(users) { throw new Error(); }). $promise. catch(function onError() { /* Will not be called. */ }); // Prefer User.query(). $promise. then(function onSuccess(users) { throw new Error(); }). catch(function onError() { /* Will be called. */ }); ``` Finally, if you are using `success` or `error` callbacks with response interceptors, the callbacks will now always run _after_ the interceptors (and wait for them to resolve in case they return a promise). Previously, the `error` callback was called before the `responseError` interceptor and the `success` callback was synchronously called after the `response` interceptor. E.g.: ```js var User = $resource('/api/users/:id', {id: '@id'}, { get: { method: 'get', interceptor: { response: function(response) { console.log('responseInterceptor-1'); return $timeout(1000).then(function() { console.log('responseInterceptor-2'); return response.resource; }); }, responseError: function(response) { console.log('responseErrorInterceptor-1'); return $timeout(1000).then(function() { console.log('responseErrorInterceptor-2'); return $q.reject('Ooops!'); }); } } } }); var onSuccess = function(value) { console.log('successCallback', value); }; var onError = function(error) { console.log('errorCallback', error); }; // Assuming the following call is successful... User.get({id: 1}, onSuccess, onError); // Old behavior: // responseInterceptor-1 // successCallback, {/* Promise object */} // responseInterceptor-2 // New behavior: // responseInterceptor-1 // responseInterceptor-2 // successCallback, {/* User object */} // Assuming the following call returns an error... User.get({id: 2}, onSuccess, onError); // Old behavior: // errorCallback, {/* Response object */} // responseErrorInterceptor-1 // responseErrorInterceptor-2 // New behavior: // responseErrorInterceptor-1 // responseErrorInterceptor-2 // errorCallback, Ooops! ``` --- src/ngResource/resource.js | 395 ++++++++++++++++++-------------- test/ngResource/resourceSpec.js | 288 +++++++++++++++++------ 2 files changed, 441 insertions(+), 242 deletions(-) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index c8a79274ca2b..11bb45ba20b3 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -110,13 +110,13 @@ function shallowClearAndCopy(src, dst) { * * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in * `actions` methods. If a parameter value is a function, it will be called every time - * a param value needs to be obtained for a request (unless the param was overridden). The function - * will be passed the current data value as an argument. + * a param value needs to be obtained for a request (unless the param was overridden). The + * function will be passed the current data value as an argument. * * Each key value in the parameter object is first bound to url template if present and then any * excess keys are appended to the url search query after the `?`. * - * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * Given a template `/path/:verb` and parameter `{verb: 'greet', salutation: 'Hello'}` results in * URL `/path/greet?salutation=Hello`. * * If the parameter value is prefixed with `@`, then the value for that parameter will be @@ -125,7 +125,7 @@ function shallowClearAndCopy(src, dst) { * For example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of * `someParam` will be `data.someProp`. * Note that the parameter will be ignored, when calling a "GET" action method (i.e. an action - * method that does not accept a request body) + * method that does not accept a request body). * * @param {Object.=} actions Hash with declaration of custom actions that will be available * in addition to the default set of resource actions (see below). If a custom action has the same @@ -134,9 +134,11 @@ function shallowClearAndCopy(src, dst) { * * The declaration should be created in the format of {@link ng.$http#usage $http.config}: * - * {action1: {method:?, params:?, isArray:?, headers:?, ...}, - * action2: {method:?, params:?, isArray:?, headers:?, ...}, - * ...} + * { + * action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ... + * } * * Where: * @@ -148,55 +150,58 @@ function shallowClearAndCopy(src, dst) { * the parameter value is a function, it will be called every time when a param value needs to * be obtained for a request (unless the param was overridden). The function will be passed the * current data value as an argument. - * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * - **`url`** – {string} – Action specific `url` override. The url templating is supported just * like for the resource-level urls. * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, * see `returns` section. * - **`transformRequest`** – * `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http + * Transform function or an array of such functions. The transform function takes the http * request body and headers and returns its transformed (typically serialized) version. * By default, transformRequest will contain one function that checks if the request data is * an object and serializes it using `angular.toJson`. To prevent this behavior, set * `transformRequest` to an empty array: `transformRequest: []` * - **`transformResponse`** – * `{function(data, headersGetter, status)|Array.}` – - * transform function or an array of such functions. The transform function takes the http + * Transform function or an array of such functions. The transform function takes the HTTP * response body, headers and status and returns its transformed (typically deserialized) * version. * By default, transformResponse will contain one function that checks if the response looks * like a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, * set `transformResponse` to an empty array: `transformResponse: []` - * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory} is supplied, this cache will be used for - * caching. - * - **`timeout`** – `{number}` – timeout in milliseconds.
+ * - **`cache`** – `{boolean|Cache}` – A boolean value or object created with + * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response. + * See {@link $http#caching $http Caching} for more information. + * - **`timeout`** – `{number}` – Timeout in milliseconds.
* **Note:** In contrast to {@link ng.$http#usage $http.config}, {@link ng.$q promises} are - * **not** supported in $resource, because the same value would be used for multiple requests. + * **not** supported in `$resource`, because the same value would be used for multiple requests. * If you are looking for a way to cancel requests, you should use the `cancellable` option. - * - **`cancellable`** – `{boolean}` – if set to true, the request made by a "non-instance" call - * will be cancelled (if not already completed) by calling `$cancelRequest()` on the call's - * return value. Calling `$cancelRequest()` for a non-cancellable or an already - * completed/cancelled request will have no effect.
- * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * - **`cancellable`** – `{boolean}` – If true, the request made by a "non-instance" call will be + * cancelled (if not already completed) by calling `$cancelRequest()` on the call's return + * value. Calling `$cancelRequest()` for a non-cancellable or an already completed/cancelled + * request will have no effect. + * - **`withCredentials`** – `{boolean}` – Whether to set the `withCredentials` flag on the * XHR object. See - * [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5) + * [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) * for more information. - * - **`responseType`** - `{string}` - see - * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). - * - **`interceptor`** - `{Object=}` - The interceptor object has four optional methods - + * - **`responseType`** – `{string}` – See + * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType). + * - **`interceptor`** – `{Object=}` – The interceptor object has four optional methods - * `request`, `requestError`, `response`, and `responseError`. See - * {@link ng.$http $http interceptors} for details. Note that `request`/`requestError` - * interceptors are applied before calling `$http`, thus before any global `$http` interceptors. - * The resource instance or array object is accessible by the `resource` property of the - * `http response` object passed to response interceptors. + * {@link ng.$http#interceptors $http interceptors} for details. Note that + * `request`/`requestError` interceptors are applied before calling `$http`, thus before any + * global `$http` interceptors. Also, rejecting or throwing an error inside the `request` + * interceptor will result in calling the `responseError` interceptor. + * The resource instance or collection is available on the `resource` property of the + * `http response` object passed to `response`/`responseError` interceptors. * Keep in mind that the associated promise will be resolved with the value returned by the - * response interceptor, if one is specified. The default response interceptor returns - * `response.resource` (i.e. the resource instance or array). - * - **`hasBody`** - `{boolean}` - allows to specify if a request body should be included or not. - * If not specified only POST, PUT and PATCH requests will have a body. - * + * response interceptors. Make sure you return an appropriate value and not the `response` + * object passed as input. For reference, the default `response` interceptor (which gets applied + * if you don't specify a custom one) returns `response.resource`.
+ * See {@link ngResource.$resource#using-interceptors below} for an example of using + * interceptors in `$resource`. + * - **`hasBody`** – `{boolean}` – If true, then the request will have a body. + * If not specified, then only POST, PUT and PATCH requests will have a body. * * @param {Object} options Hash with custom settings that should extend the * default `$resourceProvider` behavior. The supported options are: * @@ -209,27 +214,29 @@ function shallowClearAndCopy(src, dst) { * @returns {Object} A resource "class" object with methods for the default set of resource actions * optionally extended with custom `actions`. The default set contains these actions: * ```js - * { 'get': {method:'GET'}, - * 'save': {method:'POST'}, - * 'query': {method:'GET', isArray:true}, - * 'remove': {method:'DELETE'}, - * 'delete': {method:'DELETE'} }; + * { + * 'get': {method: 'GET'}, + * 'save': {method: 'POST'}, + * 'query': {method: 'GET', isArray: true}, + * 'remove': {method: 'DELETE'}, + * 'delete': {method: 'DELETE'} + * } * ``` * - * Calling these methods invoke an {@link ng.$http} with the specified http method, - * destination and parameters. When the data is returned from the server then the object is an - * instance of the resource class. The actions `save`, `remove` and `delete` are available on it - * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, - * read, update, delete) on server-side data like this: + * Calling these methods invoke {@link ng.$http} with the specified http method, destination and + * parameters. When the data is returned from the server then the object is an instance of the + * resource class. The actions `save`, `remove` and `delete` are available on it as methods with + * the `$` prefix. This allows you to easily perform CRUD operations (create, read, update, + * delete) on server-side data like this: * ```js - * var User = $resource('/user/:userId', {userId:'@id'}); - * var user = User.get({userId:123}, function() { + * var User = $resource('/user/:userId', {userId: '@id'}); + * User.get({userId: 123}).$promise.then(function(user) { * user.abc = true; * user.$save(); * }); * ``` * - * It is important to realize that invoking a $resource object method immediately returns an + * It is important to realize that invoking a `$resource` object method immediately returns an * empty reference (object or array depending on `isArray`). Once the data is returned from the * server the existing reference is populated with the actual data. This is a useful trick since * usually the resource is assigned to a model which is then rendered by the view. Having an empty @@ -252,30 +259,31 @@ function shallowClearAndCopy(src, dst) { * * * Success callback is called with (value (Object|Array), responseHeaders (Function), - * status (number), statusText (string)) arguments, where the value is the populated resource + * status (number), statusText (string)) arguments, where `value` is the populated resource * instance or collection object. The error callback is called with (httpResponse) argument. * - * Class actions return empty instance (with additional properties below). - * Instance actions return promise of the action. + * Class actions return an empty instance (with the additional properties listed below). + * Instance actions return a promise for the operation. * * The Resource instances and collections have these additional properties: * - * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + * - `$promise`: The {@link ng.$q promise} of the original server interaction that created this * instance or collection. * * On success, the promise is resolved with the same resource instance or collection object, - * updated with data from server. This makes it easy to use in - * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view + * updated with data from server. This makes it easy to use in the + * {@link ngRoute.$routeProvider `resolve` section of `$routeProvider.when()`} to defer view * rendering until the resource(s) are loaded. * * On failure, the promise is rejected with the {@link ng.$http http response} object. * * If an interceptor object was provided, the promise will instead be resolved with the value - * returned by the interceptor. + * returned by the response interceptor (on success) or responceError interceptor (on failure). * * - `$resolved`: `true` after first server interaction is completed (either with success or * rejection), `false` before that. Knowing if the Resource has been resolved is useful in - * data-binding. + * data-binding. If there is a response/responseError interceptor and it returns a promise, + * `$resolved` will wait for that too. * * The Resource instances and collections have these additional methods: * @@ -292,121 +300,128 @@ function shallowClearAndCopy(src, dst) { * * @example * - * ### Credit card resource + * ### Basic usage * - * ```js - // Define CreditCard class - var CreditCard = $resource('/user/:userId/card/:cardId', - {userId:123, cardId:'@id'}, { - charge: {method:'POST', params:{charge:true}} - }); + ```js + // Define a CreditCard class + var CreditCard = $resource('/users/:userId/cards/:cardId', + {userId: 123, cardId: '@id'}, { + charge: {method: 'POST', params: {charge: true}} + }); // We can retrieve a collection from the server - var cards = CreditCard.query(function() { - // GET: /user/123/card - // server returns: [ {id:456, number:'1234', name:'Smith'} ]; + var cards = CreditCard.query(); + // GET: /users/123/cards + // server returns: [{id: 456, number: '1234', name: 'Smith'}] + // Wait for the request to complete + cards.$promise.then(function() { var card = cards[0]; - // each item is an instance of CreditCard + + // Each item is an instance of CreditCard expect(card instanceof CreditCard).toEqual(true); - card.name = "J. Smith"; - // non GET methods are mapped onto the instances + + // Non-GET methods are mapped onto the instances + card.name = 'J. Smith'; card.$save(); - // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'} - // server returns: {id:456, number:'1234', name: 'J. Smith'}; + // POST: /users/123/cards/456 {id: 456, number: '1234', name: 'J. Smith'} + // server returns: {id: 456, number: '1234', name: 'J. Smith'} - // our custom method is mapped as well. - card.$charge({amount:9.99}); - // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'} + // Our custom method is mapped as well (since it uses POST) + card.$charge({amount: 9.99}); + // POST: /users/123/cards/456?amount=9.99&charge=true {id: 456, number: '1234', name: 'J. Smith'} }); - // we can create an instance as well - var newCard = new CreditCard({number:'0123'}); - newCard.name = "Mike Smith"; - newCard.$save(); - // POST: /user/123/card {number:'0123', name:'Mike Smith'} - // server returns: {id:789, number:'0123', name: 'Mike Smith'}; - expect(newCard.id).toEqual(789); - * ``` + // We can create an instance as well + var newCard = new CreditCard({number: '0123'}); + newCard.name = 'Mike Smith'; + + var savePromise = newCard.$save(); + // POST: /users/123/cards {number: '0123', name: 'Mike Smith'} + // server returns: {id: 789, number: '0123', name: 'Mike Smith'} + + savePromise.then(function() { + // Once the promise is resolved, the created instance + // is populated with the data returned by the server + expect(newCard.id).toEqual(789); + }); + ``` * - * The object returned from this function execution is a resource "class" which has "static" method - * for each action in the definition. + * The object returned from a call to `$resource` is a resource "class" which has one "static" + * method for each action in the definition. * - * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and - * `headers`. + * Calling these methods invokes `$http` on the `url` template with the given HTTP `method`, + * `params` and `headers`. * * @example * - * ### User resource + * ### Accessing the response * * When the data is returned from the server then the object is an instance of the resource type and * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD * operations (create, read, update, delete) on server-side data. - + * ```js - var User = $resource('/user/:userId', {userId:'@id'}); - User.get({userId:123}, function(user) { + var User = $resource('/users/:userId', {userId: '@id'}); + User.get({userId: 123}).$promise.then(function(user) { user.abc = true; user.$save(); }); ``` * - * It's worth noting that the success callback for `get`, `query` and other methods gets passed - * in the response that came from the server as well as $http header getter function, so one - * could rewrite the above example and get access to http headers as: + * It's worth noting that the success callback for `get`, `query` and other methods gets called with + * the resource instance (populated with the data that came from the server) as well as an `$http` + * header getter function, the HTTP status code and the response status text. So one could rewrite + * the above example and get access to HTTP headers as follows: * ```js - var User = $resource('/user/:userId', {userId:'@id'}); - User.get({userId:123}, function(user, getResponseHeaders){ + var User = $resource('/users/:userId', {userId: '@id'}); + User.get({userId: 123}, function(user, getResponseHeaders) { user.abc = true; user.$save(function(user, putResponseHeaders) { - //user => saved user object - //putResponseHeaders => $http header getter + // `user` => saved `User` object + // `putResponseHeaders` => `$http` header getter }); }); ``` * - * You can also access the raw `$http` promise via the `$promise` property on the object returned - * - ``` - var User = $resource('/user/:userId', {userId:'@id'}); - User.get({userId:123}) - .$promise.then(function(user) { - $scope.user = user; - }); - ``` - * * @example * - * ### Creating a custom 'PUT' request + * ### Creating custom actions * - * In this example we create a custom method on our resource to make a PUT request - * ```js - * var app = angular.module('app', ['ngResource', 'ngRoute']); - * - * // Some APIs expect a PUT request in the format URL/object/ID - * // Here we are creating an 'update' method - * app.factory('Notes', ['$resource', function($resource) { - * return $resource('/notes/:id', null, - * { - * 'update': { method:'PUT' } - * }); - * }]); - * - * // In our controller we get the ID from the URL using ngRoute and $routeParams - * // We pass in $routeParams and our Notes factory along with $scope - * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', - function($scope, $routeParams, Notes) { - * // First get a note object from the factory - * var note = Notes.get({ id:$routeParams.id }); - * $id = note.id; - * - * // Now call update passing in the ID first then the object you are updating - * Notes.update({ id:$id }, note); - * - * // This will PUT /notes/ID with the note object in the request payload - * }]); - * ``` + * In this example we create a custom method on our resource to make a PUT request: + * + ```js + var app = angular.module('app', ['ngResource']); + + // Some APIs expect a PUT request in the format URL/object/ID + // Here we are creating an 'update' method + app.factory('Notes', ['$resource', function($resource) { + return $resource('/notes/:id', {id: '@id'}, { + update: {method: 'PUT'} + }); + }]); + + // In our controller we get the ID from the URL using `$location` + app.controller('NotesCtrl', ['$location', 'Notes', function($location, Notes) { + // First, retrieve the corresponding `Note` object from the server + // (Assuming a URL of the form `.../notes?id=XYZ`) + var noteId = $location.search().id; + var note = Notes.get({id: noteId}); + + note.$promise.then(function() { + note.content = 'Hello, world!'; + + // Now call `update` to save the changes on the server + Notes.update(note); + // This will PUT /notes/ID with the note object as the request payload + + // Since `update` is a non-GET method, it will also be available on the instance + // (prefixed with `$`), so we could replace the `Note.update()` call with: + //note.$update(); + }); + }]); + ``` * * @example * @@ -417,7 +432,7 @@ function shallowClearAndCopy(src, dst) { * ```js // ...defining the `Hotel` resource... - var Hotel = $resource('/api/hotel/:id', {id: '@id'}, { + var Hotel = $resource('/api/hotels/:id', {id: '@id'}, { // Let's make the `query()` method cancellable query: {method: 'get', isArray: true, cancellable: true} }); @@ -427,14 +442,54 @@ function shallowClearAndCopy(src, dst) { this.onDestinationChanged = function onDestinationChanged(destination) { // We don't care about any pending request for hotels // in a different destination any more - this.availableHotels.$cancelRequest(); + if (this.availableHotels) { + this.availableHotels.$cancelRequest(); + } - // Let's query for hotels in '' - // (calls: /api/hotel?location=) + // Let's query for hotels in `destination` + // (calls: /api/hotels?location=) this.availableHotels = Hotel.query({location: destination}); }; ``` * + * @example + * + * ### Using interceptors + * + * You can use interceptors to transform the request or response, perform additional operations, and + * modify the returned instance/collection. The following example, uses `request` and `response` + * interceptors to augment the returned instance with additional info: + * + ```js + var Thing = $resource('/api/things/:id', {id: '@id'}, { + save: { + method: 'POST', + interceptor: { + request: function(config) { + // Before the request is sent out, store a timestamp on the request config + config.requestTimestamp = Date.now(); + return config; + }, + response: function(response) { + // Get the instance from the response object + var instance = response.resource; + + // Augment the instance with a custom `saveLatency` property, computed as the time + // between sending the request and receiving the response. + instance.saveLatency = Date.now() - response.config.requestTimestamp; + + // Return the instance + return instance; + } + } + } + }); + + Thing.save({foo: 'bar'}).$promise.then(function(thing) { + console.log('That thing was saved in ' + thing.saveLatency + 'ms.'); + }); + ``` + * */ angular.module('ngResource', ['ng']). info({ angularVersion: '"NG_VERSION_FULL"' }). @@ -667,34 +722,34 @@ angular.module('ngResource', ['ng']). } Resource[name] = function(a1, a2, a3, a4) { - var params = {}, data, success, error; + var params = {}, data, onSuccess, onError; switch (arguments.length) { case 4: - error = a4; - success = a3; + onError = a4; + onSuccess = a3; // falls through case 3: case 2: if (isFunction(a2)) { if (isFunction(a1)) { - success = a1; - error = a2; + onSuccess = a1; + onError = a2; break; } - success = a2; - error = a3; + onSuccess = a2; + onError = a3; // falls through } else { params = a1; data = a2; - success = a3; + onSuccess = a3; break; } // falls through case 1: - if (isFunction(a1)) success = a1; + if (isFunction(a1)) onSuccess = a1; else if (hasBody) data = a1; else params = a1; break; @@ -714,11 +769,14 @@ angular.module('ngResource', ['ng']). var responseInterceptor = action.interceptor && action.interceptor.response || defaultResponseInterceptor; var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || - undefined; - var hasError = !!error; - var hasResponseErrorInterceptor = !!responseErrorInterceptor; + $q.reject; + var successCallback = onSuccess ? function(val) { + onSuccess(val, response.headers, response.status, response.statusText); + } : undefined; + var errorCallback = onError || undefined; var timeoutDeferred; var numericTimeoutPromise; + var response; forEach(action, function(value, key) { switch (key) { @@ -754,8 +812,8 @@ angular.module('ngResource', ['ng']). catch(requestErrorInterceptor). then($http); - promise = promise.then(function(response) { - var data = response.data; + promise = promise.then(function(resp) { + var data = resp.data; if (data) { // Need to convert action.isArray to boolean in case it is undefined @@ -783,12 +841,14 @@ angular.module('ngResource', ['ng']). value.$promise = promise; // Restore the promise } } - response.resource = value; - return response; - }, function(response) { - response.resource = value; - return $q.reject(response); + resp.resource = value; + response = resp; + return responseInterceptor(resp); + }, function(rejectionOrResponse) { + rejectionOrResponse.resource = value; + response = rejectionOrResponse; + return responseErrorInterceptor(rejectionOrResponse); }); promise = promise['finally'](function() { @@ -800,25 +860,8 @@ angular.module('ngResource', ['ng']). } }); - promise = promise.then( - function(response) { - var value = responseInterceptor(response); - (success || noop)(value, response.headers, response.status, response.statusText); - return value; - }, - (hasError || hasResponseErrorInterceptor) ? - function(response) { - if (hasError && !hasResponseErrorInterceptor) { - // Avoid `Possibly Unhandled Rejection` error, - // but still fulfill the returned promise with a rejection - promise.catch(noop); - } - if (hasError) error(response); - return hasResponseErrorInterceptor ? - responseErrorInterceptor(response) : - $q.reject(response); - } : - undefined); + // Run the `success`/`error` callbacks, but do not let them affect the returned promise. + promise.then(successCallback, errorCallback); if (!isInstanceCall) { // we are creating instance / collection diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index 00fce4b662a8..077281a134ba 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -34,11 +34,11 @@ describe('basic usage', function() { callback = jasmine.createSpy('callback'); })); - afterEach(function() { $httpBackend.verifyNoOutstandingExpectation(); }); + describe('isValidDottedPath', function() { /* global isValidDottedPath: false */ it('should support arbitrary dotted names', function() { @@ -1312,102 +1312,225 @@ describe('basic usage', function() { }); }); - it('should allow per action response interceptor that gets full response', function() { - CreditCard = $resource('/CreditCard', {}, { - query: { - method: 'get', - isArray: true, - interceptor: { - response: function(response) { - return response; - } + + describe('responseInterceptor', function() { + it('should allow per action response interceptor that gets full response', function() { + var response; + + $httpBackend.expect('GET', '/CreditCard').respond(201, {id: 1}, {foo: 'bar'}, 'Ack'); + CreditCard = $resource('/CreditCard', {}, { + get: { + method: 'get', + interceptor: {response: function(resp) { response = resp; }} } - } + }); + + var cc = CreditCard.get(); + $httpBackend.flush(); + + expect(response.resource).toBe(cc); + expect(response.config).toBeDefined(); + expect(response.status).toBe(201); + expect(response.statusText).toBe('Ack'); + expect(response.headers()).toEqual({foo: 'bar'}); }); - $httpBackend.expect('GET', '/CreditCard').respond([{id: 1}]); - var ccs = CreditCard.query(); + it('should allow per action responseError interceptor that gets full response', function() { + var response; - ccs.$promise.then(callback); + $httpBackend.expect('GET', '/CreditCard').respond(404, {ignored: 'stuff'}, {foo: 'bar'}, 'Ack'); + CreditCard = $resource('/CreditCard', {}, { + get: { + method: 'get', + interceptor: {responseError: function(resp) { response = resp; }} + } + }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalledOnce(); + var cc = CreditCard.get(); + $httpBackend.flush(); - var response = callback.calls.mostRecent().args[0]; - expect(response.resource).toBe(ccs); - expect(response.status).toBe(200); - expect(response.config).toBeDefined(); - }); + expect(response.resource).toBe(cc); + expect(response.config).toBeDefined(); + expect(response.status).toBe(404); + expect(response.statusText).toBe('Ack'); + expect(response.headers()).toEqual({foo: 'bar'}); + }); - it('should allow per action responseError interceptor that gets full response', function() { - CreditCard = $resource('/CreditCard', {}, { - query: { - method: 'get', - isArray: true, - interceptor: { - responseError: function(response) { - return response; + it('should fulfill the promise with the value returned by the response interceptor', + function() { + $httpBackend.whenGET('/CreditCard').respond(200); + CreditCard = $resource('/CreditCard', {}, { + test1: { + method: 'get', + interceptor: {response: function() { return 'foo'; }} + }, + test2: { + method: 'get', + interceptor: {response: function() { return $q.resolve('bar'); }} + }, + test3: { + method: 'get', + interceptor: {response: function() { return $q.reject('baz'); }} } - } + }); + + CreditCard.test1().$promise.then(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('foo'); + + callback.calls.reset(); + + CreditCard.test2().$promise.then(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('bar'); + + callback.calls.reset(); + + CreditCard.test3().$promise.then(null, callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('baz'); } - }); + ); - $httpBackend.expect('GET', '/CreditCard').respond(404); - var ccs = CreditCard.query(); + it('should fulfill the promise with the value returned by the responseError interceptor', + function() { + $httpBackend.whenGET('/CreditCard').respond(404); + CreditCard = $resource('/CreditCard', {}, { + test1: { + method: 'get', + interceptor: {responseError: function() { return 'foo'; }} + }, + test2: { + method: 'get', + interceptor: {responseError: function() { return $q.resolve('bar'); }} + }, + test3: { + method: 'get', + interceptor: {responseError: function() { return $q.reject('baz'); }} + } + }); - ccs.$promise.then(callback); + CreditCard.test1().$promise.then(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('foo'); - $httpBackend.flush(); - expect(callback).toHaveBeenCalledOnce(); + callback.calls.reset(); - var response = callback.calls.mostRecent().args[0]; - expect(response.resource).toBe(ccs); - expect(response.status).toBe(404); - expect(response.config).toBeDefined(); - }); + CreditCard.test2().$promise.then(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('bar'); + callback.calls.reset(); + + CreditCard.test3().$promise.then(null, callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('baz'); + } + ); - it('should fulfill the promise with the value returned by the responseError interceptor', - inject(function($q) { + + it('should call the success callback when response interceptor succeeds', function() { + $httpBackend.whenGET('/CreditCard').respond(200); CreditCard = $resource('/CreditCard', {}, { test1: { - method: 'GET', - interceptor: {responseError: function() { return 'foo'; }} + method: 'get', + interceptor: {response: function() { return 'foo'; }} }, test2: { - method: 'GET', - interceptor: {responseError: function() { return $q.resolve('bar'); }} - }, - test3: { - method: 'GET', - interceptor: {responseError: function() { return $q.reject('baz'); }} + method: 'get', + interceptor: {response: function() { return $q.resolve('bar'); }} } }); - $httpBackend.whenGET('/CreditCard').respond(404); + CreditCard.test1(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('foo', jasmine.any(Function), 200, ''); callback.calls.reset(); - CreditCard.test1().$promise.then(callback); + + CreditCard.test2(callback); $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('bar', jasmine.any(Function), 200, ''); + }); + + + it('should call the error callback when response interceptor fails', function() { + $httpBackend.whenGET('/CreditCard').respond(200); + CreditCard = $resource('/CreditCard', {}, { + test1: { + method: 'get', + interceptor: {response: function() { throw 'foo'; }} + }, + test2: { + method: 'get', + interceptor: {response: function() { return $q.reject('bar'); }} + } + }); + CreditCard.test1(noop, callback); + $httpBackend.flush(); expect(callback).toHaveBeenCalledOnceWith('foo'); callback.calls.reset(); - CreditCard.test2().$promise.then(callback); - $httpBackend.flush(); + CreditCard.test2(noop, callback); + $httpBackend.flush(); expect(callback).toHaveBeenCalledOnceWith('bar'); + }); + + + it('should call the success callback when responseError interceptor succeeds', function() { + $httpBackend.whenGET('/CreditCard').respond(404); + CreditCard = $resource('/CreditCard', {}, { + test1: { + method: 'get', + interceptor: {responseError: function() { return 'foo'; }} + }, + test2: { + method: 'get', + interceptor: {responseError: function() { return $q.resolve('bar'); }} + } + }); + + CreditCard.test1(callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('foo', jasmine.any(Function), 404, ''); callback.calls.reset(); - CreditCard.test3().$promise.then(null, callback); + + CreditCard.test2(callback); $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('bar', jasmine.any(Function), 404, ''); + }); + - expect(callback).toHaveBeenCalledOnceWith('baz'); - }) - ); + it('should call the error callback when responseError interceptor fails', function() { + $httpBackend.whenGET('/CreditCard').respond(404); + CreditCard = $resource('/CreditCard', {}, { + test1: { + method: 'get', + interceptor: {responseError: function() { throw 'foo'; }} + }, + test2: { + method: 'get', + interceptor: {responseError: function() { return $q.reject('bar'); }} + } + }); + + CreditCard.test1(noop, callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('foo'); + + callback.calls.reset(); + + CreditCard.test2(noop, callback); + $httpBackend.flush(); + expect(callback).toHaveBeenCalledOnceWith('bar'); + }); + }); }); @@ -1810,7 +1933,7 @@ describe('extra params', function() { }); describe('errors', function() { - var $httpBackend, $resource, $q, $rootScope; + var $httpBackend, $resource; beforeEach(module(function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); @@ -1821,8 +1944,6 @@ describe('errors', function() { beforeEach(inject(function($injector) { $httpBackend = $injector.get('$httpBackend'); $resource = $injector.get('$resource'); - $q = $injector.get('$q'); - $rootScope = $injector.get('$rootScope'); })); @@ -1961,7 +2082,7 @@ describe('handling rejections', function() { function() { $httpBackend.expectGET('/CreditCard/123').respond(null); var CreditCard = $resource('/CreditCard/:id'); - var cc = CreditCard.get({id: 123}, + CreditCard.get({id: 123}, function(res) { throw new Error('should be caught'); }, function() {}); @@ -1976,7 +2097,7 @@ describe('handling rejections', function() { function() { $httpBackend.expectGET('/CreditCard/123').respond(null); var CreditCard = $resource('/CreditCard/:id'); - var cc = CreditCard.get({id: 123}, + CreditCard.get({id: 123}, function(res) { throw new Error('should be caught'); }); $httpBackend.flush(); @@ -1996,7 +2117,7 @@ describe('handling rejections', function() { } }); - var cc = CreditCard.get({id: 123}, + CreditCard.get({id: 123}, function(res) { throw new Error('should be caught'); }, function() {}); @@ -2017,7 +2138,7 @@ describe('handling rejections', function() { } }); - var cc = CreditCard.get({id: 123}, + CreditCard.get({id: 123}, function(res) { throw new Error('should be caught'); }); $httpBackend.flush(); @@ -2026,6 +2147,41 @@ describe('handling rejections', function() { } ); + + it('should not propagate exceptions in success callback to the returned promise', function() { + var successCallbackSpy = jasmine.createSpy('successCallback').and.throwError('error'); + var promiseResolveSpy = jasmine.createSpy('promiseResolve'); + var promiseRejectSpy = jasmine.createSpy('promiseReject'); + + $httpBackend.expectGET('/CreditCard/123').respond(null); + var CreditCard = $resource('/CreditCard/:id'); + CreditCard.get({id: 123}, successCallbackSpy). + $promise.then(promiseResolveSpy, promiseRejectSpy); + + $httpBackend.flush(); + expect(successCallbackSpy).toHaveBeenCalled(); + expect(promiseResolveSpy).toHaveBeenCalledWith(jasmine.any(CreditCard)); + expect(promiseRejectSpy).not.toHaveBeenCalled(); + }); + + + it('should not be able to recover from inside the error callback', function() { + var errorCallbackSpy = jasmine.createSpy('errorCallback').and.returnValue({id: 123}); + var promiseResolveSpy = jasmine.createSpy('promiseResolve'); + var promiseRejectSpy = jasmine.createSpy('promiseReject'); + + $httpBackend.expectGET('/CreditCard/123').respond(404); + var CreditCard = $resource('/CreditCard/:id'); + CreditCard.get({id: 123}, noop, errorCallbackSpy). + $promise.then(promiseResolveSpy, promiseRejectSpy); + + $httpBackend.flush(); + expect(errorCallbackSpy).toHaveBeenCalled(); + expect(promiseResolveSpy).not.toHaveBeenCalled(); + expect(promiseRejectSpy).toHaveBeenCalledWith(jasmine.objectContaining({status: 404})); + }); + + describe('requestInterceptor', function() { var rejectReason = {'lol':'cat'}; var $q, $rootScope; From 33b251d55e48da867cb2998e6d87ef33c3fec416 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 21 Feb 2018 08:33:28 +0000 Subject: [PATCH 536/883] docs(misc): add version-support-status page (#16460) Closes #16058 Closes #16458 --- README.md | 9 +++- docs/app/assets/css/docs.css | 8 +++ docs/content/api/index.ngdoc | 10 +++- .../content/misc/version-support-status.ngdoc | 54 +++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 docs/content/misc/version-support-status.ngdoc diff --git a/README.md b/README.md index ae444e3ccdb8..c2d1a9db2981 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,14 @@ It also helps with server-side communication, taming async callbacks with promis and it makes client-side navigation and deep linking with hashbang urls or HTML5 pushState a piece of cake. Best of all? It makes development fun! +-------------------- + +##### AngularJS will be moving to Long Term Support (LTS) mode on July 1st 2018: [Find out more](misc/version-support-status) + +##### Looking for the new Angular? Go here: https://github.com/angular/angular + +-------------------- + * Web site: https://angularjs.org * Tutorial: https://docs.angularjs.org/tutorial * API Docs: https://docs.angularjs.org/api @@ -20,7 +28,6 @@ piece of cake. Best of all? It makes development fun! * Core Development: [DEVELOPERS.md](DEVELOPERS.md) * Dashboard: https://dashboard.angularjs.org -##### Looking for the new Angular? Go here: https://github.com/angular/angular Documentation -------------------- diff --git a/docs/app/assets/css/docs.css b/docs/app/assets/css/docs.css index 54d81ada753d..65abc5247f0c 100644 --- a/docs/app/assets/css/docs.css +++ b/docs/app/assets/css/docs.css @@ -934,6 +934,14 @@ toc-container > div > toc-tree > ul > li > toc-tree > ul > li toc-tree > ul li { font-size: 13px; } +.dev-status span { + padding: 2px 8px; + border-radius: 5px; +} +.security span { background-color: orange; } +.stable span { background-color: green; color: white; } +.current span { background-color: blue; color: white; } + @media handheld and (max-width:800px), screen and (max-device-width:800px), screen and (max-width:800px) { .navbar { min-height: auto; diff --git a/docs/content/api/index.ngdoc b/docs/content/api/index.ngdoc index 8b954a86bd05..d34ddfb64c1d 100644 --- a/docs/content/api/index.ngdoc +++ b/docs/content/api/index.ngdoc @@ -3,7 +3,15 @@ @description # AngularJS API Docs -Welcome to the AngularJS API docs page. These pages contain the AngularJS reference materials for version . + +
+**AngularJS will be moving to Long Term Support (LTS) mode on July 1st 2018.**: [Find out more](misc/version-support-status). +
+ +## Welcome to the AngularJS API docs page. + +These pages contain the AngularJS reference materials for version . + The documentation is organized into **{@link guide/module modules}** which contain various components of an AngularJS application. These components are {@link guide/directive directives}, {@link guide/services services}, {@link guide/filter filters}, {@link guide/providers providers}, {@link guide/templates templates}, global APIs, and testing mocks. diff --git a/docs/content/misc/version-support-status.ngdoc b/docs/content/misc/version-support-status.ngdoc new file mode 100644 index 000000000000..aff4309393dd --- /dev/null +++ b/docs/content/misc/version-support-status.ngdoc @@ -0,0 +1,54 @@ +@ngdoc overview +@name Version Support Status +@description + +# Version Support Status + +This page describes the support status of the significant versions of AngularJS. + +
+ AngularJS is planning one more significant release, version 1.7, and on July 1, 2018 it will enter a 3 year Long Term Support period. +
+ +### Until July 1st 2018 + +Any version branch not shown in the following table (e.g. 1.5.x) is no longer being developed. + + + + + + + + + + +
VersionStatusComments
1.2.xSecurity patches onlyLast version to provide IE 8 support
1.6.xPatch ReleasesMinor features, bug fixes, security patches - no breaking changes
1.7.xActive Development1.7.0 (not yet released) will be the last release of AngularJS to contain breaking changes
+ +### After July 1st 2018 + +Any version branch not shown in the following table (e.g. 1.6.x) is no longer being developed. + + + + + + + + + +
VersionStatusComments
1.2.xLong Term SupportLast version to provide IE 8 support
1.7.xLong Term SupportSee [Long Term Support](#long-term-support) section below.
+ +### Long Term Support + +On July 1st 2018, we will enter a Long Term Support period for AngularJS. + +At this time we will focus exclusively on providing fixes to bugs that satisfy at least one of the following criteria: + +* A security flaw is detected in the 1.7.x branch of the framework +* One of the major browsers releases a version that will cause current production applications using AngularJS 1.7.x to stop working +* The jQuery library releases a version that will cause current production applications using AngularJS 1.7.x to stop working. + +### Blog Post + +You can read more about these plans in our [blog post announcement](https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c). \ No newline at end of file From c0adcc3a4b561260d0f1ff6b834ca940bf1971a9 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 20 Feb 2018 18:23:07 +0200 Subject: [PATCH 537/883] refactor($compile): avoid catastrophic backtracking when parsing bindings This isn't expected to have any actual impact, since AngularJS is only intended to be used in the browser (not the server) and for this RegExp to be exploited by malicious user code the developer would have to have to give the user rights to execute arbitrary JavaScript code anyway. Fixing as a general good practice and to avoid encouraging use of a similar RegExp in other environments where it might actually matter. Closes #16464 --- src/ng/compile.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 6ae2722a6fde..603d94ed9522 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1014,11 +1014,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var bindingCache = createMap(); function parseIsolateBindings(scope, directiveName, isController) { - var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*([\w$]*)\s*$/; + var LOCAL_REGEXP = /^([@&<]|=(\*?))(\??)\s*([\w$]*)$/; var bindings = createMap(); forEach(scope, function(definition, scopeName) { + definition = definition.trim(); + if (definition in bindingCache) { bindings[scopeName] = bindingCache[definition]; return; From 719e66b38bd75a66b01df5b4cd90bbbac2bc069d Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Mon, 26 Feb 2018 15:00:42 +0100 Subject: [PATCH 538/883] docs(README): fix incorrect version-support-status link (#16473) Closes #16472 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2d1a9db2981..7ec7c6b466fd 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ piece of cake. Best of all? It makes development fun! -------------------- -##### AngularJS will be moving to Long Term Support (LTS) mode on July 1st 2018: [Find out more](misc/version-support-status) +##### AngularJS will be moving to Long Term Support (LTS) mode on July 1st 2018: [Find out more](https://docs.angularjs.org/misc/version-support-status) ##### Looking for the new Angular? Go here: https://github.com/angular/angular From 290a5f23395eeb669aff3f7957300833e46646d8 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 27 Feb 2018 17:33:42 +0100 Subject: [PATCH 539/883] docs(tutorial): fix headlines --- docs/content/tutorial/step_00.ngdoc | 5 ++--- docs/content/tutorial/step_01.ngdoc | 5 ++--- docs/content/tutorial/step_02.ngdoc | 11 +++++------ docs/content/tutorial/step_03.ngdoc | 9 ++++----- docs/content/tutorial/step_04.ngdoc | 4 ++-- docs/content/tutorial/step_05.ngdoc | 8 ++++---- docs/content/tutorial/step_06.ngdoc | 6 +++--- docs/content/tutorial/step_07.ngdoc | 6 +++--- docs/content/tutorial/step_08.ngdoc | 6 +++--- docs/content/tutorial/step_09.ngdoc | 6 +++--- docs/content/tutorial/step_10.ngdoc | 6 +++--- docs/content/tutorial/step_11.ngdoc | 6 +++--- docs/content/tutorial/step_12.ngdoc | 6 +++--- docs/content/tutorial/step_13.ngdoc | 2 +- docs/content/tutorial/step_14.ngdoc | 4 ++-- 15 files changed, 43 insertions(+), 47 deletions(-) diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 36afe8862cf6..4aca8850cfe6 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -5,7 +5,6 @@
    - In this step of the tutorial, you will become familiar with the most important source code files of the AngularJS Phonecat App. You will also learn how to start the development servers bundled with [angular-seed][angular-seed], and run the application in the browser. @@ -167,7 +166,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi * Added a dependency on [Bootstrap](http://getbootstrap.com) in the `bower.json` file. -# Experiments +## Experiments
    @@ -178,7 +177,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi ``` -# Summary +## Summary Now let's go to {@link step_01 step 1} and add some content to the web app. diff --git a/docs/content/tutorial/step_01.ngdoc b/docs/content/tutorial/step_01.ngdoc index e5f104701fac..b134e69f455d 100644 --- a/docs/content/tutorial/step_01.ngdoc +++ b/docs/content/tutorial/step_01.ngdoc @@ -5,7 +5,6 @@
      - In order to illustrate how AngularJS enhances standard HTML, you will create a purely *static* HTML page and then examine how we can turn this HTML code into a template that AngularJS will use to dynamically display the same result with any set of data. @@ -37,7 +36,7 @@ In this step you will add some basic information about two cell phones to an HTM ``` -# Experiments +## Experiments
      @@ -48,7 +47,7 @@ In this step you will add some basic information about two cell phones to an HTM ``` -# Summary +## Summary This addition to your app uses static HTML to display the list. Now, let's go to {@link step_02 step 2} to learn how to use AngularJS to dynamically generate the same list. diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index ba2edc0b9085..6b4a54388b3c 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -5,7 +5,6 @@
        - Now, it's time to make the web page dynamic — with AngularJS. We will also add a test that verifies the code for the controller we are going to add. @@ -148,9 +147,9 @@ To learn more about AngularJS scopes, see the {@link ng.$rootScope.Scope Angular -# Testing +## Testing -## Testing Controllers +### Testing Controllers The "AngularJS way" of separating the controller from the view makes it easy to test code as it is being developed. In the section "Model and Controller" we have registered our controller via a constructor @@ -206,7 +205,7 @@ describe('PhoneListController', function() { -## Writing and Running Tests +### Writing and Running Tests Many AngularJS developers prefer the syntax of [Jasmine's Behavior-Driven Development (BDD) framework][jasmine-home], when writing tests. Although @@ -253,7 +252,7 @@ To run the tests, and then watch the files for changes execute: `npm test` -# Experiments +## Experiments
        @@ -308,7 +307,7 @@ To run the tests, and then watch the files for changes execute: `npm test` `toBe(4)`. -# Summary +## Summary We now have a dynamic application which separates models, views, and controllers, and we are testing as we go. Let's go to {@link step_03 step 3} to learn how to improve our application's architecture, diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index 92b8d990f587..e7a16de54bd0 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -5,7 +5,6 @@
          - In the previous step, we saw how a controller and a template worked together to convert a static HTML page into a dynamic view. This is a very common pattern in Single-Page Applications in general (and AngularJS applications in particular): @@ -197,7 +196,7 @@ Voilà! The resulting output should look the same, but let's see what we have ga -# Testing +## Testing Although we have combined our controller with a template into a component, we still can (and should) unit test the controller separately, since this is where our application logic and data reside. @@ -240,12 +239,12 @@ verifies that the phones array property on it contains three records. Note that the controller instance itself, not on a `scope`. -## Running Tests +### Running Tests Same as before, execute `npm test` to run the tests and then watch the files for changes. -# Experiments +## Experiments
          @@ -267,7 +266,7 @@ Same as before, execute `npm test` to run the tests and then watch the files for throughout the application, is a big win. -# Summary +## Summary You have learned how to organize your application and presentation logic into isolated, reusable components. Let's go to {@link step_04 step 4} to learn how to organize our code in directories and diff --git a/docs/content/tutorial/step_04.ngdoc b/docs/content/tutorial/step_04.ngdoc index 2865ad765866..e7546f721fac 100644 --- a/docs/content/tutorial/step_04.ngdoc +++ b/docs/content/tutorial/step_04.ngdoc @@ -265,7 +265,7 @@ After all the refactorings that took place, this is how our application looks fr ``` -# Testing +## Testing Since this was just a refactoring step (no actual code addition/deletions), we shouldn't need to change much (if anything) as far as our specs are concerned. @@ -301,7 +301,7 @@ pass. -# Summary +## Summary Even if we didn't add any new and exciting functionality to our application, we have made a great step towards a well-architected and maintainable application. Time to spice things up. Let's go to diff --git a/docs/content/tutorial/step_05.ngdoc b/docs/content/tutorial/step_05.ngdoc index adba95906fbb..e7a5ea519c7e 100644 --- a/docs/content/tutorial/step_05.ngdoc +++ b/docs/content/tutorial/step_05.ngdoc @@ -78,7 +78,7 @@ following: by the `filter` filter. The process is completely transparent to the developer. -# Testing +## Testing In previous steps, we learned how to write and run unit tests. Unit tests are perfect for testing controllers and other parts of our application written in JavaScript, but they can't easily @@ -124,7 +124,7 @@ easy it is to write E2E tests in AngularJS. Although this example is for a simpl that easy to set up any functional, readable, E2E test. -## Running E2E Tests with Protractor +### Running E2E Tests with Protractor Even though the syntax of this test looks very much like our controller unit test written with Jasmine, the E2E test uses APIs of [Protractor][protractor]. Read about the Protractor APIs in the @@ -142,7 +142,7 @@ To rerun the test suite, execute `npm run protractor` again. -# Experiments +## Experiments
          @@ -155,7 +155,7 @@ To rerun the test suite, execute `npm run protractor` again. Component isolation at work! -# Summary +## Summary We have now added full-text search and included a test to verify that it works! Now let's go on to {@link step_06 step 6} to learn how to add sorting capabilities to the PhoneCat application. diff --git a/docs/content/tutorial/step_06.ngdoc b/docs/content/tutorial/step_06.ngdoc index 7a19d2600444..adc4b610fbb4 100644 --- a/docs/content/tutorial/step_06.ngdoc +++ b/docs/content/tutorial/step_06.ngdoc @@ -124,7 +124,7 @@ will be reordered. That is the data-binding doing its job in the opposite direct the model. -# Testing +## Testing The changes we made should be verified with both a unit test and an E2E test. Let's look at the unit test first. @@ -217,7 +217,7 @@ The E2E test verifies that the ordering mechanism of the select box is working c You can now rerun `npm run protractor` to see the tests run. -# Experiments +## Experiments
          @@ -232,7 +232,7 @@ You can now rerun `npm run protractor` to see the tests run. `` -# Summary +## Summary Now that you have added list sorting and tested the application, go to {@link step_07 step 7} to learn about AngularJS services and how AngularJS uses dependency injection. diff --git a/docs/content/tutorial/step_07.ngdoc b/docs/content/tutorial/step_07.ngdoc index 7e801ffa822d..4b0d0e64aaaa 100644 --- a/docs/content/tutorial/step_07.ngdoc +++ b/docs/content/tutorial/step_07.ngdoc @@ -180,7 +180,7 @@ let's add the annotations to our `PhoneListController`: ``` -# Testing +## Testing Because we started using dependency injection and our controller has dependencies, constructing the controller in our tests is a bit more complicated. We could use the `new` operator and provide the @@ -283,7 +283,7 @@ Chrome 49.0: Executed 2 of 2 SUCCESS (0.133 secs / 0.097 secs) ``` -# Experiments +## Experiments
          @@ -299,7 +299,7 @@ Chrome 49.0: Executed 2 of 2 SUCCESS (0.133 secs / 0.097 secs) ``` -# Summary +## Summary Now that you have learned how easy it is to use AngularJS services (thanks to AngularJS's dependency injection), go to {@link step_08 step 8}, where you will add some thumbnail images of phones and diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index a55461d0cc21..5707ea4d9902 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -70,7 +70,7 @@ which it would have done if we had only specified an attribute binding in a regu HTTP request to an invalid location. -# Testing +## Testing
          **`e2e-tests/scenarios.js`**: @@ -95,7 +95,7 @@ views, that we will implement in the upcoming steps. You can now rerun `npm run protractor` to see the tests run. -# Experiments +## Experiments
          @@ -108,7 +108,7 @@ You can now rerun `npm run protractor` to see the tests run. inject the valid address. -# Summary +## Summary Now that you have added phone images and links, go to {@link step_09 step 9} to learn about AngularJS layout templates and how AngularJS makes it easy to create applications that have multiple views. diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index 99683ccfeb44..da1e92a7dfc6 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -334,7 +334,7 @@ The takeaway here is: -# Testing +## Testing Since some of our modules depend on {@link ngRoute ngRoute} now, it is necessary to update the Karma configuration file with angular-route. Other than that, the unit tests should (still) pass without @@ -398,7 +398,7 @@ various URLs and verifying that the correct view was rendered. You can now rerun `npm run protractor` to see the tests run (and hopefully pass). -# Experiments +## Experiments
          @@ -415,7 +415,7 @@ You can now rerun `npm run protractor` to see the tests run (and hopefully pass) component isolation at work! -# Summary +## Summary With the routing set up and the phone list view implemented, we are ready to go to {@link step_10 step 10} and implement a proper phone details view. diff --git a/docs/content/tutorial/step_10.ngdoc b/docs/content/tutorial/step_10.ngdoc index 537f3ded49bf..65069b74ff58 100644 --- a/docs/content/tutorial/step_10.ngdoc +++ b/docs/content/tutorial/step_10.ngdoc @@ -122,7 +122,7 @@ including lists and bindings that comprise the phone details. Note how we use th -# Testing +## Testing We wrote a new unit test that is similar to the one we wrote for the `phoneList` component's controller in {@link step_07#testing step 7}. @@ -194,7 +194,7 @@ heading on the page is "Nexus S". You can run the tests with `npm run protractor`. -# Experiments +## Experiments
          @@ -202,7 +202,7 @@ You can run the tests with `npm run protractor`. images on the 'Nexus S' details page. -# Summary +## Summary Now that the phone details view is in place, proceed to {@link step_11 step 11} to learn how to write your own custom display filter. diff --git a/docs/content/tutorial/step_11.ngdoc b/docs/content/tutorial/step_11.ngdoc index d9ab2565d23e..6bc360cbb647 100644 --- a/docs/content/tutorial/step_11.ngdoc +++ b/docs/content/tutorial/step_11.ngdoc @@ -104,7 +104,7 @@ Let's employ the filter in the phone details template: ``` -# Testing +## Testing Filters, like any other code, should be tested. Luckily, these tests are very easy to write. @@ -146,7 +146,7 @@ Chrome 49.0: Executed 4 of 4 SUCCESS (0.091 secs / 0.075 secs) ``` -# Experiments +## Experiments
          @@ -167,7 +167,7 @@ Chrome 49.0: Executed 4 of 4 SUCCESS (0.091 secs / 0.075 secs) ``` -# Summary +## Summary Now that we have learned how to write and test a custom filter, let's go to {@link step_12 step 12} to learn how we can use AngularJS to enhance the phone details page further. diff --git a/docs/content/tutorial/step_12.ngdoc b/docs/content/tutorial/step_12.ngdoc index e16bdaa5bb2d..b9d4e0850c57 100644 --- a/docs/content/tutorial/step_12.ngdoc +++ b/docs/content/tutorial/step_12.ngdoc @@ -73,7 +73,7 @@ thumbnail image. -# Testing +## Testing To verify this new feature, we added two E2E tests. One verifies that `mainImageUrl` is set to the first phone image URL by default. The second test clicks on several thumbnail images and verifies @@ -151,7 +151,7 @@ property to the controller. As previously, we will use a mocked response. Our unit tests should now be passing again. -# Experiments +## Experiments
          @@ -176,7 +176,7 @@ Our unit tests should now be passing again. Now, whenever you double-click on a thumbnail, an alert pops-up. Pretty annoying! -# Summary +## Summary With the phone image swapper in place, we are ready for {@link step_13 step 13} to learn an even better way to fetch data. diff --git a/docs/content/tutorial/step_13.ngdoc b/docs/content/tutorial/step_13.ngdoc index f96ccd5c1913..2ad46e2c9459 100644 --- a/docs/content/tutorial/step_13.ngdoc +++ b/docs/content/tutorial/step_13.ngdoc @@ -310,7 +310,7 @@ Chrome 49.0: Executed 5 of 5 SUCCESS (0.123 secs / 0.104 secs) ``` -# Summary +## Summary Now that we have seen how to build a custom service as a RESTful client, we are ready for {@link step_14 step 14} to learn how to enhance the user experience with animations. diff --git a/docs/content/tutorial/step_14.ngdoc b/docs/content/tutorial/step_14.ngdoc index b1b5ff043f58..40667717ebee 100644 --- a/docs/content/tutorial/step_14.ngdoc +++ b/docs/content/tutorial/step_14.ngdoc @@ -503,7 +503,7 @@ element). A boolean parameter (`wasCanceled`) is passed to the function, letting if the animation was canceled or not. Use this function to do any necessary clean-up. -# Experiments +## Experiments
          @@ -544,7 +544,7 @@ if the animation was canceled or not. Use this function to do any necessary clea * Go crazy and come up with your own funky animations! -# Summary +## Summary Our application is now much more pleasant to use, thanks to the smooth transitions between pages and UI states. From 77917e34c93668e9936768bed681696d78028748 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sun, 18 Feb 2018 20:32:04 +0100 Subject: [PATCH 540/883] chore(docs.angularjs.org): allow crawling of examples, don't deploy e2e test files --- Gruntfile.js | 2 +- docs/app/assets/robots.txt | 13 ++----------- scripts/docs.angularjs.org-firebase/firebase.json | 9 ++++++++- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index ba5efa0d8f09..70fd9d8a8236 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -341,7 +341,7 @@ module.exports = function(grunt) { }, { cwd: 'build/docs', - src: '**', + src: ['**', '!ptore2e/**'], dest: 'deploy/docs/', expand: true }, diff --git a/docs/app/assets/robots.txt b/docs/app/assets/robots.txt index 36b7daeca859..898272b08202 100644 --- a/docs/app/assets/robots.txt +++ b/docs/app/assets/robots.txt @@ -1,13 +1,4 @@ User-agent: * -Disallow: /examples/ -Disallow: /ptore2e/ -Disallow: /Error404.html - -# The js / map files in the root are used by the embedded examples, not by the app itself -Disallow: /*.js$ -Disallow: /*.map$ - -# (Javascript) crawlers need to access JS files -Allow: /components/*.js -Allow: /js/*.js +# The map files are not required by the app +Disallow: /*.map$ \ No newline at end of file diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index 9e112f2ff9ee..a83409ed7155 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -29,7 +29,14 @@ ], "headers": [ { - "source": "/partials/**", + "source": "/Error404.html", + "headers" : [{ + "key" : "X-Robots-Tag", + "value" : "noindex" + }] + }, + { + "source": "/@(partials|examples)/**", "headers" : [{ "key" : "X-Robots-Tag", "value" : "noindex" From 02fb980de67fc9158920ec4ab0969d544ac96c1a Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sun, 18 Feb 2018 20:35:55 +0100 Subject: [PATCH 541/883] chore(docs.angularjs.org): only deploy production index.html as entry file Previously, we rewrote index.html to index-production.html, but Firebase ignored this, probably because an exact file match always takes priority. This lead to the problem thatthe root - angularjs.org - didn't include the angular.js source files from the CDN --- Gruntfile.js | 12 +++++++----- scripts/docs.angularjs.org-firebase/firebase.json | 13 ------------- .../docs.angularjs.org-firebase/functions/index.js | 2 +- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 70fd9d8a8236..bb3eb9508ee4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -341,15 +341,17 @@ module.exports = function(grunt) { }, { cwd: 'build/docs', - src: ['**', '!ptore2e/**'], + src: ['**', '!ptore2e/**', '!index*.html'], dest: 'deploy/docs/', expand: true }, { - src: ['build/docs/index-production.html'], - dest: docsScriptFolder + '/functions/content', - expand: true, - flatten: true + src: 'build/docs/index-production.html', + dest: 'deploy/docs/index.html' + }, + { + src: 'build/docs/index-production.html', + dest: docsScriptFolder + '/functions/content/index.html' }, { cwd: 'build/docs', diff --git a/scripts/docs.angularjs.org-firebase/firebase.json b/scripts/docs.angularjs.org-firebase/firebase.json index a83409ed7155..0e018010b061 100644 --- a/scripts/docs.angularjs.org-firebase/firebase.json +++ b/scripts/docs.angularjs.org-firebase/firebase.json @@ -1,11 +1,6 @@ { "hosting": { "public": "../../deploy/docs", - "ignore": [ - "/index.html", - "/index-debug.html", - "/index-jquery.html" - ], "redirects": [ { "source": "/error/:namespace\\::error*", @@ -14,14 +9,6 @@ } ], "rewrites": [ - { - "source": "/", - "destination": "/index-production.html" - }, - { - "source": "/index.html", - "destination": "/index-production.html" - }, { "source": "**/*!(.@(jpg|jpeg|gif|png|html|js|map|json|css|svg|ttf|txt|woff|woff2|eot|xml))", "function": "sendFile" diff --git a/scripts/docs.angularjs.org-firebase/functions/index.js b/scripts/docs.angularjs.org-firebase/functions/index.js index b86eb32f642a..eace519a45ad 100644 --- a/scripts/docs.angularjs.org-firebase/functions/index.js +++ b/scripts/docs.angularjs.org-firebase/functions/index.js @@ -25,7 +25,7 @@ const buildSnapshot = data => ` function sendFile(request, response) { const snapshotRequested = typeof request.query._escaped_fragment_ !== 'undefined'; - const filePath = `content/${snapshotRequested ? `partials${request.path}` : 'index-production'}.html`; + const filePath = `content/${snapshotRequested ? `partials${request.path}` : 'index'}.html`; if (snapshotRequested) { fs.readFile(filePath, {encoding: 'utf8'}, (error, data) => { From a37f89f8646df3ea64aee32e63055b9722236753 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 20 Feb 2018 17:59:45 +0100 Subject: [PATCH 542/883] chore(docs-app): add dynamic 404 behavior Adapted from https://github.com/angular/angular/commit/88045a50506adfe32c2f7a213c8e95f46d1e40e1, https://github.com/angular/angular/commit/c3fb820473d64036ef0dd3d4c004cc7fbc67be75, and https://github.com/angular/angular/commit/5a624fa1be530a1b3479a4cc7f96e5a20a3d64fb. --- docs/app/e2e/.eslintrc.json | 1 + docs/app/e2e/app.scenario.js | 63 +++++++++++++++++++ docs/app/src/docs.js | 16 +++-- docs/config/index.js | 5 +- docs/config/services/deployments/test.js | 40 ++++++++++++ .../templates/app/indexPage.template.html | 21 +++++-- 6 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 docs/config/services/deployments/test.js diff --git a/docs/app/e2e/.eslintrc.json b/docs/app/e2e/.eslintrc.json index 6a949b92ffc9..60c814cc9339 100644 --- a/docs/app/e2e/.eslintrc.json +++ b/docs/app/e2e/.eslintrc.json @@ -9,6 +9,7 @@ }, "globals": { + "angular": false, /* testabilityPatch / matchers */ "inject": false, "module": false, diff --git a/docs/app/e2e/app.scenario.js b/docs/app/e2e/app.scenario.js index 1333870eff4d..a78667962ab9 100644 --- a/docs/app/e2e/app.scenario.js +++ b/docs/app/e2e/app.scenario.js @@ -21,6 +21,9 @@ describe('docs.angularjs.org', function() { console.log('browser console errors: ' + require('util').inspect(filteredLog)); } }); + + browser.ignoreSynchronization = false; + browser.clearMockModules(); }); @@ -102,6 +105,66 @@ describe('docs.angularjs.org', function() { expect(mainHeader.getText()).toEqual('Oops!'); }); + it('should set "noindex" if the page does not exist', function() { + browser.get('build/docs/index-production.html#!/api/does/not/exist'); + var robots = element(by.css('meta[name="robots"][content="noindex"]')); + var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]')); + expect(robots.isPresent()).toBe(true); + expect(googleBot.isPresent()).toBe(true); + }); + + it('should remove "noindex" if the page exists', function() { + browser.get('build/docs/index-production.html#!/api'); + var robots = element(by.css('meta[name="robots"][content="noindex"]')); + var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]')); + expect(robots.isPresent()).toBe(false); + expect(googleBot.isPresent()).toBe(false); + }); + + describe('template request error', function() { + beforeEach(function() { + browser.addMockModule('httpMocker', function() { + angular.module('httpMocker', ['ngMock']) + .run(['$httpBackend', function($httpBackend) { + $httpBackend.whenGET('localhost:8000/build/docs/partials/api.html').respond(500, ''); + }]); + }); + }); + + it('should set "noindex" for robots if the request fails', function() { + // index-test includes ngMock + browser.get('build/docs/index-test.html#!/api'); + var robots = element(by.css('meta[name="robots"][content="noindex"]')); + var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]')); + expect(robots.isPresent()).toBe(true); + expect(googleBot.isPresent()).toBe(true); + }); + }); + + + describe('page bootstrap error', function() { + beforeEach(function() { + browser.addMockModule('httpMocker', function() { + // Require a module that does not exist to break the bootstrapping + angular.module('httpMocker', ['doesNotExist']); + }); + }); + + it('should have "noindex" for robots if bootstrapping fails', function() { + browser.get('build/docs/index.html#!/api').catch(function() { + // get() will fail on AngularJS bootstrap, but if we continue here, protractor + // will assume the app is ready + browser.ignoreSynchronization = true; + var robots = element(by.css('meta[name="robots"][content="noindex"]')); + var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]')); + expect(robots.isPresent()).toBe(true); + expect(googleBot.isPresent()).toBe(true); + }); + }); + + + }); + }); }); diff --git a/docs/app/src/docs.js b/docs/app/src/docs.js index 33b1be384beb..b6e6e49a2aa8 100644 --- a/docs/app/src/docs.js +++ b/docs/app/src/docs.js @@ -8,6 +8,8 @@ angular.module('DocsController', ['currentVersionData']) function($scope, $rootScope, $location, $window, $cookies, NG_PAGES, NG_NAVIGATION, CURRENT_NG_VERSION) { + var errorPartialPath = 'Error404.html'; + $scope.navClass = function(navItem) { return { active: navItem.href && this.currentPage && this.currentPage.path, @@ -16,8 +18,6 @@ angular.module('DocsController', ['currentVersionData']) }; }; - - $scope.$on('$includeContentLoaded', function() { var pagePath = $scope.currentPage ? $scope.currentPage.path : $location.path(); $window._gaq.push(['_trackPageview', pagePath]); @@ -26,6 +26,7 @@ angular.module('DocsController', ['currentVersionData']) $scope.$on('$includeContentError', function() { $scope.loading = false; + $scope.loadingError = true; }); $scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) { @@ -35,6 +36,7 @@ angular.module('DocsController', ['currentVersionData']) var currentPage = $scope.currentPage = NG_PAGES[path]; $scope.loading = true; + $scope.loadingError = false; if (currentPage) { $scope.partialPath = 'partials/' + path + '.html'; @@ -50,18 +52,22 @@ angular.module('DocsController', ['currentVersionData']) } else { $scope.currentArea = NG_NAVIGATION['api']; $scope.breadcrumb = []; - $scope.partialPath = 'Error404.html'; + $scope.partialPath = errorPartialPath; } }); + $scope.hasError = function() { + return $scope.partialPath === errorPartialPath || $scope.loadingError; + }; + /********************************** Initialize ***********************************/ $scope.versionNumber = CURRENT_NG_VERSION.full; $scope.version = CURRENT_NG_VERSION.full + ' ' + CURRENT_NG_VERSION.codeName; - $scope.loading = 0; - + $scope.loading = false; + $scope.loadingError = false; var INDEX_PATH = /^(\/|\/index[^.]*.html)$/; if (!$location.path() || INDEX_PATH.test($location.path())) { diff --git a/docs/config/index.js b/docs/config/index.js index 4ddf7922c7bd..12777f6a8f5e 100644 --- a/docs/config/index.js +++ b/docs/config/index.js @@ -22,6 +22,7 @@ module.exports = new Package('angularjs', [ .factory(require('./services/deployments/debug')) .factory(require('./services/deployments/default')) .factory(require('./services/deployments/jquery')) +.factory(require('./services/deployments/test')) .factory(require('./services/deployments/production')) .factory(require('./inline-tag-defs/type')) @@ -157,12 +158,14 @@ module.exports = new Package('angularjs', [ generateProtractorTestsProcessor, generateExamplesProcessor, debugDeployment, defaultDeployment, - jqueryDeployment, productionDeployment) { + jqueryDeployment, testDeployment, + productionDeployment) { generateIndexPagesProcessor.deployments = [ debugDeployment, defaultDeployment, jqueryDeployment, + testDeployment, productionDeployment ]; diff --git a/docs/config/services/deployments/test.js b/docs/config/services/deployments/test.js new file mode 100644 index 000000000000..ba0805b5079a --- /dev/null +++ b/docs/config/services/deployments/test.js @@ -0,0 +1,40 @@ +'use strict'; + +module.exports = function testDeployment(getVersion) { + return { + name: 'test', + examples: { + commonFiles: { + scripts: ['../../../angular.js'] + }, + dependencyPath: '../../../' + }, + scripts: [ + '../angular.js', + '../angular-resource.js', + '../angular-route.js', + '../angular-cookies.js', + '../angular-mocks.js', + '../angular-sanitize.js', + '../angular-touch.js', + '../angular-animate.js', + 'components/marked-' + getVersion('marked') + '/lib/marked.js', + 'js/angular-bootstrap/dropdown-toggle.js', + 'components/lunr-' + getVersion('lunr') + '/lunr.js', + 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js', + 'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js', + 'js/current-version-data.js', + 'js/all-versions-data.js', + 'js/pages-data.js', + 'js/nav-data.js', + 'js/docs.js' + ], + stylesheets: [ + 'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.css', + 'css/prettify-theme.css', + 'css/angular-topnav.css', + 'css/docs.css', + 'css/animations.css' + ] + }; +}; diff --git a/docs/config/templates/app/indexPage.template.html b/docs/config/templates/app/indexPage.template.html index 44ef6ebd7b1a..eb5c6614a2bc 100644 --- a/docs/config/templates/app/indexPage.template.html +++ b/docs/config/templates/app/indexPage.template.html @@ -11,6 +11,18 @@ AngularJS + - * - *
          - *
          - *
          - * Current time is: - *
          - * Blood 1 : {{blood_1}} - * Blood 2 : {{blood_2}} - * - * - * - *
          - *
          - * - * - * - */ + /** + * @ngdoc service + * @name $interval + * + * @description + * AngularJS's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + *
          + * **Note**: Intervals created by this service must be explicitly destroyed when you are finished + * with them. In particular they are not automatically destroyed when a controller's scope or a + * directive's element are destroyed. + * You should take this into consideration and make sure to always cancel the interval at the + * appropriate moment. See the example below for more details on how and when to do this. + *
          + * + * @param {function()} fn A function that should be called repeatedly. If no additional arguments + * are passed (see below), the function is called with the current iteration count. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {promise} A promise which will be notified on each iteration. It will resolve once all iterations of the interval complete. + * + * @example + * + * + * + * + *
          + *
          + *
          + * Current time is: + *
          + * Blood 1 : {{blood_1}} + * Blood 2 : {{blood_2}} + * + * + * + *
          + *
          + * + *
          + *
          + */ function interval(fn, delay, count, invokeApply) { var hasParams = arguments.length > 4, args = hasParams ? sliceArgs(arguments, 4) : [], @@ -177,16 +177,16 @@ function $IntervalProvider() { } - /** - * @ngdoc method - * @name $interval#cancel - * - * @description - * Cancels a task associated with the `promise`. - * - * @param {Promise=} promise returned by the `$interval` function. - * @returns {boolean} Returns `true` if the task was successfully canceled. - */ + /** + * @ngdoc method + * @name $interval#cancel + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {Promise=} promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ interval.cancel = function(promise) { if (promise && promise.$$intervalId in intervals) { // Interval cancels should not report as unhandled promise. From 3365256502344970f86355d3ace1cb4251ae9828 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 13 Mar 2018 19:52:58 +0200 Subject: [PATCH 550/883] fix($timeout): throw when trying to cancel non-$timeout promise Previously, calling `$timeout.cancel()` with a promise that was not generated by a call to `$timeout()` would do nothing. This could, for example, happen when calling `.then()`/`.catch()` on the returned promise, which creates a new promise, and passing that to `$timeout.cancel()`. With this commit, `$timeout.cancel()` will throw an error if called with a non-$timeout promise, thus surfacing errors that would otherwise go unnoticed. Fixes #16424 BREAKING CHNAGE: `$timeout.cancel()` will throw an error if called with a promise that was not generated by `$timeout()`. Previously, it would silently do nothing. Before: ```js var promise = $timeout(doSomething, 1000).then(doSomethingElse); $timeout.cancel(promise); // No error; timeout NOT canceled. ``` After: ```js var promise = $timeout(doSomething, 1000).then(doSomethingElse); $timeout.cancel(promise); // Throws error. ``` Correct usage: ```js var promise = $timeout(doSomething, 1000); var newPromise = promise.then(doSomethingElse); $timeout.cancel(promise); // Timeout canceled. ``` --- docs/content/error/$timeout/badprom.ngdoc | 25 ++++++++++++++++++++++ src/ng/timeout.js | 26 +++++++++++++++++------ test/ng/timeoutSpec.js | 8 ++++++- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 docs/content/error/$timeout/badprom.ngdoc diff --git a/docs/content/error/$timeout/badprom.ngdoc b/docs/content/error/$timeout/badprom.ngdoc new file mode 100644 index 000000000000..c1b0d025ad8f --- /dev/null +++ b/docs/content/error/$timeout/badprom.ngdoc @@ -0,0 +1,25 @@ +@ngdoc error +@name $timeout:badprom +@fullName Non-$timeout promise +@description + +This error occurs when calling {@link ng.$timeout#cancel $timeout.cancel()} with a promise that +was not generated by the {@link ng.$timeout $timeout} service. This can, for example, happen when +calling {@link ng.$q#the-promise-api then()/catch()} on the returned promise, which creates a new +promise, and pass that new promise to {@link ng.$timeout#cancel $timeout.cancel()}. + +Example of incorrect usage that leads to this error: + +```js +var promise = $timeout(doSomething, 1000).then(doSomethingElse); +$timeout.cancel(promise); +``` + +To fix the example above, keep a reference to the promise returned by +{@link ng.$timeout $timeout()} and pass that to {@link ng.$timeout#cancel $timeout.cancel()}: + +```js +var promise = $timeout(doSomething, 1000); +var newPromise = promise.then(doSomethingElse); +$timeout.cancel(promise); +``` diff --git a/src/ng/timeout.js b/src/ng/timeout.js index 71c06ce39ab0..1e4eaad3349f 100644 --- a/src/ng/timeout.js +++ b/src/ng/timeout.js @@ -1,5 +1,7 @@ 'use strict'; +var $timeoutMinErr = minErr('$timeout'); + /** @this */ function $TimeoutProvider() { this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', @@ -83,14 +85,24 @@ function $TimeoutProvider() { * canceled. */ timeout.cancel = function(promise) { - if (promise && promise.$$timeoutId in deferreds) { - // Timeout cancels should not report an unhandled promise. - markQExceptionHandled(deferreds[promise.$$timeoutId].promise); - deferreds[promise.$$timeoutId].reject('canceled'); - delete deferreds[promise.$$timeoutId]; - return $browser.defer.cancel(promise.$$timeoutId); + if (!promise) return false; + + if (!promise.hasOwnProperty('$$timeoutId')) { + throw $timeoutMinErr('badprom', + '`$timeout.cancel()` called with a promise that was not generated by `$timeout()`.'); } - return false; + + if (!deferreds.hasOwnProperty(promise.$$timeoutId)) return false; + + var id = promise.$$timeoutId; + var deferred = deferreds[id]; + + // Timeout cancels should not report an unhandled promise. + markQExceptionHandled(deferred.promise); + deferred.reject('canceled'); + delete deferreds[id]; + + return $browser.defer.cancel(id); }; return timeout; diff --git a/test/ng/timeoutSpec.js b/test/ng/timeoutSpec.js index 648c39663c0d..bfd5d53285e7 100644 --- a/test/ng/timeoutSpec.js +++ b/test/ng/timeoutSpec.js @@ -280,11 +280,17 @@ describe('$timeout', function() { })); - it('should not throw a runtime exception when given an undefined promise', inject(function($timeout) { + it('should not throw an error when given an undefined promise', inject(function($timeout) { expect($timeout.cancel()).toBe(false); })); + it('should throw an error when given a non-$timeout promise', inject(function($timeout) { + var promise = $timeout(noop).then(noop); + expect(function() { $timeout.cancel(promise); }).toThrowMinErr('$timeout', 'badprom'); + })); + + it('should forget references to relevant deferred', inject(function($timeout, $browser) { // $browser.defer.cancel is only called on cancel if the deferred object is still referenced var cancelSpy = spyOn($browser.defer, 'cancel').and.callThrough(); From a8bef95127775d83d80daa4617c33227c4b443d4 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 13 Mar 2018 19:53:56 +0200 Subject: [PATCH 551/883] fix($interval): throw when trying to cancel non-$interval promise Previously, calling `$interval.cancel()` with a promise that was not generated by a call to `$interval()` would do nothing. This could, for example, happen when calling `.then()`/`.catch()` on the returned promise, which creates a new promise, and passing that to `$interval.cancel()`. With this commit, `$interval.cancel()` will throw an error if called with a non-$interval promise, thus surfacing errors that would otherwise go unnoticed. Related to #16424. BREAKING CHNAGE: `$interval.cancel()` will throw an error if called with a promise that was not generated by `$interval()`. Previously, it would silently do nothing. Before: ```js var promise = $interval(doSomething, 1000, 5).then(doSomethingElse); $interval.cancel(promise); // No error; interval NOT canceled. ``` After: ```js var promise = $interval(doSomething, 1000, 5).then(doSomethingElse); $interval.cancel(promise); // Throws error. ``` Correct usage: ```js var promise = $interval(doSomething, 1000, 5); var newPromise = promise.then(doSomethingElse); $interval.cancel(promise); // Interval canceled. ``` Closes #16476 --- docs/content/error/$interval/badprom.ngdoc | 25 +++++++++++++++++++ src/ng/interval.js | 28 +++++++++++++++------- test/ng/intervalSpec.js | 9 +++++-- 3 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 docs/content/error/$interval/badprom.ngdoc diff --git a/docs/content/error/$interval/badprom.ngdoc b/docs/content/error/$interval/badprom.ngdoc new file mode 100644 index 000000000000..2c9f8c5371a9 --- /dev/null +++ b/docs/content/error/$interval/badprom.ngdoc @@ -0,0 +1,25 @@ +@ngdoc error +@name $interval:badprom +@fullName Non-$interval promise +@description + +This error occurs when calling {@link ng.$interval#cancel $interval.cancel()} with a promise that +was not generated by the {@link ng.$interval $interval} service. This can, for example, happen when +calling {@link ng.$q#the-promise-api then()/catch()} on the returned promise, which creates a new +promise, and pass that new promise to {@link ng.$interval#cancel $interval.cancel()}. + +Example of incorrect usage that leads to this error: + +```js +var promise = $interval(doSomething, 1000, 5).then(doSomethingElse); +$interval.cancel(promise); +``` + +To fix the example above, keep a reference to the promise returned by +{@link ng.$interval $interval()} and pass that to {@link ng.$interval#cancel $interval.cancel()}: + +```js +var promise = $interval(doSomething, 1000, 5); +var newPromise = promise.then(doSomethingElse); +$interval.cancel(promise); +``` diff --git a/src/ng/interval.js b/src/ng/interval.js index a34682ed007d..750a6ba3df1c 100644 --- a/src/ng/interval.js +++ b/src/ng/interval.js @@ -1,5 +1,7 @@ 'use strict'; +var $intervalMinErr = minErr('$interval'); + /** @this */ function $IntervalProvider() { this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser', @@ -188,15 +190,25 @@ function $IntervalProvider() { * @returns {boolean} Returns `true` if the task was successfully canceled. */ interval.cancel = function(promise) { - if (promise && promise.$$intervalId in intervals) { - // Interval cancels should not report as unhandled promise. - markQExceptionHandled(intervals[promise.$$intervalId].promise); - intervals[promise.$$intervalId].reject('canceled'); - $window.clearInterval(promise.$$intervalId); - delete intervals[promise.$$intervalId]; - return true; + if (!promise) return false; + + if (!promise.hasOwnProperty('$$intervalId')) { + throw $intervalMinErr('badprom', + '`$interval.cancel()` called with a promise that was not generated by `$interval()`.'); } - return false; + + if (!intervals.hasOwnProperty(promise.$$intervalId)) return false; + + var id = promise.$$intervalId; + var deferred = intervals[id]; + + // Interval cancels should not report an unhandled promise. + markQExceptionHandled(deferred.promise); + deferred.reject('canceled'); + $window.clearInterval(id); + delete intervals[id]; + + return true; }; return interval; diff --git a/test/ng/intervalSpec.js b/test/ng/intervalSpec.js index 47281429e0b2..3b23250d1f98 100644 --- a/test/ng/intervalSpec.js +++ b/test/ng/intervalSpec.js @@ -335,12 +335,17 @@ describe('$interval', function() { })); - it('should not throw a runtime exception when given an undefined promise', - inject(function($interval) { + it('should not throw an error when given an undefined promise', inject(function($interval) { expect($interval.cancel()).toBe(false); })); + it('should throw an error when given a non-$interval promise', inject(function($interval) { + var promise = $interval(noop).then(noop); + expect(function() { $interval.cancel(promise); }).toThrowMinErr('$interval', 'badprom'); + })); + + it('should not trigger digest when cancelled', inject(function($interval, $rootScope, $browser) { var watchSpy = jasmine.createSpy('watchSpy'); $rootScope.$watch(watchSpy); From 98e0e047b0f705005b256c70feb4e6368ff3a591 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 14 Mar 2018 22:35:34 +0100 Subject: [PATCH 552/883] docs(ngShow/ngHide): add note about flicker when toggling elements Related to https://github.com/angular/angular.js/issues/14015 Closes #16489 --- src/ng/directive/ngShowHide.js | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/ng/directive/ngShowHide.js b/src/ng/directive/ngShowHide.js index 74f02f923989..8e24b5ba081c 100644 --- a/src/ng/directive/ngShowHide.js +++ b/src/ng/directive/ngShowHide.js @@ -182,6 +182,25 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; }); + * + * @knownIssue + * + * ### Flickering when using ngShow to toggle between elements + * + * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can + * happen that both the element to show and the element to hide are visible for a very short time. + * + * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations + * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than + * other browsers. + * + * There are several way to mitigate this problem: + * + * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}. + * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}. + * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements. + * - Use `ng-class="{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}. + * - Define an animation on the affected elements. */ var ngShowDirective = ['$animate', function($animate) { return { @@ -382,6 +401,25 @@ var ngShowDirective = ['$animate', function($animate) { }); + * + * @knownIssue + * + * ### Flickering when using ngHide to toggle between elements + * + * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can + * happen that both the element to show and the element to hide are visible for a very short time. + * + * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations + * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than + * other browsers. + * + * There are several way to mitigate this problem: + * + * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}. + * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}. + * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements. + * - Use `ng-class="{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}. + * - Define an animation on the affected elements. */ var ngHideDirective = ['$animate', function($animate) { return { From c0bc1df3f73d03455175ca7e2002c026a0b64b4c Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 16 Mar 2018 16:48:12 +0100 Subject: [PATCH 553/883] chore(travis): update iOs test browsers Closes #16493 --- karma-shared.conf.js | 28 +++++++++++++--------------- scripts/travis/build.sh | 2 +- test/ng/directive/ngOptionsSpec.js | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index e95a95fbc111..ec06ed40a369 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -104,11 +104,15 @@ module.exports = function(config, specificOptions) { platform: 'Windows 10', version: 'latest-1' }, - 'SL_iOS': { + 'SL_iOS_10': { base: 'SauceLabs', browserName: 'iphone', - platform: 'OS X 10.10', - version: '8.1' + version: '10.3' + }, + 'SL_iOS_11': { + base: 'SauceLabs', + browserName: 'iphone', + version: '11' }, 'BS_Chrome': { @@ -156,23 +160,17 @@ module.exports = function(config, specificOptions) { os: 'Windows', os_version: '10' }, - 'BS_iOS_8': { - base: 'BrowserStack', - device: 'iPhone 6', - os: 'ios', - os_version: '8.3' - }, - 'BS_iOS_9': { - base: 'BrowserStack', - device: 'iPhone 6S', - os: 'ios', - os_version: '9.3' - }, 'BS_iOS_10': { base: 'BrowserStack', device: 'iPhone 7', os: 'ios', os_version: '10.0' + }, + 'BS_iOS_11': { + base: 'BrowserStack', + device: 'iPhone 8', + os: 'ios', + os_version: '11.0' } } }); diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index 9338247915a3..39c62de0de65 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -14,7 +14,7 @@ SAUCE_ACCESS_KEY=$(echo "$SAUCE_ACCESS_KEY" | rev) BROWSERS="SL_Chrome,SL_Chrome-1,\ SL_Firefox,SL_Firefox-1,\ SL_Safari,SL_Safari-1,\ -SL_iOS,\ +SL_iOS_10,SL_iOS_11,\ SL_IE_9,SL_IE_10,SL_IE_11,\ SL_EDGE,SL_EDGE-1" diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index 2af26f489367..56b11d04f0d2 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -2928,7 +2928,7 @@ describe('ngOptions', function() { // getter/setter is not defined on the prototype (probably due to some bug). On Safari 9, the // getter/setter that is already defined on the `