From e31464b47d19f78f26694b2aa908238dfedfcd79 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 25 Sep 2017 15:46:29 +0100 Subject: [PATCH 01/99] Keep track of pdf layout hidden state --- services/web/public/coffee/ide.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index d37334649c..e317b355ef 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -71,11 +71,12 @@ define [ view: "editor" chatOpen: false pdfLayout: 'sideBySide' + pdfHidden: false, reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}") miniReviewPanelVisible: false } $scope.user = window.user - + $scope.$watch "project.features.trackChangesVisible", (visible) -> return if !visible? $scope.ui.showCollabFeaturesOnboarding = window.showTrackChangesOnboarding and visible @@ -99,6 +100,9 @@ define [ if value? localStorage "ui.reviewPanelOpen.#{window.project_id}", value + $scope.$on "layout:pdf:resize", (_, layoutState) -> + $scope.ui.pdfHidden = layoutState.east.initClosed + # Tracking code. $scope.$watch "ui.view", (newView, oldView) -> if newView? and newView != "editor" and newView != "pdf" From 5b3c9f4033cbde25a708a30e59578c1e41bf050f Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 25 Sep 2017 15:46:43 +0100 Subject: [PATCH 02/99] Prevent autocompile if pdf preview is hidden --- .../web/public/coffee/ide/pdf/controllers/PdfController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index ce3c8cbce1..93166d4388 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -77,7 +77,7 @@ define [ autoCompileTimeout = null triggerAutoCompile = () -> - return if autoCompileTimeout + return if autoCompileTimeout or $scope.ui.pdfHidden timeSinceLastCompile = Date.now() - $scope.recompiledAt # If time is non-monotonic, assume that the user's system clock has been From 0f855689a7c6c4b7d5f1a8a0aeefecfb41ba2c1c Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 26 Sep 2017 08:07:35 +0100 Subject: [PATCH 03/99] show error for compile in progress --- services/web/app/coffee/Features/Compile/ClsiManager.coffee | 2 ++ services/web/app/views/project/editor/pdf.pug | 4 ++++ .../public/coffee/ide/pdf/controllers/PdfController.coffee | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 68b13a8f68..46cb4e35e3 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -107,6 +107,8 @@ module.exports = ClsiManager = callback null, compile:status:"project-too-large" else if response.statusCode == 409 callback null, compile:status:"conflict" + else if response.statusCode == 423 + callback null, compile:status:"compile-in-progress" else error = new Error("CLSI returned non-success code: #{response.statusCode}") logger.error err: error, project_id: project_id, "CLSI returned failure code" diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index db4a0e9dd3..065dd0cec0 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -344,6 +344,10 @@ div.full-size.pdf(ng-controller="PdfController") strong #{translate("pdf_compile_rate_limit_hit")} span #{translate("project_flagged_too_many_compiles")} + .alert.alert-danger(ng-show="pdf.compileInProgress") + strong #{translate("pdf_compile_in_progress_error")} + span #{translate("pdf_compile_try_again")} + .alert.alert-danger(ng-show="pdf.timedout") p strong #{translate("timedout")}. diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index ce3c8cbce1..ed69ee63f7 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -167,6 +167,7 @@ define [ $scope.pdf.compileTerminated = false $scope.pdf.compileExited = false $scope.pdf.failedCheck = false + $scope.pdf.compileInProgress = false # make a cache to look up files by name fileByPath = {} @@ -223,6 +224,9 @@ define [ else if response.status == "validation-problems" $scope.pdf.view = "validation-problems" $scope.pdf.validation = response.validationProblems + else if response.status == "compile-in-progress" + $scope.pdf.view = 'errors' + $scope.pdf.compileInProgress = true else if response.status == "success" $scope.pdf.view = 'pdf' $scope.shouldShowLogs = false From 2c0e9bb89af261f0ae0e49027079a86ce0aefcb9 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Tue, 26 Sep 2017 10:19:30 +0100 Subject: [PATCH 04/99] return overleaf details from ProejctsDetailsHandler.getdetails --- .../Project/ProjectDetailsHandler.coffee | 10 +++++++--- .../Project/ProjectDetailsHandlerTests.coffee | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee index 8234907ff4..5819e03472 100644 --- a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee @@ -9,7 +9,7 @@ Errors = require("../Errors/Errors") module.exports = ProjectDetailsHandler = getDetails: (project_id, callback)-> - ProjectGetter.getProject project_id, {name:true, description:true, compiler:true, features:true, owner_ref:true}, (err, project)-> + ProjectGetter.getProject project_id, {name:true, description:true, compiler:true, features:true, owner_ref:true, overleaf:true}, (err, project)-> if err? logger.err err:err, project_id:project_id, "error getting project" return callback(err) @@ -21,7 +21,11 @@ module.exports = ProjectDetailsHandler = description: project.description compiler: project.compiler features: user.features - logger.log project_id:project_id, details:details, "getting project details" + + if project.overleaf? + details.overleaf = project.overleaf + + logger.log project_id:project_id, details: details, "getting project details" callback(err, details) getProjectDescription: (project_id, callback)-> @@ -66,4 +70,4 @@ module.exports = ProjectDetailsHandler = logger.log project_id: project_id, level: newAccessLevel, "set public access level" if project_id? && newAccessLevel? and _.include [PublicAccessLevels.READ_ONLY, PublicAccessLevels.READ_AND_WRITE, PublicAccessLevels.PRIVATE], newAccessLevel Project.update {_id:project_id},{publicAccesLevel:newAccessLevel}, (err)-> - callback() \ No newline at end of file + callback() diff --git a/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee index c4c3b3ef07..abb0b505d0 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee @@ -12,7 +12,7 @@ describe 'ProjectDetailsHandler', -> beforeEach -> @project_id = "321l3j1kjkjl" @user_id = "user-id-123" - @project = + @project = name: "project" description: "this is a great project" something:"should not exist" @@ -20,7 +20,7 @@ describe 'ProjectDetailsHandler', -> owner_ref: @user_id @user = features: "mock-features" - @ProjectGetter = + @ProjectGetter = getProjectWithoutDocLines: sinon.stub().callsArgWith(1, null, @project) getProject: sinon.stub().callsArgWith(2, null, @project) @ProjectModel = @@ -42,7 +42,7 @@ describe 'ProjectDetailsHandler', -> describe "getDetails", -> it "should find the project and owner", (done)-> - @handler.getDetails @project_id, (err, details)=> + @handler.getDetails @project_id, (err, details)=> details.name.should.equal @project.name details.description.should.equal @project.description details.compiler.should.equal @project.compiler @@ -50,6 +50,13 @@ describe 'ProjectDetailsHandler', -> assert.equal(details.something, undefined) done() + it "should find overleaf metadata if it exists", (done)-> + @project.overleaf = { id: 'id' } + @handler.getDetails @project_id, (err, details)=> + details.overleaf.should.equal @project.overleaf + assert.equal(details.something, undefined) + done() + it "should return an error for a non-existent project", (done)-> @ProjectGetter.getProject.callsArg(2, null, null) err = new Errors.NotFoundError("project not found") @@ -79,7 +86,7 @@ describe 'ProjectDetailsHandler', -> @handler.getProjectDescription @project_id, (returnedErr, returnedDescription)=> err.should.equal returnedErr description.should.equal returnedDescription - done() + done() describe "setProjectDescription", -> @@ -110,7 +117,7 @@ describe 'ProjectDetailsHandler', -> @handler.renameProject @project_id, @newName, => @tpdsUpdateSender.moveEntity.calledWith({project_id:@project_id, project_name:@project.name, newProjectName:@newName}).should.equal true done() - + it "should not do anything with an invalid name", (done) -> @handler.validateProjectName = sinon.stub().yields(new Error("invalid name")) @handler.renameProject @project_id, @newName, => From 4adf88ca01eb7988c676814ab5c6494a49677e34 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Tue, 26 Sep 2017 10:19:49 +0100 Subject: [PATCH 05/99] handle OL or SL ids in UserInfoController.getPersonalInfo --- .../Features/User/UserInfoController.coffee | 14 ++++- .../User/UserInfoControllerTests.coffee | 59 +++++++++++++++---- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/services/web/app/coffee/Features/User/UserInfoController.coffee b/services/web/app/coffee/Features/User/UserInfoController.coffee index 8054f48afe..0de5501e3c 100644 --- a/services/web/app/coffee/Features/User/UserInfoController.coffee +++ b/services/web/app/coffee/Features/User/UserInfoController.coffee @@ -4,6 +4,7 @@ UserDeleter = require("./UserDeleter") UserUpdater = require("./UserUpdater") sanitize = require('sanitizer') AuthenticationController = require('../Authentication/AuthenticationController') +ObjectId = require("mongojs").ObjectId module.exports = UserController = getLoggedInUsersPersonalInfo: (req, res, next = (error) ->) -> @@ -19,8 +20,17 @@ module.exports = UserController = UserController.sendFormattedPersonalInfo(user, res, next) getPersonalInfo: (req, res, next = (error) ->) -> - UserGetter.getUser req.params.user_id, { _id: true, first_name: true, last_name: true, email: true}, (error, user) -> - logger.log user_id: req.params.user_id, "reciving request for getting users personal info" + {user_id} = req.params + + if user_id.match(/^\d+$/) + query = { "overleaf.id": parseInt(user_id, 10) } + else if user_id.match(/^[a-f0-9]{24}$/) + query = { _id: ObjectId(user_id) } + else + return res.send(400) + + UserGetter.getUser query, { _id: true, first_name: true, last_name: true, email: true}, (error, user) -> + logger.log user_id: req.params.user_id, "receiving request for getting users personal info" return next(error) if error? return res.send(404) if !user? UserController.sendFormattedPersonalInfo(user, res, next) diff --git a/services/web/test/UnitTests/coffee/User/UserInfoControllerTests.coffee b/services/web/test/UnitTests/coffee/User/UserInfoControllerTests.coffee index 37a1c034f0..7f1c0917d6 100644 --- a/services/web/test/UnitTests/coffee/User/UserInfoControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/User/UserInfoControllerTests.coffee @@ -12,9 +12,9 @@ ObjectId = require("mongojs").ObjectId describe "UserInfoController", -> beforeEach -> - @UserDeleter = + @UserDeleter = deleteUser: sinon.stub().callsArgWith(1) - @UserUpdater = + @UserUpdater = updatePersonalInfo: sinon.stub() @sanitizer = escape:(v)->v sinon.spy @sanitizer, "escape" @@ -50,23 +50,47 @@ describe "UserInfoController", -> .should.equal true describe "getPersonalInfo", -> - beforeEach -> - @user_id = ObjectId().toString() - @user = - _id: ObjectId(@user_id) - @req.params = user_id: @user_id - - describe "when the user exists", -> + describe "when the user exists with sharelatex id", -> beforeEach -> + @user_id = ObjectId().toString() + @user = + _id: ObjectId(@user_id) + @req.params = user_id: @user_id @UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user) @UserInfoController.sendFormattedPersonalInfo = sinon.stub() @UserInfoController.getPersonalInfo(@req, @res, @next) it "should look up the user in the database", -> @UserGetter.getUser - .calledWith(@user_id, { _id: true, first_name: true, last_name: true, email: true }) + .calledWith( + { _id: ObjectId(@user_id) }, + { _id: true, first_name: true, last_name: true, email: true } + ).should.equal true + + it "should send the formatted details back to the client", -> + @UserInfoController.sendFormattedPersonalInfo + .calledWith(@user, @res, @next) .should.equal true - + + describe "when the user exists with overleaf id", -> + beforeEach -> + @user_id = 12345 + @user = + _id: ObjectId() + overleaf: + id: @user_id + @req.params = user_id: @user_id.toString() + @UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user) + @UserInfoController.sendFormattedPersonalInfo = sinon.stub() + @UserInfoController.getPersonalInfo(@req, @res, @next) + + it "should look up the user in the database", -> + @UserGetter.getUser + .calledWith( + { "overleaf.id": @user_id }, + { _id: true, first_name: true, last_name: true, email: true } + ).should.equal true + it "should send the formatted details back to the client", -> @UserInfoController.sendFormattedPersonalInfo .calledWith(@user, @res, @next) @@ -74,13 +98,24 @@ describe "UserInfoController", -> describe "when the user does not exist", -> beforeEach -> + @user_id = ObjectId().toString() + @req.params = user_id: @user_id @UserGetter.getUser = sinon.stub().callsArgWith(2, null, null) - @UserInfoController.sendFormattedPersonalInfo = sinon.stub() @UserInfoController.getPersonalInfo(@req, @res, @next) it "should return 404 to the client", -> @res.statusCode.should.equal 404 + describe "when the user id is invalid", -> + beforeEach -> + @user_id = "invalid" + @req.params = user_id: @user_id + @UserGetter.getUser = sinon.stub().callsArgWith(2, null, null) + @UserInfoController.getPersonalInfo(@req, @res, @next) + + it "should return 400 to the client", -> + @res.statusCode.should.equal 400 + describe "sendFormattedPersonalInfo", -> beforeEach -> @user = From 1502da85cf0fd15daa1adbaa05bad35c1e479709 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 27 Sep 2017 10:37:20 +0200 Subject: [PATCH 06/99] Set up acceptance tests to run in docker container --- services/web/Gruntfile.coffee | 25 ++++++++++++++-- services/web/Jenkinsfile | 6 ++++ services/web/package.json | 4 ++- .../coffee/AuthorizationTests.coffee | 3 ++ .../coffee/helpers/MockDocUpdaterApi.coffee | 12 ++++++++ .../coffee/helpers/MockDocstoreApi.coffee | 29 +++++++++++++++++++ .../web/test/acceptance/scripts/full-test.sh | 26 +++++++++++++++++ 7 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee create mode 100644 services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee create mode 100755 services/web/test/acceptance/scripts/full-test.sh diff --git a/services/web/Gruntfile.coffee b/services/web/Gruntfile.coffee index 0845b435c2..82ec9987e3 100644 --- a/services/web/Gruntfile.coffee +++ b/services/web/Gruntfile.coffee @@ -20,6 +20,8 @@ module.exports = (grunt) -> grunt.loadNpmTasks 'grunt-parallel' grunt.loadNpmTasks 'grunt-exec' grunt.loadNpmTasks 'grunt-postcss' + grunt.loadNpmTasks 'grunt-forever' + grunt.loadNpmTasks 'grunt-shell' # grunt.loadNpmTasks 'grunt-contrib-imagemin' # grunt.loadNpmTasks 'grunt-sprity' @@ -31,6 +33,10 @@ module.exports = (grunt) -> cssmin: command:"node_modules/clean-css/bin/cleancss --s0 -o public/stylesheets/style.css public/stylesheets/style.css" + forever: + app: + options: + index: "app.js" watch: coffee: @@ -244,8 +250,11 @@ module.exports = (grunt) -> pattern: "@@RELEASE@@" replacement: process.env.BUILD_NUMBER || "(unknown build)" - - + shell: + fullAcceptanceTests: + command: "bash ./test/acceptance/scripts/full-test.sh" + dockerTests: + command: 'docker run -v "$(pwd):/app" --env SHARELATEX_ALLOW_PUBLIC_ACCESS=true --rm sharelatex/acceptance-test-runner' availabletasks: tasks: @@ -396,6 +405,18 @@ module.exports = (grunt) -> grunt.registerTask 'test:acceptance', 'Run the acceptance tests (use --grep= or --feature= for individual tests)', ['compile:acceptance_tests', 'mochaTest:acceptance'] grunt.registerTask 'test:smoke', 'Run the smoke tests', ['compile:smoke_tests', 'mochaTest:smoke'] + grunt.registerTask( + 'test:acceptance:full', + "Start server and run acceptance tests", + ['shell:fullAcceptanceTests'] + ) + + grunt.registerTask( + 'test:acceptance:docker', + "Run acceptance tests inside docker container", + ['compile:acceptance_tests', 'shell:dockerTests'] + ) + grunt.registerTask 'test:modules:unit', 'Run the unit tests for the modules', ['compile:modules:server', 'compile:modules:unit_tests'].concat(moduleUnitTestTasks) grunt.registerTask 'run:watch', "Compile and run the web-sharelatex server", ['compile', 'env:run', 'parallel'] diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index c43f82ac4e..dbc86d99fd 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -113,6 +113,12 @@ pipeline { } } + stage('Acceptance Tests') { + steps { + sh './node_modules/.bin/grunt test:acceptance:docker' + } + } + stage('Package') { steps { sh 'rm -rf ./node_modules/grunt*' diff --git a/services/web/package.json b/services/web/package.json index 335e99b85d..25122f635d 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -75,9 +75,9 @@ "bunyan": "0.22.1", "chai": "3.5.0", "chai-spies": "", - "grunt": "0.4.5", "clean-css": "^3.4.18", "es6-promise": "^4.0.5", + "grunt": "0.4.5", "grunt-available-tasks": "0.4.1", "grunt-bunyan": "0.5.0", "grunt-contrib-clean": "0.5.0", @@ -89,12 +89,14 @@ "grunt-exec": "^0.4.7", "grunt-execute": "^0.2.2", "grunt-file-append": "0.0.6", + "grunt-forever": "^0.4.7", "grunt-git-rev-parse": "^0.1.4", "grunt-mocha-test": "0.9.0", "grunt-newer": "^1.2.0", "grunt-parallel": "^0.5.1", "grunt-postcss": "^0.8.0", "grunt-sed": "^0.1.1", + "grunt-shell": "^2.1.0", "sandboxed-module": "0.2.0", "sinon": "^1.17.0", "timekeeper": "", diff --git a/services/web/test/acceptance/coffee/AuthorizationTests.coffee b/services/web/test/acceptance/coffee/AuthorizationTests.coffee index 05c1615a3e..37cc48226f 100644 --- a/services/web/test/acceptance/coffee/AuthorizationTests.coffee +++ b/services/web/test/acceptance/coffee/AuthorizationTests.coffee @@ -4,6 +4,9 @@ User = require "./helpers/User" request = require "./helpers/request" settings = require "settings-sharelatex" +MockDocstoreApi = require './helpers/MockDocstoreApi' +MockDocUpdaterApi = require './helpers/MockDocUpdaterApi' + try_read_access = (user, project_id, test, callback) -> async.series [ (cb) -> diff --git a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee new file mode 100644 index 0000000000..07ecc33b9a --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee @@ -0,0 +1,12 @@ +express = require("express") +app = express() + +module.exports = MockDocUpdaterApi = + run: () -> + app.post "/project/:project_id/flush", (req, res, next) => + res.sendStatus 200 + + app.listen 3003, (error) -> + throw error if error? + +MockDocUpdaterApi.run() diff --git a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee new file mode 100644 index 0000000000..e7b0e4142c --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee @@ -0,0 +1,29 @@ +express = require("express") +bodyParser = require "body-parser" +app = express() + +module.exports = MockDocUpdaterApi = + docs: {} + + run: () -> + app.post "/project/:project_id/doc/:doc_id", bodyParser.json(), (req, res, next) => + {project_id, doc_id} = req.params + {lines, version, ranges} = req.body + @docs[project_id] ?= {} + @docs[project_id][doc_id] = {lines, version, ranges} + @docs[project_id][doc_id].rev ?= 0 + @docs[project_id][doc_id].rev += 1 + res.json { + modified: true + rev: @docs[project_id][doc_id].rev + } + + app.get "/project/:project_id/doc", (req, res, next) => + docs = (doc for doc_id, doc of @docs[req.params.project_id]) + res.send JSON.stringify docs + + app.listen 3016, (error) -> + throw error if error? + +MockDocUpdaterApi.run() + diff --git a/services/web/test/acceptance/scripts/full-test.sh b/services/web/test/acceptance/scripts/full-test.sh new file mode 100755 index 0000000000..c8ce75dd4b --- /dev/null +++ b/services/web/test/acceptance/scripts/full-test.sh @@ -0,0 +1,26 @@ +#! /usr/bin/env bash + +# If you're running on OS X, you probably need to manually +# 'rm -r node_modules/bcrypt; npm install bcrypt' inside +# the docker container, before it will start. +# npm rebuild bcrypt + +echo ">> Starting server..." + +grunt --no-color forever:app:start + +echo ">> Server started" + +sleep 5 + +echo ">> Running acceptance tests..." +grunt --no-color mochaTest:acceptance +_test_exit_code=$? + +echo ">> Killing server" + +grunt --no-color forever:app:stop + +echo ">> Done" + +exit $_test_exit_code \ No newline at end of file From ffc35d9d65b5efab278d9c55ee8183cb9e71ac87 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 27 Sep 2017 10:50:34 +0200 Subject: [PATCH 07/99] Include docker command directly because node isn't available in Jenkins --- services/web/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index dbc86d99fd..93f0a31008 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -115,7 +115,8 @@ pipeline { stage('Acceptance Tests') { steps { - sh './node_modules/.bin/grunt test:acceptance:docker' + sh 'docker pull sharelatex/acceptance-test-runner' + sh 'docker run --rm -v $(pwd):/app --env SHARELATEX_ALLOW_PUBLIC_ACCESS=true sharelatex/acceptance-test-runner' } } From 23bd8407961b0dd12262c273da9245e35e4e08bd Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 27 Sep 2017 10:53:00 +0200 Subject: [PATCH 08/99] Fix MockDocStoreApi name --- .../web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee index e7b0e4142c..5caed105b9 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee @@ -2,7 +2,7 @@ express = require("express") bodyParser = require "body-parser" app = express() -module.exports = MockDocUpdaterApi = +module.exports = MockDocStoreApi = docs: {} run: () -> From 96a129a8600a52be5b8ef8ef3df6ae17bf84446f Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 27 Sep 2017 10:54:06 +0100 Subject: [PATCH 09/99] show user.name in history if available --- .../ide/history/controllers/HistoryListController.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/history/controllers/HistoryListController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryListController.coffee index d3ca0c50f2..f6e7c724c3 100644 --- a/services/web/public/coffee/ide/history/controllers/HistoryListController.coffee +++ b/services/web/public/coffee/ide/history/controllers/HistoryListController.coffee @@ -115,7 +115,10 @@ define [ $scope.resetHoverState() $scope.displayName = (user) -> - full_name = "#{user.first_name} #{user.last_name}" + if user.name? + full_name = user.name + else + full_name = "#{user.first_name} #{user.last_name}" fallback_name = "Unknown" if !user? fallback_name From afff8ddf29c524e80e9f4c6ceddd5824b6a42f6b Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 26 Sep 2017 14:50:45 +0100 Subject: [PATCH 10/99] Pass (dummy) autocompile onboarding --- .../app/coffee/Features/Project/ProjectController.coffee | 7 +++++-- services/web/app/views/project/editor.pug | 1 + services/web/public/coffee/ide.coffee | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 84fa89ea37..ef5df22f28 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -248,6 +248,8 @@ module.exports = ProjectController = return cb(null, false) else return cb(null, true) + showAutoCompileOnboarding: (cb) -> + return cb(null, true) }, (err, results)-> if err? logger.err err:err, "error getting details for project page" @@ -255,9 +257,9 @@ module.exports = ProjectController = project = results.project user = results.user subscription = results.subscription - { showTrackChangesOnboarding, showPerUserTCNotice } = results + { showTrackChangesOnboarding, showPerUserTCNotice, showAutoCompileOnboarding } = results - daysSinceLastUpdated = (new Date() - project.lastUpdated) /86400000 + daysSinceLastUpdated = (new Date() - project.lastUpdated) / 86400000 logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor" AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, (error, privilegeLevel)-> @@ -300,6 +302,7 @@ module.exports = ProjectController = trackChangesState: project.track_changes showTrackChangesOnboarding: !!showTrackChangesOnboarding showPerUserTCNotice: !!showPerUserTCNotice + showAutoCompileOnboarding: !!showAutoCompileOnboarding privilegeLevel: privilegeLevel chatUrl: Settings.apis.chat.url anonymous: anonymous diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index fb92510917..1065941815 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -122,6 +122,7 @@ block requirejs window.trackChangesState = data.trackChangesState; window.showTrackChangesOnboarding = #{!!showTrackChangesOnboarding}; window.showPerUserTCNotice = #{!!showPerUserTCNotice}; + window.showAutoCompileOnboarding = #{!!showAutoCompileOnboarding} window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)}; window.requirejs = { "paths" : { diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index e317b355ef..af7e710561 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -73,7 +73,8 @@ define [ pdfLayout: 'sideBySide' pdfHidden: false, reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}") - miniReviewPanelVisible: false + miniReviewPanelVisible: false, + showAutoCompileOnboarding: window.user.betaProgram and window.showAutoCompileOnboarding } $scope.user = window.user From 8d2a451b44529b9bb38ba6e989f5e4970f88e509 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 27 Sep 2017 12:12:20 +0100 Subject: [PATCH 11/99] First pass at autocompile onboarding popover --- .../web/app/views/project/editor/editor.pug | 11 ++++++++++- .../autocompile/setting-dropdown.png | Bin 0 -> 22577 bytes .../app/editor/feature-onboarding.less | 17 ++++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 services/web/public/img/onboarding/autocompile/setting-dropdown.png diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 6007f2e0be..3c3efd63a5 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -94,4 +94,13 @@ div.full-size( ng-show="ui.view == 'pdf'" ) include ./pdf - + +.onboarding__autocompile.popover.right + .arrow + .popover-inner + h3.popover-title Auto Compile + .popover-content + p Try out the new auto compile setting! + img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") + p When enabled, your project will be compiled after you finish your sentence. + button.btn.btn-default.btn-block Got it diff --git a/services/web/public/img/onboarding/autocompile/setting-dropdown.png b/services/web/public/img/onboarding/autocompile/setting-dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..cc0da8f7a5820bf06f1ea94351152c26fdd3d11b GIT binary patch literal 22577 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 literal 0 HcmV?d00001 diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index 7289ed4fb7..f1098875aa 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -98,4 +98,19 @@ a.feat-onboard-dismiss { color: #FFF; opacity: 1; } -} \ No newline at end of file +} + +.onboarding__autocompile { + display: block; + top: 10px; + left: 694px; + + .arrow { + top: 17px !important; + left: -10px !important; + + &:after { + border-right-color: #f7f7f7 !important; + } + } +} From 316cf0722511f09a8f8a29b8f9b3c9e251ef59f4 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 27 Sep 2017 16:35:28 +0100 Subject: [PATCH 12/99] Add AutoCompileOnboardingController --- services/web/app/views/project/editor/editor.pug | 2 +- services/web/public/coffee/ide.coffee | 3 ++- .../coffee/ide/AutoCompileOnboardingController.coffee | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 services/web/public/coffee/ide/AutoCompileOnboardingController.coffee diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 3c3efd63a5..c68b889d6d 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,7 +95,7 @@ div.full-size( ) include ./pdf -.onboarding__autocompile.popover.right +.onboarding__autocompile.popover.right(ng-controller="AutoCompileOnboardingController") .arrow .popover-inner h3.popover-title Auto Compile diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index af7e710561..5fc208ce87 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -12,7 +12,8 @@ define [ "ide/labels/LabelsManager" "ide/review-panel/ReviewPanelManager" "ide/SafariScrollPatcher" - "ide/FeatureOnboardingController" + "ide/FeatureOnboardingController", + "ide/AutoCompileOnboardingController", "ide/settings/index" "ide/share/index" "ide/chat/index" diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee new file mode 100644 index 0000000000..67110d59c9 --- /dev/null +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -0,0 +1,7 @@ +define [ + "base" +], (App) -> + App.controller "AutoCompileOnboardingController", ($scope) -> + unsub = $scope.$on "pdf.recompile", () -> + console.log('recompiling') + unsub() \ No newline at end of file From 9386ddf4a9a5f14f9c3147813f54ad70a77aa1f7 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 27 Sep 2017 17:08:58 +0100 Subject: [PATCH 13/99] Only show autocompile onboarding when first manual compile is run --- services/web/app/views/project/editor/editor.pug | 6 +++++- services/web/public/coffee/ide.coffee | 3 +++ .../public/coffee/ide/pdf/controllers/PdfController.coffee | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index c68b889d6d..daac701f31 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,7 +95,11 @@ div.full-size( ) include ./pdf -.onboarding__autocompile.popover.right(ng-controller="AutoCompileOnboardingController") + +.popover.right.onboarding__autocompile( + ng-controller="AutoCompileOnboardingController" + ng-if="onboarding.autoCompile == 'show'" +) .arrow .popover-inner h3.popover-title Auto Compile diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index 5fc208ce87..6e4061081c 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -77,6 +77,9 @@ define [ miniReviewPanelVisible: false, showAutoCompileOnboarding: window.user.betaProgram and window.showAutoCompileOnboarding } + $scope.onboarding = { + autoCompile: 'unseen' + } $scope.user = window.user $scope.$watch "project.features.trackChangesVisible", (visible) -> diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 73ae9a4380..1e0403bb76 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -412,6 +412,9 @@ define [ $scope.recompile = (options = {}) -> return if $scope.pdf.compiling + if !options.isAutoCompile and $scope.onboarding.autoCompile == 'unseen' + $scope.onboarding.autoCompile = 'show' + event_tracking.sendMBSampled "editor-recompile-sampled", options $scope.pdf.compiling = true From 3259b871c0063cc6c489897ad537fef4ea36c1f8 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 27 Sep 2017 17:20:06 +0100 Subject: [PATCH 14/99] Dismiss autocompile onboarding --- services/web/app/views/project/editor/editor.pug | 3 ++- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index daac701f31..68230e018e 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -107,4 +107,5 @@ div.full-size( p Try out the new auto compile setting! img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") p When enabled, your project will be compiled after you finish your sentence. - button.btn.btn-default.btn-block Got it + button.btn.btn-default.btn-block(ng-click="dismiss()") + | Got it diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 67110d59c9..815825e750 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -2,6 +2,5 @@ define [ "base" ], (App) -> App.controller "AutoCompileOnboardingController", ($scope) -> - unsub = $scope.$on "pdf.recompile", () -> - console.log('recompiling') - unsub() \ No newline at end of file + $scope.dismiss = () -> + $scope.onboarding.autoCompile = 'dismissed' \ No newline at end of file From 7e407621e9ac094d0c7e9fa779597db792ae0df3 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 27 Sep 2017 17:45:28 +0100 Subject: [PATCH 15/99] Position onboarding popover after measuring position --- services/web/app/views/project/editor/pdf.pug | 2 +- .../coffee/ide/AutoCompileOnboardingController.coffee | 7 +++++++ .../public/stylesheets/app/editor/feature-onboarding.less | 1 - 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 065dd0cec0..536eefeb5b 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -1,6 +1,6 @@ div.full-size.pdf(ng-controller="PdfController") .toolbar.toolbar-tall - .btn-group( + .btn-group#recompile( dropdown, tooltip-html="'"+translate('recompile_pdf')+" ({{modifierKey}} + Enter)'" tooltip-class="keyboard-tooltip" diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 815825e750..08d7674dcd 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -2,5 +2,12 @@ define [ "base" ], (App) -> App.controller "AutoCompileOnboardingController", ($scope) -> + recompileBtn = angular.element('#recompile') + { top, left } = recompileBtn.offset() + angular.element('.onboarding__autocompile').offset({ + top: top, + left: left + 170 + }) + $scope.dismiss = () -> $scope.onboarding.autoCompile = 'dismissed' \ No newline at end of file diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index f1098875aa..cd4b6f3b3a 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -103,7 +103,6 @@ a.feat-onboard-dismiss { .onboarding__autocompile { display: block; top: 10px; - left: 694px; .arrow { top: 17px !important; From fcc2db9ea7c3dc6723632e3839fbfed46231f3f0 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 11:03:54 +0100 Subject: [PATCH 16/99] Use width of button instead of hardcoded --- services/web/app/views/project/editor/editor.pug | 1 - .../public/coffee/ide/AutoCompileOnboardingController.coffee | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 68230e018e..26602de1b1 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,7 +95,6 @@ div.full-size( ) include ./pdf - .popover.right.onboarding__autocompile( ng-controller="AutoCompileOnboardingController" ng-if="onboarding.autoCompile == 'show'" diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 08d7674dcd..184ac05e51 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -6,7 +6,7 @@ define [ { top, left } = recompileBtn.offset() angular.element('.onboarding__autocompile').offset({ top: top, - left: left + 170 + left: left + recompileBtn.width() + 11 # Width of arrow }) $scope.dismiss = () -> From 464c7c79d8bfa0903c1b17fb99894673e2eca0f7 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 11:31:55 +0100 Subject: [PATCH 17/99] Keep track of pdf panel width --- services/web/public/coffee/ide.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index 6e4061081c..b082ed0413 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -73,6 +73,7 @@ define [ chatOpen: false pdfLayout: 'sideBySide' pdfHidden: false, + pdfWidth: 0, reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}") miniReviewPanelVisible: false, showAutoCompileOnboarding: window.user.betaProgram and window.showAutoCompileOnboarding @@ -107,6 +108,7 @@ define [ $scope.$on "layout:pdf:resize", (_, layoutState) -> $scope.ui.pdfHidden = layoutState.east.initClosed + $scope.ui.pdfWidth = layoutState.east.size # Tracking code. $scope.$watch "ui.view", (newView, oldView) -> From 2d5a61f5b6d7facc5c1ce422e567376c5a850d7c Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 11:32:38 +0100 Subject: [PATCH 18/99] Determine placement of popover based on width of pdf panel --- .../web/app/views/project/editor/editor.pug | 21 ++++++++++--------- .../AutoCompileOnboardingController.coffee | 19 +++++++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 26602de1b1..ccda61229d 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,16 +95,17 @@ div.full-size( ) include ./pdf -.popover.right.onboarding__autocompile( +div( ng-controller="AutoCompileOnboardingController" ng-if="onboarding.autoCompile == 'show'" ) - .arrow - .popover-inner - h3.popover-title Auto Compile - .popover-content - p Try out the new auto compile setting! - img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") - p When enabled, your project will be compiled after you finish your sentence. - button.btn.btn-default.btn-block(ng-click="dismiss()") - | Got it + .onboarding__autocompile.popover(ng-class="placement") + .arrow + .popover-inner + h3.popover-title Auto Compile + .popover-content + p Try out the new auto compile setting! + img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") + p When enabled, your project will be compiled after you finish your sentence. + button.btn.btn-default.btn-block(ng-click="dismiss()") + | Got it diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 184ac05e51..3131661315 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -3,11 +3,22 @@ define [ ], (App) -> App.controller "AutoCompileOnboardingController", ($scope) -> recompileBtn = angular.element('#recompile') + popover = angular.element('.onboarding__autocompile') { top, left } = recompileBtn.offset() - angular.element('.onboarding__autocompile').offset({ - top: top, - left: left + recompileBtn.width() + 11 # Width of arrow - }) + + if $scope.ui.pdfWidth < 475 + $scope.placement = 'left' + popover.offset({ + top: top, + left: left - popover.width() - 11 # Width of arrow + }) + else + $scope.placement = 'right' + angular.element('.onboarding__autocompile').offset({ + top: top, + left: left + recompileBtn.width() + 11 # Width of arrow + }) + $scope.dismiss = () -> $scope.onboarding.autoCompile = 'dismissed' \ No newline at end of file From e78ee69c04cb37535fc21bf25bf175b7fa29c3f4 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 11:55:20 +0100 Subject: [PATCH 19/99] Fix positioning & styling of arrows --- .../coffee/ide/AutoCompileOnboardingController.coffee | 5 ++--- .../stylesheets/app/editor/feature-onboarding.less | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 3131661315..50852d8093 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -10,15 +10,14 @@ define [ $scope.placement = 'left' popover.offset({ top: top, - left: left - popover.width() - 11 # Width of arrow + left: left - popover.width() }) else $scope.placement = 'right' angular.element('.onboarding__autocompile').offset({ top: top, - left: left + recompileBtn.width() + 11 # Width of arrow + left: left + recompileBtn.width() }) - $scope.dismiss = () -> $scope.onboarding.autoCompile = 'dismissed' \ No newline at end of file diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index cd4b6f3b3a..134001b212 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -106,10 +106,21 @@ a.feat-onboard-dismiss { .arrow { top: 17px !important; + } + + &.right > .arrow { left: -10px !important; &:after { border-right-color: #f7f7f7 !important; } } + + &.left > .arrow { + right: -10px !important; + + &:after { + border-left-color: #f7f7f7 !important; + } + } } From d9af9e723b83b1c7709842167749095026a9ac55 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 12:12:48 +0100 Subject: [PATCH 20/99] Clean up popover wrapper --- .../web/app/views/project/editor/editor.pug | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index ccda61229d..f9621987b8 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,17 +95,17 @@ div.full-size( ) include ./pdf -div( +.onboarding__autocompile.popover( ng-controller="AutoCompileOnboardingController" ng-if="onboarding.autoCompile == 'show'" + ng-class="placement" ) - .onboarding__autocompile.popover(ng-class="placement") - .arrow - .popover-inner - h3.popover-title Auto Compile - .popover-content - p Try out the new auto compile setting! - img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") - p When enabled, your project will be compiled after you finish your sentence. - button.btn.btn-default.btn-block(ng-click="dismiss()") - | Got it + .arrow + .popover-inner + h3.popover-title Auto Compile + .popover-content + p Try out the new auto compile setting! + img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") + p When enabled, your project will be compiled after you finish your sentence. + button.btn.btn-default.btn-block(ng-click="dismiss()") + | Got it From 199e85e4a98ff181588b0c17e9def1678bedb879 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 12:16:02 +0100 Subject: [PATCH 21/99] Comment --- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 50852d8093..37b52c754f 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -6,6 +6,8 @@ define [ popover = angular.element('.onboarding__autocompile') { top, left } = recompileBtn.offset() + # If pdf panel smaller than recompile button + popover, show to left. + # Otherwise show to right if $scope.ui.pdfWidth < 475 $scope.placement = 'left' popover.offset({ From 39c8a6a1939d2b2da75a1fb61c35df382331a552 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 12:27:29 +0100 Subject: [PATCH 22/99] Send analytics data when onboarding dismissed --- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 37b52c754f..5dd11d2230 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -22,4 +22,5 @@ define [ }) $scope.dismiss = () -> - $scope.onboarding.autoCompile = 'dismissed' \ No newline at end of file + $scope.onboarding.autoCompile = 'dismissed' + event_tracking.sendMB "shown-autocompile-onboarding" From e95778c703f656ee8d0183004809be229d7017e7 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 13:02:16 +0100 Subject: [PATCH 23/99] Fix event tracking not being injecting --- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 5dd11d2230..aecfcb395a 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -1,7 +1,7 @@ define [ "base" ], (App) -> - App.controller "AutoCompileOnboardingController", ($scope) -> + App.controller "AutoCompileOnboardingController", ($scope, event_tracking) -> recompileBtn = angular.element('#recompile') popover = angular.element('.onboarding__autocompile') { top, left } = recompileBtn.offset() From f2c0bf55156c02a0444b277e661a6352306bc658 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 13:04:18 +0100 Subject: [PATCH 24/99] First pass at getting onboarding shown event from analytics --- .../coffee/Features/Project/ProjectController.coffee | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index ef5df22f28..479a57a00c 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -249,7 +249,16 @@ module.exports = ProjectController = else return cb(null, true) showAutoCompileOnboarding: (cb) -> - return cb(null, true) + cb = underscore.once(cb) + if (!user_id?) + return cb() + AnalyticsManager.getLastOccurance user_id, "shown-autocompile-onboarding", (error, event) -> + if error? + return cb(null, false) + else if event? + return cb(null, false) + else + return cb(null, true) }, (err, results)-> if err? logger.err err:err, "error getting details for project page" From 3e2388a7dee5b975fc528b7f03448d98c5687fe7 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 13:57:15 +0100 Subject: [PATCH 25/99] Don't show autocompile for users signed up after release date --- .../app/coffee/Features/Project/ProjectController.coffee | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 479a57a00c..7c0328fe17 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -250,9 +250,16 @@ module.exports = ProjectController = return cb(null, true) showAutoCompileOnboarding: (cb) -> cb = underscore.once(cb) - if (!user_id?) + if !user_id? return cb() + timestamp = user_id.toString().substring(0,8) + userSignupDate = new Date( parseInt( timestamp, 16 ) * 1000 ) + if userSignupDate > new Date("2017-10-05") + # Don't show for users who registered after it was released + return cb(null, false) + timeout = setTimeout cb, 500 AnalyticsManager.getLastOccurance user_id, "shown-autocompile-onboarding", (error, event) -> + clearTimeout timeout if error? return cb(null, false) else if event? From e41a48de7253ee277b73f43a6918dba6575bfa3e Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 28 Sep 2017 14:01:03 +0100 Subject: [PATCH 26/99] Conditionally disable text-shadow on chrome v61 and v62. --- services/web/public/coffee/ide.coffee | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index e317b355ef..357b45224e 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -185,6 +185,21 @@ define [ if ide.browserIsSafari ide.safariScrollPatcher = new SafariScrollPatcher($scope) + # Fix Chrome 61 and 62 text-shadow rendering + browserIsChrome61or62 = false + try + chromeVersion = parseFloat(navigator.userAgent.split(" Chrome/")[1]) || null; + browserIsChrome61or62 = ( + chromeVersion? && + (chromeVersion == 61 || chromeVersion == 62) + ) + console.log chromeVersion, browserIsChrome61or62 + if browserIsChrome61or62 + document.styleSheets[0].insertRule(".ace_editor.ace_autocomplete .ace_completion-highlight { text-shadow: none !important; }", 1) + catch err + console.error err + + # User can append ?ft=somefeature to url to activate a feature toggle ide.featureToggle = location?.search?.match(/^\?ft=(\w+)$/)?[1] From 65d38aa7f7b2df09529613abc74b49d7add4cd00 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 28 Sep 2017 14:09:37 +0100 Subject: [PATCH 27/99] Remove debug line. --- services/web/public/coffee/ide.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index 357b45224e..06201bd0b1 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -193,7 +193,6 @@ define [ chromeVersion? && (chromeVersion == 61 || chromeVersion == 62) ) - console.log chromeVersion, browserIsChrome61or62 if browserIsChrome61or62 document.styleSheets[0].insertRule(".ace_editor.ace_autocomplete .ace_completion-highlight { text-shadow: none !important; }", 1) catch err From 8cd1f8c7ac595421e02d935c91c29382bc4da57e Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 28 Sep 2017 14:13:51 +0100 Subject: [PATCH 28/99] Simplify logic for showing autocompile onboarding --- services/web/public/coffee/ide.coffee | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index b082ed0413..b3d83e7ee5 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -74,12 +74,11 @@ define [ pdfLayout: 'sideBySide' pdfHidden: false, pdfWidth: 0, - reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}") + reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}"), miniReviewPanelVisible: false, - showAutoCompileOnboarding: window.user.betaProgram and window.showAutoCompileOnboarding } $scope.onboarding = { - autoCompile: 'unseen' + autoCompile: if window.user.betaProgram and window.showAutoCompileOnboarding then 'unseen' else 'dismissed' } $scope.user = window.user From c50f309b0998f8a17bdd1f92a9105cd65e38dd85 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 28 Sep 2017 15:12:37 +0100 Subject: [PATCH 29/99] add missing whitespace in pdf.pug --- services/web/app/views/project/editor/pdf.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 065dd0cec0..377f09f71a 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -345,7 +345,7 @@ div.full-size.pdf(ng-controller="PdfController") span #{translate("project_flagged_too_many_compiles")} .alert.alert-danger(ng-show="pdf.compileInProgress") - strong #{translate("pdf_compile_in_progress_error")} + strong #{translate("pdf_compile_in_progress_error")}. span #{translate("pdf_compile_try_again")} .alert.alert-danger(ng-show="pdf.timedout") From 3c9c94f3c20c7376110eab43f8a3f171db150df5 Mon Sep 17 00:00:00 2001 From: Joe Green Date: Fri, 29 Sep 2017 10:37:39 +0100 Subject: [PATCH 30/99] release number (#32) Replace release number in pug template for sentry --- services/web/Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 93f0a31008..6421174e68 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -74,6 +74,8 @@ pipeline { } steps { sh 'node_modules/.bin/grunt compile --verbose' + // replace the build number placeholder for sentry + sh 'node_modules/.bin/grunt version' } } From dd7e6f0612a8de51fc795918490ccf63b926d45b Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 29 Sep 2017 10:49:45 +0100 Subject: [PATCH 31/99] Make class names more consistent & switch to JS targeting through id --- services/web/app/views/project/editor/editor.pug | 2 +- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 2 +- .../web/public/stylesheets/app/editor/feature-onboarding.less | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index f9621987b8..40734e8632 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -95,7 +95,7 @@ div.full-size( ) include ./pdf -.onboarding__autocompile.popover( +#onboarding-autocompile.onboarding-autocompile.popover( ng-controller="AutoCompileOnboardingController" ng-if="onboarding.autoCompile == 'show'" ng-class="placement" diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index aecfcb395a..80ba7de814 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -3,7 +3,7 @@ define [ ], (App) -> App.controller "AutoCompileOnboardingController", ($scope, event_tracking) -> recompileBtn = angular.element('#recompile') - popover = angular.element('.onboarding__autocompile') + popover = angular.element('#onboarding-autocompile') { top, left } = recompileBtn.offset() # If pdf panel smaller than recompile button + popover, show to left. diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index 134001b212..80c21e26c3 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -100,7 +100,7 @@ a.feat-onboard-dismiss { } } -.onboarding__autocompile { +.onboarding-autocompile { display: block; top: 10px; From ba6a0b44a996e74afbde7f5b989c95c75dcd3db2 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 29 Sep 2017 10:53:06 +0100 Subject: [PATCH 32/99] Fix incorrect selector --- .../public/coffee/ide/AutoCompileOnboardingController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee index 80ba7de814..a57575fb94 100644 --- a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -16,7 +16,7 @@ define [ }) else $scope.placement = 'right' - angular.element('.onboarding__autocompile').offset({ + popover.offset({ top: top, left: left + recompileBtn.width() }) From ab7d83b1c5616d6c7196e5b5e772efb1d69957da Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 29 Sep 2017 10:59:01 +0100 Subject: [PATCH 33/99] Switch to translations --- services/web/app/views/project/editor/editor.pug | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 40734e8632..37a103c6ce 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -102,10 +102,10 @@ div.full-size( ) .arrow .popover-inner - h3.popover-title Auto Compile + h3.popover-title #{translate("auto_compile")} .popover-content - p Try out the new auto compile setting! + p #{translate("try_out_auto_compile_setting")} img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") - p When enabled, your project will be compiled after you finish your sentence. + p #{tranlate("auto_compile_onboarding_description")} button.btn.btn-default.btn-block(ng-click="dismiss()") - | Got it + | #{translate("got_it")} From a4fa713f38dd9347e6ddfc60df46fa87c68fec7f Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 29 Sep 2017 11:18:44 +0100 Subject: [PATCH 34/99] Fix typo --- services/web/app/views/project/editor/editor.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 37a103c6ce..66bff761a1 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -106,6 +106,6 @@ div.full-size( .popover-content p #{translate("try_out_auto_compile_setting")} img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") - p #{tranlate("auto_compile_onboarding_description")} + p #{translate("auto_compile_onboarding_description")} button.btn.btn-default.btn-block(ng-click="dismiss()") | #{translate("got_it")} From 738acefac745339bf2d907f77dd3a53177366c26 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 29 Sep 2017 11:38:56 +0100 Subject: [PATCH 35/99] Style onboarding image with more space & light border --- .../public/stylesheets/app/editor/feature-onboarding.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index 80c21e26c3..ef89a93df4 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -108,6 +108,11 @@ a.feat-onboard-dismiss { top: 17px !important; } + img { + margin-bottom: 10px; + border: 1px solid @gray-lighter; + } + &.right > .arrow { left: -10px !important; From bf1c24f6f9c308a93c3c03721864bace2fced0b5 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 28 Sep 2017 15:01:45 +0100 Subject: [PATCH 36/99] return pathname from DocumentController.getDoc --- .../Documents/DocumentController.coffee | 6 +- .../Project/ProjectEntityHandler.coffee | 25 +++-- .../Documents/DocumentControllerTests.coffee | 8 +- .../Project/ProjectEntityHandlerTests.coffee | 105 +++++++++++------- 4 files changed, 88 insertions(+), 56 deletions(-) diff --git a/services/web/app/coffee/Features/Documents/DocumentController.coffee b/services/web/app/coffee/Features/Documents/DocumentController.coffee index 2042f6a218..5a68a4777c 100644 --- a/services/web/app/coffee/Features/Documents/DocumentController.coffee +++ b/services/web/app/coffee/Features/Documents/DocumentController.coffee @@ -7,7 +7,7 @@ module.exports = doc_id = req.params.doc_id plain = req?.query?.plain == 'true' logger.log doc_id:doc_id, project_id:project_id, "receiving get document request from api (docupdater)" - ProjectEntityHandler.getDoc project_id, doc_id, (error, lines, rev, version, ranges) -> + ProjectEntityHandler.getDoc project_id, doc_id, {pathname: true}, (error, lines, rev, version, ranges, pathname) -> if error? logger.err err:error, doc_id:doc_id, project_id:project_id, "error finding element for getDocument" return next(error) @@ -20,6 +20,7 @@ module.exports = lines: lines version: version ranges: ranges + pathname: pathname } setDocument: (req, res, next = (error) ->) -> @@ -33,6 +34,3 @@ module.exports = return next(error) logger.log doc_id:doc_id, project_id:project_id, "finished receiving set document request from api (docupdater)" res.sendStatus 200 - - - diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 870e8a05b2..6489b2bbea 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -131,7 +131,7 @@ module.exports = ProjectEntityHandler = setRootDoc: (project_id, newRootDocID, callback = (error) ->)-> logger.log project_id: project_id, rootDocId: newRootDocID, "setting root doc" Project.update {_id:project_id}, {rootDoc_id:newRootDocID}, {}, callback - + unsetRootDoc: (project_id, callback = (error) ->) -> logger.log project_id: project_id, "removing root doc" Project.update {_id:project_id}, {$unset: {rootDoc_id: true}}, {}, callback @@ -140,8 +140,15 @@ module.exports = ProjectEntityHandler = if typeof(options) == "function" callback = options options = {} - DocstoreManager.getDoc project_id, doc_id, options, callback + if options["pathname"] + delete options["pathname"] + projectLocator.findElement {project_id: project_id, element_id: doc_id, type: 'doc'}, (error, doc, path) => + return callback(error) if error? + DocstoreManager.getDoc project_id, doc_id, options, (error, lines, rev, version, ranges) => + callback(error, lines, rev, version, ranges, path.fileSystem) + else + DocstoreManager.getDoc project_id, doc_id, options, callback addDoc: (project_id, folder_id, docName, docLines, callback = (error, doc, folder_id) ->)=> ProjectGetter.getProjectWithOnlyFolders project_id, (err, project) -> @@ -158,7 +165,7 @@ module.exports = ProjectEntityHandler = # Put doc in docstore first, so that if it errors, we don't have a doc_id in the project # which hasn't been created in docstore. DocstoreManager.updateDoc project_id.toString(), doc._id.toString(), docLines, 0, {}, (err, modified, rev) -> - return callback(err) if err? + return callback(err) if err? ProjectEntityHandler._putElement project, folder_id, doc, "doc", (err, result)=> return callback(err) if err? @@ -207,7 +214,7 @@ module.exports = ProjectEntityHandler = replaceFile: (project_id, file_id, fsPath, callback)-> ProjectGetter.getProject project_id, {name:true}, (err, project) -> return callback(err) if err? - findOpts = + findOpts = project_id:project._id element_id:file_id type:"file" @@ -280,7 +287,7 @@ module.exports = ProjectEntityHandler = procesFolder = (previousFolders, folderName, callback)=> previousFolders = previousFolders || [] parentFolder = previousFolders[previousFolders.length-1] - if parentFolder? + if parentFolder? parentFolder_id = parentFolder._id builtUpPath = "#{builtUpPath}/#{folderName}" projectLocator.findElementByPath project, builtUpPath, (err, foundFolder)=> @@ -360,7 +367,7 @@ module.exports = ProjectEntityHandler = return callback(err) if err? projectLocator.findElement {project:project, element_id:entity_id, type:entityType}, (err, entity, path)-> return callback(err) if err? - + if entityType.match(/folder/) ensureFolderIsNotMovedIntoChild = (callback = (error) ->) -> projectLocator.findElement {project: project, element_id: folder_id, type:"folder"}, (err, destEntity, destPath) -> @@ -372,7 +379,7 @@ module.exports = ProjectEntityHandler = callback() else ensureFolderIsNotMovedIntoChild = (callback = () ->) -> callback() - + ensureFolderIsNotMovedIntoChild (error) -> return callback(error) if error? self._removeElementFromMongoArray Project, project_id, path.mongo, (err)-> @@ -382,7 +389,7 @@ module.exports = ProjectEntityHandler = return callback(err) if err? ProjectEntityHandler._putElement project, destinationFolder_id, entity, entityType, (err, result)-> return callback(err) if err? - opts = + opts = project_id:project_id project_name:project.name startPath:path.fileSystem @@ -506,7 +513,7 @@ module.exports = ProjectEntityHandler = _countElements : (project, callback)-> - + countFolder = (folder, cb = (err, count)->)-> jobs = _.map folder?.folders, (folder)-> diff --git a/services/web/test/UnitTests/coffee/Documents/DocumentControllerTests.coffee b/services/web/test/UnitTests/coffee/Documents/DocumentControllerTests.coffee index fedfa1c1b3..1d4cef928f 100644 --- a/services/web/test/UnitTests/coffee/Documents/DocumentControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Documents/DocumentControllerTests.coffee @@ -24,6 +24,7 @@ describe "DocumentController", -> @doc_lines = ["one", "two", "three"] @version = 42 @ranges = {"mock": "ranges"} + @pathname = '/a/b/c/file.tex' @rev = 5 describe "getDocument", -> @@ -34,12 +35,12 @@ describe "DocumentController", -> describe "when the document exists", -> beforeEach -> - @ProjectEntityHandler.getDoc = sinon.stub().callsArgWith(2, null, @doc_lines, @rev, @version, @ranges) + @ProjectEntityHandler.getDoc = sinon.stub().callsArgWith(3, null, @doc_lines, @rev, @version, @ranges, @pathname) @DocumentController.getDocument(@req, @res, @next) it "should get the document from Mongo", -> @ProjectEntityHandler.getDoc - .calledWith(@project_id, @doc_id) + .calledWith(@project_id, @doc_id, pathname: true) .should.equal true it "should return the document data to the client as JSON", -> @@ -48,10 +49,11 @@ describe "DocumentController", -> lines: @doc_lines version: @version ranges: @ranges + pathname: @pathname describe "when the document doesn't exist", -> beforeEach -> - @ProjectEntityHandler.getDoc = sinon.stub().callsArgWith(2, new Errors.NotFoundError("not found"), null) + @ProjectEntityHandler.getDoc = sinon.stub().callsArgWith(3, new Errors.NotFoundError("not found"), null) @DocumentController.getDocument(@req, @res, @next) it "should call next with the NotFoundError", -> diff --git a/services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee index 0ac40cd2c5..0bf3460cbb 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectEntityHandlerTests.coffee @@ -14,17 +14,17 @@ describe 'ProjectEntityHandler', -> doc_id = '4eecb1c1bffa66588e0000a2' folder_id = "4eecaffcbffa66588e000008" rootFolderId = "4eecaffcbffa66588e000007" - + beforeEach -> - @FileStoreHandler = + @FileStoreHandler = uploadFileFromDisk:(project_id, fileRef, localImagePath, callback)->callback() copyFile: sinon.stub().callsArgWith(4, null) @tpdsUpdateSender = addDoc:sinon.stub().callsArg(1) addFile:sinon.stub().callsArg(1) addFolder:sinon.stub().callsArg(1) - @rootFolder = - _id:rootFolderId, + @rootFolder = + _id:rootFolderId, folders:[ {name:"level1", folders:[]} ] @@ -46,7 +46,7 @@ describe 'ProjectEntityHandler', -> @FileModel = class File constructor:(options)-> {@name} = options - @._id = "file_id" + @._id = "file_id" @rev = 0 @FolderModel = class Folder constructor:(options)-> @@ -57,12 +57,12 @@ describe 'ProjectEntityHandler', -> @ProjectModel.findById = (project_id, callback)=> callback(null, @project) @ProjectModel.getProject = (project_id, fields, callback)=> callback(null, @project) - @ProjectGetter = + @ProjectGetter = getProjectWithOnlyFolders : (project_id, callback)=> callback(null, @project) getProjectWithoutDocLines : (project_id, callback)=> callback(null, @project) getProject:sinon.stub() @projectUpdater = markAsUpdated:sinon.stub() - @projectLocator = + @projectLocator = findElement : sinon.stub() @settings = maxEntitiesPerProject:200 @@ -97,8 +97,8 @@ describe 'ProjectEntityHandler', -> else cb null, @parentFolder @ProjectEntityHandler.addFolder = (project_id, parentFolder_id, folderName, callback)=> - callback null, {name:folderName}, @parentFolder_id - + callback null, {name:folderName}, @parentFolder_id + it 'should return the root folder if the path is just a slash', (done)-> path = "/" @ProjectEntityHandler.mkdirp project_id, path, (err, folders, lastFolder)=> @@ -239,7 +239,7 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, path: @pathAfterMove) @ProjectGetter.getProject.callsArgWith(2, null, @project) @tpdsUpdateSender.moveEntity = sinon.stub().callsArg(1) - + describe "moving a doc", -> beforeEach (done) -> @docId = "4eecaffcbffa66588e000009" @@ -257,10 +257,10 @@ describe 'ProjectEntityHandler', -> it 'should remove the element from its current position', -> @ProjectEntityHandler._removeElementFromMongoArray .calledWith(@ProjectModel, project_id, @path.mongo ).should.equal true - + it "should put the element back in the new folder", -> @ProjectEntityHandler._putElement.calledWith(@project, folder_id, @doc, "docs").should.equal true - + it 'should tell the third party data store', -> @tpdsUpdateSender.moveEntity .calledWith({ @@ -271,7 +271,7 @@ describe 'ProjectEntityHandler', -> rev: @doc.rev }) .should.equal true - + describe "moving a folder", -> beforeEach -> @folder_id = "folder-to-move" @@ -294,7 +294,7 @@ describe 'ProjectEntityHandler', -> else console.log "UNKNOWN ID", options sinon.spy @projectLocator, "findElement" - + describe "when the destination folder is outside the moving folder", -> beforeEach (done) -> @path.fileSystem = "/one/directory" @@ -318,7 +318,7 @@ describe 'ProjectEntityHandler', -> @path.mongo ) .should.equal true - + it "should put the element back in the new folder", -> @ProjectEntityHandler._putElement .calledWith( @@ -328,7 +328,7 @@ describe 'ProjectEntityHandler', -> "folder" ) .should.equal true - + it 'should tell the third party data store', -> @tpdsUpdateSender.moveEntity .calledWith({ @@ -339,7 +339,7 @@ describe 'ProjectEntityHandler', -> rev: @folder.rev }) .should.equal true - + describe "when the destination folder is inside the moving folder", -> beforeEach -> @path.fileSystem = "/one/two" @@ -355,7 +355,7 @@ describe 'ProjectEntityHandler', -> project: @project }) .should.equal true - + it "should return an error", -> @callback .calledWith(new Error("destination folder is a child folder of me")) @@ -385,16 +385,41 @@ describe 'ProjectEntityHandler', -> @rev = 5 @version = 42 @ranges = {"mock": "ranges"} + @DocstoreManager.getDoc = sinon.stub().callsArgWith(3, null, @lines, @rev, @version, @ranges) - @ProjectEntityHandler.getDoc project_id, doc_id, @callback - it "should call the docstore", -> - @DocstoreManager.getDoc - .calledWith(project_id, doc_id) - .should.equal true + describe 'without pathname option', -> + beforeEach -> + @ProjectEntityHandler.getDoc project_id, doc_id, @callback + + it "should call the docstore", -> + @DocstoreManager.getDoc + .calledWith(project_id, doc_id) + .should.equal true + + it "should call the callback with the lines, version and rev", -> + @callback.calledWith(null, @lines, @rev, @version, @ranges).should.equal true + + describe 'with pathname option', -> + beforeEach -> + @project = 'a project' + @path = mongo: "mongo.path", fileSystem: "/file/system/path" + @projectLocator.findElement = sinon.stub().callsArgWith(1, null, {}, @path) + @ProjectEntityHandler.getDoc project_id, doc_id, {pathname: true}, @callback + + it "should call the project locator", -> + @projectLocator.findElement + .calledWith({project_id: project_id, element_id: doc_id, type: 'doc'}) + .should.equal true + + it "should call the docstore", -> + @DocstoreManager.getDoc + .calledWith(project_id, doc_id) + .should.equal true + + it "should return the pathname if option given", -> + @callback.calledWith(null, @lines, @rev, @version, @ranges, @path.fileSystem).should.equal true - it "should call the callback with the lines, version and rev", -> - @callback.calledWith(null, @lines, @rev, @version, @ranges).should.equal true describe 'addDoc', -> beforeEach -> @@ -876,7 +901,7 @@ describe 'ProjectEntityHandler', -> path: path }) .should.equal true - + describe "setRootDoc", -> it "should call Project.update", -> @project_id = "project-id-123234adfs" @@ -907,22 +932,22 @@ describe 'ProjectEntityHandler', -> it 'should copy the file in FileStoreHandler', (done)-> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)=> + @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)=> @FileStoreHandler.copyFile.calledWith(oldProject_id, oldFileRef._id, project_id, fileRef._id).should.equal true done() it 'should put file into folder by calling put element', (done)-> - @ProjectEntityHandler._putElement = (passedProject, passedFolder_id, passedFileRef, passedType, callback)-> + @ProjectEntityHandler._putElement = (passedProject, passedFolder_id, passedFileRef, passedType, callback)-> passedProject._id.should.equal project_id passedFolder_id.should.equal folder_id passedFileRef.name.should.equal fileName passedType.should.equal 'file' done() - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> it 'should return doc and parent folder', (done)-> - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> parentFolder.should.equal folder_id fileRef.name.should.equal fileName done() @@ -942,7 +967,7 @@ describe 'ProjectEntityHandler', -> options.rev.should.equal 0 done() - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> describe "renameEntity", -> @@ -1054,7 +1079,7 @@ describe 'ProjectEntityHandler', -> @folder = _id: ObjectId() name: "someFolder" - @doc = + @doc = _id: ObjectId() name: "new.tex" @path = mongo: "mongo.path", fileSystem: "/file/system/old.tex" @@ -1064,7 +1089,7 @@ describe 'ProjectEntityHandler', -> describe "updating the project", -> - + it "should use the correct mongo path", (done)-> @ProjectEntityHandler._putElement @project, @folder._id, @doc, "docs", (err)=> @@ -1089,12 +1114,12 @@ describe 'ProjectEntityHandler', -> done() it "should error if the element has no _id", (done)-> - doc = + doc = name:"something" @ProjectEntityHandler._putElement @project, @folder._id, doc, "doc", (err)=> @ProjectModel.update.called.should.equal false done() - + describe "_countElements", -> @@ -1109,7 +1134,7 @@ describe 'ProjectEntityHandler', -> fileRefs:{} folders: [ { - docs:[_id:1234], + docs:[_id:1234], fileRefs:[{_id:23123}, {_id:123213}, {_id:2312}] folders:[ { @@ -1131,7 +1156,7 @@ describe 'ProjectEntityHandler', -> } ] } - ] + ] it "should return the correct number", (done)-> @ProjectEntityHandler._countElements @project, (err, count)-> @@ -1142,19 +1167,19 @@ describe 'ProjectEntityHandler', -> @project.rootFolder[0].folders[0].folders = undefined @ProjectEntityHandler._countElements @project, (err, count)-> count.should.equal 17 - done() + done() it "should deal with null docs", (done)-> @project.rootFolder[0].folders[0].docs = undefined @ProjectEntityHandler._countElements @project, (err, count)-> count.should.equal 23 - done() + done() it "should deal with null fileRefs", (done)-> @project.rootFolder[0].folders[0].folders[0].fileRefs = undefined @ProjectEntityHandler._countElements @project, (err, count)-> count.should.equal 23 - done() + done() From e9114551ba679fb722d50ad643811fc55d5ff297 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 2 Oct 2017 10:11:26 +0100 Subject: [PATCH 37/99] add unit test for precompile resources check --- .../coffee/Compile/ClsiManagerTests.coffee | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee index 32deed5522..f02c228ad6 100644 --- a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee @@ -33,7 +33,7 @@ describe "ClsiManager", -> getProjectDocsIfMatch: sinon.stub().callsArgWith(2,null,null) "./ClsiCookieManager": @ClsiCookieManager "./ClsiStateManager": @ClsiStateManager - "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub(), warn: sinon.stub() } + "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub(), err: sinon.stub(), warn: sinon.stub() } "request": @request = sinon.stub() "./ClsiFormatChecker": @ClsiFormatChecker "metrics-sharelatex": @Metrics = @@ -122,6 +122,21 @@ describe "ClsiManager", -> it "should call the callback with a success status", -> @callback.calledWith(null, @status, ).should.equal true + describe "when the resources fail the precompile check", -> + beforeEach -> + @ClsiFormatChecker.checkRecoursesForProblems = sinon.stub().callsArgWith(1, new Error("failed")) + @ClsiManager._postToClsi = sinon.stub().callsArgWith(4, null, { + compile: + status: @status = "failure" + }) + @ClsiManager.sendRequest @project_id, @user_id, {}, @callback + + it "should call the callback only once", -> + @callback.calledOnce.should.equal true + + it "should call the callback with an error", -> + @callback.calledWithExactly(new Error("failed")).should.equal true + describe "deleteAuxFiles", -> beforeEach -> @ClsiManager._makeRequest = sinon.stub().callsArg(2) From bd005d7bb6993c9f0fd9f16f0d2c5d523abfadc0 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 2 Oct 2017 10:14:52 +0100 Subject: [PATCH 38/99] fix double callback in precompile resources check --- .../Features/Compile/ClsiManager.coffee | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 46cb4e35e3..ca3cd2b6ab 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -38,17 +38,17 @@ module.exports = ClsiManager = if validationProblems? logger.log project_id:project_id, validationProblems:validationProblems, "problems with users latex before compile was attempted" return callback(null, "validation-problems", null, null, validationProblems) - ClsiManager._postToClsi project_id, user_id, req, options.compileGroup, (error, response) -> - if error? - logger.err err:error, project_id:project_id, "error sending request to clsi" - return callback(error) - logger.log project_id: project_id, outputFilesLength: response?.outputFiles?.length, status: response?.status, compile_status: response?.compile?.status, "received compile response from CLSI" - ClsiCookieManager._getServerId project_id, (err, clsiServerId)-> - if err? - logger.err err:err, project_id:project_id, "error getting server id" - return callback(err) - outputFiles = ClsiManager._parseOutputFiles(project_id, response?.compile?.outputFiles) - callback(null, response?.compile?.status, outputFiles, clsiServerId) + ClsiManager._postToClsi project_id, user_id, req, options.compileGroup, (error, response) -> + if error? + logger.err err:error, project_id:project_id, "error sending request to clsi" + return callback(error) + logger.log project_id: project_id, outputFilesLength: response?.outputFiles?.length, status: response?.status, compile_status: response?.compile?.status, "received compile response from CLSI" + ClsiCookieManager._getServerId project_id, (err, clsiServerId)-> + if err? + logger.err err:err, project_id:project_id, "error getting server id" + return callback(err) + outputFiles = ClsiManager._parseOutputFiles(project_id, response?.compile?.outputFiles) + callback(null, response?.compile?.status, outputFiles, clsiServerId) stopCompile: (project_id, user_id, options, callback = (error) ->) -> compilerUrl = @_getCompilerUrl(options?.compileGroup, project_id, user_id, "compile/stop") From a69afae03dd54ce331ec23f9bbf7592cc05992d1 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 2 Oct 2017 13:49:28 +0100 Subject: [PATCH 39/99] Remove unnecessary arrow elem --- .../web/app/views/project/editor/editor.pug | 1 - .../app/editor/feature-onboarding.less | 44 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 66bff761a1..86cc63a5e5 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -100,7 +100,6 @@ div.full-size( ng-if="onboarding.autoCompile == 'show'" ng-class="placement" ) - .arrow .popover-inner h3.popover-title #{translate("auto_compile")} .popover-content diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index ef89a93df4..475658f885 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -104,28 +104,42 @@ a.feat-onboard-dismiss { display: block; top: 10px; - .arrow { - top: 17px !important; - } - img { margin-bottom: 10px; border: 1px solid @gray-lighter; } - &.right > .arrow { - left: -10px !important; - - &:after { - border-right-color: #f7f7f7 !important; - } + &::before, &::after { + content: ''; + border-width: 11px; + border-style: solid; + border-color: transparent; + top: 7px; + display: block; + position: absolute; } - &.left > .arrow { - right: -10px !important; + &.right::before { + border-left-width: 0; + border-right-color: rgba(0, 0, 0, .3); + left: -11px; + } - &:after { - border-left-color: #f7f7f7 !important; - } + &.right::after { + border-left-width: 0; + border-right-color: #f7f7f7; + left: -9.5px; + } + + &.left::before { + border-right-width: 0; + border-left-color: rgba(0, 0, 0, .3); + right: -11px + } + + &.left::after { + border-right-width: 0; + border-left-color: #f7f7f7; + right: -9.5px; } } From a3800a321be6d6a5a93d972d208f706e81b4ee55 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 2 Oct 2017 14:12:18 +0100 Subject: [PATCH 40/99] Add beta program badge on autocompile popover & setting --- services/web/app/views/project/editor/editor.pug | 4 +++- services/web/app/views/project/editor/pdf.pug | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 86cc63a5e5..89ec5c7828 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -101,7 +101,9 @@ div.full-size( ng-class="placement" ) .popover-inner - h3.popover-title #{translate("auto_compile")} + h3.popover-title + | #{translate("auto_compile")} + span.beta-feature-badge .popover-content p #{translate("try_out_auto_compile_setting")} img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 536eefeb5b..99369eb4c5 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -28,7 +28,9 @@ div.full-size.pdf(ng-controller="PdfController") ul.dropdown-menu.dropdown-menu-left // Only show on beta program? if user.betaProgram - li.dropdown-header #{translate("auto_compile")} + li.dropdown-header + | #{translate("auto_compile")} + span.beta-feature-badge li a(href, ng-click="autocompile_enabled = true") i.fa.fa-fw(ng-class="{'fa-check': autocompile_enabled}") From 7d5785b98f089a1828f270de0732c89cfa3ed078 Mon Sep 17 00:00:00 2001 From: Nate Stemen Date: Mon, 2 Oct 2017 18:10:53 +0100 Subject: [PATCH 41/99] adding top 100 packages and package tracking --- .../auto-complete/AutoCompleteManager.coffee | 13 +++-- .../auto-complete/CommandManager.coffee | 22 ++++---- .../auto-complete/PackageManager.coffee | 52 +++++++++++++++++++ 3 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 24a524b4b6..60241da990 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -1,10 +1,11 @@ define [ "ide/editor/directives/aceEditor/auto-complete/CommandManager" "ide/editor/directives/aceEditor/auto-complete/EnvironmentManager" + "ide/editor/directives/aceEditor/auto-complete/PackageManager" "ide/editor/directives/aceEditor/auto-complete/Helpers" "ace/ace" "ace/ext-language_tools" -], (CommandManager, EnvironmentManager, Helpers) -> +], (CommandManager, EnvironmentManager, PackageManager, Helpers) -> Range = ace.require("ace/range").Range aceSnippetManager = ace.require('ace/snippets').snippetManager @@ -35,6 +36,7 @@ define [ }) SnippetCompleter = new EnvironmentManager() + PackageCompleter = new PackageManager() Graphics = @graphics Preamble = @preamble @@ -126,10 +128,11 @@ define [ callback null, result @editor.completers = [ - @suggestionManager, - SnippetCompleter, - ReferencesCompleter, - LabelsCompleter, + @suggestionManager + SnippetCompleter + PackageCompleter + ReferencesCompleter + LabelsCompleter GraphicsCompleter ] diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee index fd6cdf7e64..c513f6854d 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee @@ -63,19 +63,19 @@ define [], () -> meta: "cmd" } special = for cmd in special - { - caption: "\\#{cmd}{}" - snippet: "\\#{cmd}{}" - meta: "cmd" - } + { + caption: "\\#{cmd}{}" + snippet: "\\#{cmd}{}" + meta: "cmd" + } staticCommands = [].concat( - noArgumentCommands, - singleArgumentCommands, - doubleArgumentCommands, - tripleArgumentCommands, - special - ) + noArgumentCommands, + singleArgumentCommands, + doubleArgumentCommands, + tripleArgumentCommands, + special + ) class Parser constructor: (@doc, @prefix) -> diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee new file mode 100644 index 0000000000..af8cac861a --- /dev/null +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee @@ -0,0 +1,52 @@ +define () -> + packages = [ + 'inputenc', 'graphicx', 'amsmath', 'geometry', 'amssymb', 'hyperref', + 'babel', 'color', 'xcolor', 'url', 'natbib', 'fontenc', 'fancyhdr', + 'amsfonts', 'booktabs', 'amsthm', 'float', 'tikz', 'caption', + 'setspace', 'multirow', 'array', 'multicol', 'titlesec', 'enumitem', + 'ifthen', 'listings', 'blindtext', 'subcaption', 'times', 'bm', + 'subfigure', 'algorithm', 'fontspec', 'biblatex', 'tabularx', + 'microtype', 'etoolbox', 'parskip', 'calc', 'verbatim', 'mathtools', + 'epsfig', 'wrapfig', 'lipsum', 'cite', 'textcomp', 'longtable', + 'textpos', 'algpseudocode', 'enumerate', 'subfig', 'pdfpages', + 'epstopdf', 'latexsym', 'lmodern', 'pifont', 'ragged2e', 'rotating', + 'dcolumn', 'xltxtra', 'marvosym', 'indentfirst', 'xspace', 'csquotes', + 'xparse', 'changepage', 'soul', 'xunicode', 'comment', 'mathrsfs', + 'tocbibind', 'lastpage', 'algorithm2e', 'pgfplots', 'lineno', + 'graphics', 'algorithmic', 'fullpage', 'mathptmx', 'todonotes', + 'ulem', 'tweaklist', 'moderncvstyleclassic', 'collection', + 'moderncvcompatibility', 'gensymb', 'helvet', 'siunitx', 'adjustbox', + 'placeins', 'colortbl', 'appendix', 'makeidx', 'supertabular', 'ifpdf', + 'framed', 'aliascnt', 'layaureo', 'authblk' + ] + + packageSnippets = for pkg in packages + { + caption: "\\usepackage{#{pkg}}" + snippet: """\\usepackage{#{pkg}}""" + meta: "pkg" + } + + parseLoadedPackages = (text) -> + re = /^\\usepackage(?:\[(.*?)])?.*?{((?:.|\n)*?)}/gm + result = [] + iterations = 0 + while match = re.exec(text) + if match[2] + for pkg in match[2].split(",") + cleaned = pkg.replace(/%.*\n/gm,'').trim() + if cleaned not in result + result.push cleaned + iterations += 1 + if iterations >= 1000 + return result + return result + + class PackageManager + getCompletions: (editor, session, pos, prefix, callback) -> + docText = session.getValue() + loaded = parseLoadedPackages(docText) + # console.log loaded + callback null, packageSnippets + + return PackageManager From 38b8450cee2c297136abc0b6bdf06c311fd6a1af Mon Sep 17 00:00:00 2001 From: James Allen Date: Tue, 3 Oct 2017 10:29:49 +0100 Subject: [PATCH 42/99] Add jsonwebtoken package --- services/web/npm-shrinkwrap.json | 1216 +++++++++++++++++++++++++++++- services/web/package.json | 1 + 2 files changed, 1211 insertions(+), 6 deletions(-) diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json index bfb59b91cc..5c26a8431e 100644 --- a/services/web/npm-shrinkwrap.json +++ b/services/web/npm-shrinkwrap.json @@ -59,6 +59,12 @@ "from": "ansi-regex@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.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", + "dev": true + }, "aproba": { "version": "1.1.2", "from": "aproba@>=1.0.3 <2.0.0", @@ -150,6 +156,12 @@ "from": "asynckit@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" }, + "autoprefixer": { + "version": "6.7.7", + "from": "autoprefixer@>=6.6.1 <7.0.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "dev": true + }, "aws-sdk": { "version": "2.113.0", "from": "aws-sdk@>=2.2.36 <3.0.0", @@ -224,6 +236,11 @@ } } }, + "base64url": { + "version": "2.0.0", + "from": "base64url@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz" + }, "basic-auth-connect": { "version": "1.0.0", "from": "basic-auth-connect@>=1.0.0 <2.0.0", @@ -297,6 +314,38 @@ "from": "brace-expansion@>=1.1.7 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" }, + "broadway": { + "version": "0.3.6", + "from": "broadway@>=0.3.2 <0.4.0", + "resolved": "https://registry.npmjs.org/broadway/-/broadway-0.3.6.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "dev": true + }, + "cliff": { + "version": "0.1.9", + "from": "cliff@0.1.9", + "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.9.tgz", + "dev": true + }, + "winston": { + "version": "0.8.0", + "from": "winston@0.8.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.0.tgz", + "dev": true + } + } + }, + "browserslist": { + "version": "1.7.7", + "from": "browserslist@>=1.7.6 <2.0.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "dev": true + }, "bson": { "version": "1.0.4", "from": "bson@>=1.0.4 <1.1.0", @@ -319,6 +368,11 @@ "from": "buffer-crc32@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "from": "buffer-equal-constant-time@1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + }, "buffer-shims": { "version": "1.0.0", "from": "buffer-shims@>=1.0.0 <2.0.0", @@ -373,6 +427,12 @@ "from": "camelize@1.0.0", "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" }, + "caniuse-db": { + "version": "1.0.30000740", + "from": "caniuse-db@>=1.0.30000634 <2.0.0", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000740.tgz", + "dev": true + }, "caseless": { "version": "0.12.0", "from": "caseless@>=0.12.0 <0.13.0", @@ -383,11 +443,31 @@ "from": "center-align@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz" }, + "chai": { + "version": "3.5.0", + "from": "chai@3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "dev": true + }, "chai-spies": { "version": "0.7.1", "from": "chai-spies@latest", "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-0.7.1.tgz" }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, "character-parser": { "version": "1.2.0", "from": "character-parser@1.2.0", @@ -415,6 +495,20 @@ } } }, + "cliff": { + "version": "0.1.10", + "from": "cliff@>=0.1.9 <0.2.0", + "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "1.0.3", + "from": "colors@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "dev": true + } + } + }, "cliui": { "version": "2.1.0", "from": "cliui@>=2.1.0 <3.0.0", @@ -568,6 +662,12 @@ "from": "cookie-signature@1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" }, + "cookies": { + "version": "0.7.1", + "from": "cookies@>=0.2.2", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", + "dev": true + }, "core-js": { "version": "1.2.7", "from": "core-js@>=1.2.0 <2.0.0", @@ -640,6 +740,19 @@ } } }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "dev": true, + "optional": true + }, + "cycle": { + "version": "1.0.3", + "from": "cycle@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "dev": true + }, "dashdash": { "version": "1.14.1", "from": "dashdash@>=1.12.0 <2.0.0", @@ -677,6 +790,20 @@ "from": "decamelize@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" }, + "deep-eql": { + "version": "0.1.3", + "from": "deep-eql@>=0.1.3 <0.2.0", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "dev": true, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "from": "type-detect@0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "dev": true + } + } + }, "deep-equal": { "version": "1.0.1", "from": "deep-equal@>=1.0.1 <1.1.0", @@ -739,6 +866,12 @@ "from": "diff@1.0.7", "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz" }, + "director": { + "version": "1.2.7", + "from": "director@1.2.7", + "resolved": "https://registry.npmjs.org/director/-/director-1.2.7.tgz", + "dev": true + }, "dns-prefetch-control": { "version": "0.1.0", "from": "dns-prefetch-control@0.1.0", @@ -749,6 +882,38 @@ "from": "doctypes@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz" }, + "dom-serializer": { + "version": "0.1.0", + "from": "dom-serializer@>=0.0.0 <1.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "dev": true, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "from": "domelementtype@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "from": "domelementtype@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "from": "domhandler@>=2.3.0 <3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "dev": true + }, + "domutils": { + "version": "1.6.2", + "from": "domutils@>=1.5.1 <2.0.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "dev": true + }, "dont-sniff-mimetype": { "version": "1.0.0", "from": "dont-sniff-mimetype@1.0.0", @@ -764,12 +929,6 @@ "from": "double-ended-queue@>=2.1.0-0 <3.0.0", "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz" }, - "dtrace-provider": { - "version": "0.2.8", - "from": "dtrace-provider@0.2.8", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.2.8.tgz", - "optional": true - }, "each-series": { "version": "1.0.0", "from": "each-series@>=1.0.0 <2.0.0", @@ -781,6 +940,11 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "optional": true }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "from": "ecdsa-sig-formatter@1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz" + }, "ee-first": { "version": "1.1.1", "from": "ee-first@1.1.1", @@ -791,6 +955,12 @@ "from": "ejs@>=0.8.3 <0.9.0", "resolved": "https://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz" }, + "electron-to-chromium": { + "version": "1.3.24", + "from": "electron-to-chromium@>=1.2.7 <2.0.0", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz", + "dev": true + }, "encodeurl": { "version": "1.0.1", "from": "encodeurl@>=1.0.1 <1.1.0", @@ -813,6 +983,12 @@ "from": "end-of-stream@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz" }, + "entities": { + "version": "1.1.1", + "from": "entities@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "dev": true + }, "es-abstract": { "version": "1.8.2", "from": "es-abstract@>=1.5.0 <2.0.0", @@ -823,6 +999,12 @@ "from": "es-to-primitive@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz" }, + "es6-promise": { + "version": "4.1.1", + "from": "es6-promise@>=4.0.5 <5.0.0", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "dev": true + }, "escape-html": { "version": "1.0.2", "from": "escape-html@1.0.2", @@ -843,6 +1025,20 @@ "from": "etag@>=1.7.0 <1.8.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" }, + "event-stream": { + "version": "0.5.3", + "from": "event-stream@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-0.5.3.tgz", + "dev": true, + "dependencies": { + "optimist": { + "version": "0.2.8", + "from": "optimist@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.2.8.tgz", + "dev": true + } + } + }, "eventemitter2": { "version": "0.4.14", "from": "eventemitter2@>=0.4.13 <0.5.0", @@ -932,11 +1128,23 @@ "from": "extsprintf@1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" }, + "eyes": { + "version": "0.1.8", + "from": "eyes@>=0.1.8 <0.2.0", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "dev": true + }, "failure": { "version": "1.1.1", "from": "failure@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz" }, + "faye-websocket": { + "version": "0.10.0", + "from": "faye-websocket@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "dev": true + }, "file-utils": { "version": "0.1.5", "from": "file-utils@>=0.1.5 <0.2.0", @@ -978,6 +1186,20 @@ } } }, + "flatiron": { + "version": "0.4.3", + "from": "flatiron@>=0.4.2 <0.5.0", + "resolved": "https://registry.npmjs.org/flatiron/-/flatiron-0.4.3.tgz", + "dev": true, + "dependencies": { + "optimist": { + "version": "0.6.0", + "from": "optimist@0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", + "dev": true + } + } + }, "flexbuffer": { "version": "0.0.6", "from": "flexbuffer@0.0.6", @@ -1005,16 +1227,42 @@ "from": "foreach@>=2.0.5 <3.0.0", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" }, + "forever": { + "version": "0.14.2", + "from": "forever@>=0.14.1 <0.15.0", + "resolved": "https://registry.npmjs.org/forever/-/forever-0.14.2.tgz", + "dev": true + }, "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" }, + "forever-monitor": { + "version": "1.5.2", + "from": "forever-monitor@>=1.5.1 <1.6.0", + "resolved": "https://registry.npmjs.org/forever-monitor/-/forever-monitor-1.5.2.tgz", + "dev": true, + "dependencies": { + "minimatch": { + "version": "1.0.0", + "from": "minimatch@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "dev": true + } + } + }, "form-data": { "version": "2.1.4", "from": "form-data@>=2.1.1 <2.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz" }, + "formatio": { + "version": "1.1.1", + "from": "formatio@1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "dev": true + }, "forwarded": { "version": "0.1.1", "from": "forwarded@>=0.1.0 <0.2.0", @@ -1089,6 +1337,12 @@ "from": "gauge@>=2.7.3 <2.8.0", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" }, + "gaze": { + "version": "1.1.2", + "from": "gaze@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "dev": true + }, "generic-pool": { "version": "2.4.2", "from": "generic-pool@2.4.2", @@ -1128,6 +1382,26 @@ } } }, + "globule": { + "version": "1.2.0", + "from": "globule@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "dev": true, + "dependencies": { + "glob": { + "version": "7.1.2", + "from": "glob@>=7.1.1 <7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "from": "minimatch@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.11", "from": "graceful-fs@>=4.1.2 <5.0.0", @@ -1195,6 +1469,26 @@ } } }, + "grunt-available-tasks": { + "version": "0.4.1", + "from": "grunt-available-tasks@0.4.1", + "resolved": "https://registry.npmjs.org/grunt-available-tasks/-/grunt-available-tasks-0.4.1.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "from": "underscore.string@>=2.3.3 <2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "dev": true + } + } + }, "grunt-bunyan": { "version": "0.5.0", "from": "grunt-bunyan@>=0.5.0 <0.6.0", @@ -1207,11 +1501,151 @@ } } }, + "grunt-contrib-clean": { + "version": "0.5.0", + "from": "grunt-contrib-clean@0.5.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz", + "dev": true + }, + "grunt-contrib-coffee": { + "version": "0.10.0", + "from": "grunt-contrib-coffee@0.10.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.10.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "from": "ansi-styles@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "from": "chalk@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "dev": true + }, + "coffee-script": { + "version": "1.7.1", + "from": "coffee-script@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "from": "strip-ansi@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "dev": true + } + } + }, + "grunt-contrib-less": { + "version": "0.9.0", + "from": "grunt-contrib-less@0.9.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-0.9.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "from": "ansi-styles@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "from": "chalk@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "from": "strip-ansi@~0.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "dev": true + } + } + }, + "grunt-contrib-requirejs": { + "version": "0.4.1", + "from": "grunt-contrib-requirejs@0.4.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-requirejs/-/grunt-contrib-requirejs-0.4.1.tgz", + "dev": true + }, + "grunt-contrib-watch": { + "version": "1.0.0", + "from": "grunt-contrib-watch@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "1.5.2", + "from": "async@>=1.5.0 <2.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "from": "lodash@>=3.10.1 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "dev": true + } + } + }, + "grunt-env": { + "version": "0.4.4", + "from": "grunt-env@0.4.4", + "resolved": "https://registry.npmjs.org/grunt-env/-/grunt-env-0.4.4.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + } + } + }, + "grunt-exec": { + "version": "0.4.7", + "from": "grunt-exec@>=0.4.7 <0.5.0", + "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.7.tgz", + "dev": true + }, "grunt-execute": { "version": "0.2.2", "from": "grunt-execute@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz" }, + "grunt-file-append": { + "version": "0.0.6", + "from": "grunt-file-append@0.0.6", + "resolved": "https://registry.npmjs.org/grunt-file-append/-/grunt-file-append-0.0.6.tgz", + "dev": true + }, + "grunt-forever": { + "version": "0.4.7", + "from": "grunt-forever@>=0.4.7 <0.5.0", + "resolved": "https://registry.npmjs.org/grunt-forever/-/grunt-forever-0.4.7.tgz", + "dev": true + }, + "grunt-git-rev-parse": { + "version": "0.1.5", + "from": "grunt-git-rev-parse@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-git-rev-parse/-/grunt-git-rev-parse-0.1.5.tgz", + "dev": true + }, "grunt-legacy-log": { "version": "0.1.3", "from": "grunt-legacy-log@>=0.1.0 <0.2.0", @@ -1263,6 +1697,90 @@ } } }, + "grunt-lib-contrib": { + "version": "0.6.1", + "from": "grunt-lib-contrib@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz", + "dev": true + }, + "grunt-mocha-test": { + "version": "0.9.0", + "from": "grunt-mocha-test@0.9.0", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.9.0.tgz", + "dev": true + }, + "grunt-newer": { + "version": "1.3.0", + "from": "grunt-newer@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-newer/-/grunt-newer-1.3.0.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "1.5.2", + "from": "async@^1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "dev": true + }, + "glob": { + "version": "7.1.2", + "from": "glob@^7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "from": "minimatch@^3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "from": "rimraf@>=2.5.2 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "dev": true + } + } + }, + "grunt-parallel": { + "version": "0.5.1", + "from": "grunt-parallel@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/grunt-parallel/-/grunt-parallel-0.5.1.tgz", + "dev": true, + "dependencies": { + "q": { + "version": "0.8.12", + "from": "q@>=0.8.12 <0.9.0", + "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "dev": true + } + } + }, + "grunt-postcss": { + "version": "0.8.0", + "from": "grunt-postcss@>=0.8.0 <0.9.0", + "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.8.0.tgz", + "dev": true, + "dependencies": { + "diff": { + "version": "2.2.3", + "from": "diff@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "dev": true + } + } + }, + "grunt-sed": { + "version": "0.1.1", + "from": "grunt-sed@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-sed/-/grunt-sed-0.1.1.tgz", + "dev": true + }, + "grunt-shell": { + "version": "2.1.0", + "from": "grunt-shell@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-2.1.0.tgz", + "dev": true + }, "hang": { "version": "1.0.0", "from": "hang@>=1.0.0 <1.1.0", @@ -1283,6 +1801,24 @@ "from": "has@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz" }, + "has-ansi": { + "version": "2.0.0", + "from": "has-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "dev": true + }, + "has-color": { + "version": "0.1.7", + "from": "has-color@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "from": "has-flag@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "dev": true + }, "has-unicode": { "version": "2.0.1", "from": "has-unicode@>=2.0.0 <3.0.0", @@ -1338,11 +1874,43 @@ "from": "hsts@2.1.0", "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.1.0.tgz" }, + "htmlparser2": { + "version": "3.9.2", + "from": "htmlparser2@>=3.9.0 <4.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "from": "readable-stream@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "from": "string_decoder@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "dev": true + } + } + }, "http-errors": { "version": "1.6.2", "from": "http-errors@>=1.6.2 <1.7.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz" }, + "http-parser-js": { + "version": "0.4.8", + "from": "http-parser-js@>=0.4.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.8.tgz", + "dev": true + }, "http-proxy": { "version": "1.16.2", "from": "http-proxy@>=1.8.1 <2.0.0", @@ -1353,6 +1921,18 @@ "from": "http-signature@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" }, + "i": { + "version": "0.3.5", + "from": "i@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.5.tgz", + "dev": true + }, + "i18next": { + "version": "1.7.10", + "from": "i18next@>=1.7.1 <1.8.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-1.7.10.tgz", + "dev": true + }, "iconv-lite": { "version": "0.2.11", "from": "iconv-lite@>=0.2.11 <0.3.0", @@ -1492,6 +2072,12 @@ "from": "jmespath@0.15.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz" }, + "js-base64": { + "version": "2.3.2", + "from": "js-base64@>=2.1.9 <3.0.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", + "dev": true + }, "js-stringify": { "version": "1.0.2", "from": "js-stringify@>=1.0.1 <2.0.0", @@ -1523,6 +2109,12 @@ "from": "json-stringify-safe@>=5.0.1 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, + "json5": { + "version": "0.2.0", + "from": "json5@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.2.0.tgz", + "dev": true + }, "jsonfile": { "version": "1.1.1", "from": "jsonfile@>=1.1.0 <1.2.0", @@ -1533,6 +2125,11 @@ "from": "jsonify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" }, + "jsonwebtoken": { + "version": "8.0.1", + "from": "jsonwebtoken@latest", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz" + }, "jsprim": { "version": "1.4.1", "from": "jsprim@>=1.2.2 <2.0.0", @@ -1567,16 +2164,38 @@ "from": "just-extend@>=1.1.22 <2.0.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.22.tgz" }, + "jwa": { + "version": "1.1.5", + "from": "jwa@>=1.1.4 <2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz" + }, + "jws": { + "version": "3.1.4", + "from": "jws@>=3.1.4 <4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz" + }, "kareem": { "version": "1.5.0", "from": "kareem@1.5.0", "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz" }, + "keygrip": { + "version": "1.0.2", + "from": "keygrip@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", + "dev": true + }, "kind-of": { "version": "3.2.2", "from": "kind-of@>=3.0.2 <4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" }, + "lazy": { + "version": "1.0.11", + "from": "lazy@>=1.0.11 <1.1.0", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "dev": true + }, "lazy-cache": { "version": "1.0.4", "from": "lazy-cache@>=1.0.3 <2.0.0", @@ -1708,6 +2327,42 @@ } } }, + "less": { + "version": "1.6.3", + "from": "less@>=1.6.0 <1.7.0", + "resolved": "https://registry.npmjs.org/less/-/less-1.6.3.tgz", + "dev": true, + "dependencies": { + "clean-css": { + "version": "2.0.8", + "from": "clean-css@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.0.8.tgz", + "dev": true, + "optional": true + }, + "commander": { + "version": "2.0.0", + "from": "commander@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "dev": true, + "optional": true + }, + "mime": { + "version": "1.2.11", + "from": "mime@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "dev": true, + "optional": true + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@~0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "dev": true, + "optional": true + } + } + }, "libbase64": { "version": "0.1.0", "from": "libbase64@0.1.0", @@ -1730,6 +2385,12 @@ "from": "libqp@1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" }, + "livereload-js": { + "version": "2.2.2", + "from": "livereload-js@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "dev": true + }, "loads": { "version": "0.0.4", "from": "loads@>=0.0.0 <0.1.0", @@ -1740,6 +2401,41 @@ "from": "lodash@>=4.13.1 <5.0.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" }, + "lodash.includes": { + "version": "4.3.0", + "from": "lodash.includes@>=4.3.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" + }, + "lodash.isboolean": { + "version": "3.0.3", + "from": "lodash.isboolean@>=3.0.3 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" + }, + "lodash.isinteger": { + "version": "4.0.4", + "from": "lodash.isinteger@>=4.0.4 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" + }, + "lodash.isnumber": { + "version": "3.0.3", + "from": "lodash.isnumber@>=3.0.3 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "from": "lodash.isplainobject@>=4.0.6 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" + }, + "lodash.isstring": { + "version": "4.0.1", + "from": "lodash.isstring@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" + }, + "lodash.once": { + "version": "4.1.1", + "from": "lodash.once@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" + }, "lodash.reduce": { "version": "4.6.0", "from": "lodash.reduce@4.6.0", @@ -1962,11 +2658,23 @@ } } }, + "lolex": { + "version": "1.3.2", + "from": "lolex@1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "dev": true + }, "longest": { "version": "1.0.1", "from": "longest@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" }, + "lpad": { + "version": "0.1.0", + "from": "lpad@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/lpad/-/lpad-0.1.0.tgz", + "dev": true + }, "lru-cache": { "version": "2.7.3", "from": "lru-cache@>=2.0.0 <3.0.0", @@ -2310,6 +3018,12 @@ "from": "muri@1.2.2", "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz" }, + "mute-stream": { + "version": "0.0.7", + "from": "mute-stream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "dev": true + }, "mv": { "version": "0.0.5", "from": "mv@0.0.5", @@ -2326,6 +3040,26 @@ "from": "native-promise-only@>=0.8.1 <0.9.0", "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz" }, + "nconf": { + "version": "0.6.9", + "from": "nconf@>=0.6.9 <0.7.0", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.6.9.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.9", + "from": "async@0.2.9", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz", + "dev": true + }, + "optimist": { + "version": "0.6.0", + "from": "optimist@0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", + "dev": true + } + } + }, "ncp": { "version": "2.0.0", "from": "ncp@>=2.0.0 <2.1.0", @@ -2441,16 +3175,60 @@ "from": "nodemailer-wellknown@0.1.7", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz" }, + "nomnom": { + "version": "1.6.2", + "from": "nomnom@>=1.6.0 <1.7.0", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "0.5.1", + "from": "colors@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "from": "underscore@>=1.4.4 <1.5.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "dev": true + } + } + }, "nopt": { "version": "3.0.6", "from": "nopt@>=3.0.1 <3.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" }, + "normalize-range": { + "version": "0.1.2", + "from": "normalize-range@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "from": "npm-run-path@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "dev": true + }, "npmlog": { "version": "4.1.2", "from": "npmlog@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" }, + "nssocket": { + "version": "0.5.3", + "from": "nssocket@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.5.3.tgz", + "dev": true + }, + "num2fraction": { + "version": "1.2.2", + "from": "num2fraction@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "from": "number-is-nan@>=1.0.0 <2.0.0", @@ -2501,6 +3279,154 @@ "from": "one-time@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz" }, + "onesky": { + "version": "0.1.6", + "from": "onesky@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/onesky/-/onesky-0.1.6.tgz", + "dev": true, + "dependencies": { + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "dev": true, + "optional": true + }, + "async": { + "version": "0.9.2", + "from": "async@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "dev": true, + "optional": true + }, + "boom": { + "version": "0.4.2", + "from": "boom@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dev": true, + "optional": true + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "dev": true, + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dev": true, + "optional": true + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dev": true, + "optional": true + }, + "hoek": { + "version": "0.9.1", + "from": "hoek@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "dev": true, + "optional": true + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "dev": true, + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "dev": true + }, + "oauth-sign": { + "version": "0.3.0", + "from": "oauth-sign@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "dev": true, + "optional": true + }, + "qs": { + "version": "1.0.2", + "from": "qs@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "dev": true + }, + "request": { + "version": "2.40.0", + "from": "request@>=2.40.0 <2.41.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "dev": true + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.4.3", + "from": "tunnel-agent@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "dev": true, + "optional": true + } + } + }, "optimist": { "version": "0.6.1", "from": "optimist@0.6.1", @@ -2595,6 +3521,12 @@ "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" }, + "path-key": { + "version": "2.0.1", + "from": "path-key@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "dev": true + }, "path-parse": { "version": "1.0.5", "from": "path-parse@>=1.0.5 <2.0.0", @@ -2620,6 +3552,12 @@ "from": "performance-now@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz" }, + "pkginfo": { + "version": "0.3.1", + "from": "pkginfo@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "dev": true + }, "platform": { "version": "1.3.4", "from": "platform@1.3.4", @@ -2642,6 +3580,26 @@ } } }, + "postcss": { + "version": "5.2.17", + "from": "postcss@>=5.2.16 <6.0.0", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "from": "source-map@>=0.5.6 <0.6.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "from": "postcss-value-parser@>=3.2.3 <4.0.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "dev": true + }, "precond": { "version": "0.2.3", "from": "precond@>=0.2.0 <0.3.0", @@ -2657,11 +3615,23 @@ "from": "promise@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz" }, + "prompt": { + "version": "0.2.14", + "from": "prompt@0.2.14", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", + "dev": true + }, "proxy-addr": { "version": "1.0.10", "from": "proxy-addr@>=1.0.8 <1.1.0", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz" }, + "ps-tree": { + "version": "0.0.3", + "from": "ps-tree@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-0.0.3.tgz", + "dev": true + }, "pseudomap": { "version": "1.0.2", "from": "pseudomap@>=1.0.1 <2.0.0", @@ -2856,6 +3826,12 @@ } } }, + "read": { + "version": "1.0.7", + "from": "read@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "dev": true + }, "readable-stream": { "version": "1.0.34", "from": "readable-stream@>=1.0.24 <1.1.0", @@ -3118,11 +4094,31 @@ "from": "regexp-clone@0.0.1", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz" }, + "regexp-quote": { + "version": "0.0.0", + "from": "regexp-quote@0.0.0", + "resolved": "https://registry.npmjs.org/regexp-quote/-/regexp-quote-0.0.0.tgz", + "dev": true + }, "repeat-string": { "version": "1.6.1", "from": "repeat-string@>=1.5.2 <2.0.0", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" }, + "replace": { + "version": "0.2.10", + "from": "replace@>=0.2.4 <0.3.0", + "resolved": "https://registry.npmjs.org/replace/-/replace-0.2.10.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "0.5.1", + "from": "colors@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "dev": true + } + } + }, "request": { "version": "2.81.0", "from": "request@>=2.69.0 <3.0.0", @@ -3150,6 +4146,12 @@ "from": "require-like@0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" }, + "requirejs": { + "version": "2.1.22", + "from": "requirejs@>=2.1.0 <2.2.0", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.22.tgz", + "dev": true + }, "requires-port": { "version": "1.0.0", "from": "requires-port@>=1.0.0 <2.0.0", @@ -3182,6 +4184,12 @@ } } }, + "revalidator": { + "version": "0.1.8", + "from": "revalidator@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "dev": true + }, "right-align": { "version": "0.1.3", "from": "right-align@>=0.1.1 <0.2.0", @@ -3218,6 +4226,26 @@ "from": "samsam@1.1.2", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz" }, + "sandboxed-module": { + "version": "0.2.0", + "from": "sandboxed-module@0.2.0", + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-0.2.0.tgz", + "dev": true, + "dependencies": { + "stack-trace": { + "version": "0.0.6", + "from": "stack-trace@0.0.6", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.6.tgz", + "dev": true + } + } + }, + "sanitize-html": { + "version": "1.14.1", + "from": "sanitize-html@>=1.14.1 <2.0.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.14.1.tgz", + "dev": true + }, "sanitizer": { "version": "0.1.1", "from": "sanitizer@0.1.1", @@ -3368,6 +4396,12 @@ "from": "signal-exit@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" }, + "sinon": { + "version": "1.17.7", + "from": "sinon@>=1.17.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "dev": true + }, "sixpack-client": { "version": "1.0.0", "from": "sixpack-client@>=1.0.0 <2.0.0", @@ -3465,6 +4499,12 @@ "from": "strip-json-comments@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" }, + "supports-color": { + "version": "3.2.3", + "from": "supports-color@>=3.2.3 <4.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "dev": true + }, "tape": { "version": "4.8.0", "from": "tape@>=4.6.3 <5.0.0", @@ -3574,6 +4614,84 @@ "from": "timekeeper@latest", "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.0.0.tgz" }, + "timespan": { + "version": "2.3.0", + "from": "timespan@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "dev": true + }, + "tiny-lr": { + "version": "0.2.1", + "from": "tiny-lr@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "dev": true, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "from": "body-parser@>=1.14.0 <1.15.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "dev": true, + "dependencies": { + "qs": { + "version": "5.2.0", + "from": "qs@5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "from": "bytes@2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "dev": true + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "from": "http-errors@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "from": "iconv-lite@0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "dev": true + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "dev": true + }, + "qs": { + "version": "5.1.0", + "from": "qs@>=5.1.0 <5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "from": "raw-body@>=2.1.5 <2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "dev": true + } + } + } + } + }, "to-mongodb-core": { "version": "2.0.0", "from": "to-mongodb-core@>=2.0.0 <3.0.0", @@ -3611,6 +4729,20 @@ } } }, + "translations-sharelatex": { + "version": "0.1.4", + "from": "git+https://github.com/sharelatex/translations-sharelatex.git#master", + "resolved": "git+https://github.com/sharelatex/translations-sharelatex.git#12d5cefc591bcc0b4e54b5ce9acfbd980208b9e1", + "dev": true, + "dependencies": { + "async": { + "version": "2.5.0", + "from": "async@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "dev": true + } + } + }, "tsscmp": { "version": "1.0.5", "from": "tsscmp@1.0.5", @@ -3627,6 +4759,12 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "optional": true }, + "type-detect": { + "version": "1.0.0", + "from": "type-detect@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "dev": true + }, "type-is": { "version": "1.6.15", "from": "type-is@>=1.6.15 <1.7.0", @@ -3708,6 +4846,26 @@ "from": "util-deprecate@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" }, + "utile": { + "version": "0.2.1", + "from": "utile@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.9 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "from": "ncp@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "dev": true + } + } + }, "utils-merge": { "version": "1.0.0", "from": "utils-merge@1.0.0", @@ -3841,6 +4999,32 @@ "from": "void-elements@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" }, + "watch": { + "version": "0.13.0", + "from": "watch@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.13.0.tgz", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "from": "websocket-driver@>=0.5.1", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "dev": true + }, + "websocket-extensions": { + "version": "0.1.2", + "from": "websocket-extensions@>=0.1.1", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.2.tgz", + "dev": true + }, "which": { "version": "1.0.9", "from": "which@>=1.0.5 <1.1.0", @@ -3856,6 +5040,20 @@ "from": "window-size@0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" }, + "winston": { + "version": "0.8.3", + "from": "winston@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "dev": true + } + } + }, "with": { "version": "3.0.1", "from": "with@>=3.0.0 <3.1.0", @@ -3966,6 +5164,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" } } + }, + "zlib-browserify": { + "version": "0.0.1", + "from": "zlib-browserify@0.0.1", + "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz", + "dev": true } } } diff --git a/services/web/package.json b/services/web/package.json index 25122f635d..a35688bfe7 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -30,6 +30,7 @@ "http-proxy": "^1.8.1", "ioredis": "^2.4.0", "jade": "~1.3.1", + "jsonwebtoken": "^8.0.1", "ldapjs": "^0.7.1", "lodash": "^4.13.1", "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master", From 15b73713d2b98c561633df09fe0f05854cbeb36d Mon Sep 17 00:00:00 2001 From: James Allen Date: Tue, 3 Oct 2017 10:43:17 +0100 Subject: [PATCH 43/99] Add OL + SL image from blog --- services/web/public/img/ol_plus_sl.png | Bin 0 -> 62033 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 services/web/public/img/ol_plus_sl.png diff --git a/services/web/public/img/ol_plus_sl.png b/services/web/public/img/ol_plus_sl.png new file mode 100644 index 0000000000000000000000000000000000000000..b0b8523dc7aaef8d6cea9fabf5c41916cc5e6653 GIT binary patch literal 62033 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 fd=_pOHf=>#oeGI7!#*rj(@-p7 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 literal 0 HcmV?d00001 From 91e0397bf54b7f88c0c29ecee79f13789b42ba86 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 3 Oct 2017 10:48:59 +0100 Subject: [PATCH 44/99] Update signup date check to today --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 7c0328fe17..17adeae4c1 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -254,7 +254,7 @@ module.exports = ProjectController = return cb() timestamp = user_id.toString().substring(0,8) userSignupDate = new Date( parseInt( timestamp, 16 ) * 1000 ) - if userSignupDate > new Date("2017-10-05") + if userSignupDate > new Date("2017-10-03") # Don't show for users who registered after it was released return cb(null, false) timeout = setTimeout cb, 500 From d14723f24a8a45005a267ff5b69fe6df77605a7e Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 3 Oct 2017 16:16:21 +0100 Subject: [PATCH 45/99] add rate limits for autocompiles global rate limit for all users and a lower rate limit for free users --- .../Features/Compile/CompileManager.coffee | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index 61fe7038a6..756222121a 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -34,12 +34,16 @@ module.exports = CompileManager = return callback(error) if error? for key, value of limits options[key] = value - # only pass user_id down to clsi if this is a per-user compile - compileAsUser = if Settings.disablePerUserCompiles then undefined else user_id - ClsiManager.sendRequest project_id, compileAsUser, options, (error, status, outputFiles, clsiServerId, validationProblems) -> - return callback(error) if error? - logger.log files: outputFiles, "output files" - callback(null, status, outputFiles, clsiServerId, limits, validationProblems) + # Put a lower limit on autocompiles for free users + CompileManager._checkIfFreeAutoCompileLimitHasBeenHit options.isAutoCompile, limits.compileGroup, (err, canCompile)-> + if !canCompile + return callback null, "autocompile-backoff", [] + # only pass user_id down to clsi if this is a per-user compile + compileAsUser = if Settings.disablePerUserCompiles then undefined else user_id + ClsiManager.sendRequest project_id, compileAsUser, options, (error, status, outputFiles, clsiServerId, validationProblems) -> + return callback(error) if error? + logger.log files: outputFiles, "output files" + callback(null, status, outputFiles, clsiServerId, limits, validationProblems) stopCompile: (project_id, user_id, callback = (error) ->) -> @@ -75,15 +79,41 @@ module.exports = CompileManager = _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, callback = (err, canCompile)->)-> if !isAutoCompile return callback(null, true) - opts = + Metrics.inc "auto-compile" + opts = endpointName:"auto_compile" timeInterval:20 subjectName:"everyone" - throttle: 25 + throttle: 200 rateLimiter.addCount opts, (err, canCompile)-> if err? canCompile = false logger.log canCompile:canCompile, opts:opts, "checking if auto compile limit has been hit" + if !canCompile + Metrics.inc "auto-compile-rate-limited" + callback err, canCompile + + + _checkIfFreeAutoCompileLimitHasBeenHit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> + if !isAutoCompile + return callback(null, true) + + if compileGroup is "priority" + Metrics.inc "auto-compile-priority" + return callback(null, true) + + Metrics.inc "auto-compile-free" + opts = + endpointName:"auto_compile" + timeInterval:20 + subjectName:"free" + throttle: 100 + rateLimiter.addCount opts, (err, canCompile)-> + if err? + canCompile = false + logger.log canCompile:canCompile, opts:opts, "checking if free users auto compile limit has been hit" + if !canCompile + Metrics.inc "auto-compile-free-rate-limited" callback err, canCompile _ensureRootDocumentIsSet: (project_id, callback = (error) ->) -> From 2723537f824d757fa07f61bc1892571357c73d69 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 3 Oct 2017 16:23:49 +0100 Subject: [PATCH 46/99] disable autocompile when rate limit is hit --- services/web/app/views/project/editor/pdf.pug | 6 ++++++ .../coffee/ide/pdf/controllers/PdfController.coffee | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 377f09f71a..02531e9584 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -391,6 +391,12 @@ div.full-size.pdf(ng-controller="PdfController") ng-click="startFreeTrial('compile-timeout')" ) #{translate("start_free_trial")} + + .alert.alert-danger(ng-show="pdf.autocompile_disabled") + p + strong #{translate("autocompile_disabled")}. + span #{translate("autocompile_disabled_reason")} + .alert.alert-danger(ng-show="pdf.projectTooLarge") strong #{translate("project_too_large")} span #{translate("project_too_large_please_reduce")} diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 73ae9a4380..e77d4a22cb 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -127,7 +127,7 @@ define [ sendCompileRequest = (options = {}) -> url = "/project/#{$scope.project_id}/compile" params = {} - if options.isAutoCompile + if options.isAutoCompile or options.isBackgroundAutoCompile params["auto_compile"]=true # if the previous run was a check, clear the error logs $scope.pdf.logEntries = [] if $scope.check @@ -168,6 +168,7 @@ define [ $scope.pdf.compileExited = false $scope.pdf.failedCheck = false $scope.pdf.compileInProgress = false + $scope.pdf.autocompile_disabled = false # make a cache to look up files by name fileByPath = {} @@ -206,7 +207,13 @@ define [ $scope.shouldShowLogs = true fetchLogs(fileByPath) else if response.status == "autocompile-backoff" - $scope.pdf.view = 'uncompiled' + if $scope.pdf.isAutoCompile # initial autocompile + $scope.pdf.view = 'uncompiled' + else # background autocompile from typing + $scope.pdf.view = 'errors' + $scope.pdf.autocompile_disabled = true + $scope.autocompile_enabled = false # disable any further autocompiles + event_tracking.sendMB "autocompile-rate-limited", {hasPremiumCompile: $scope.hasPremiumCompile} else if response.status == "project-too-large" $scope.pdf.view = 'errors' $scope.pdf.projectTooLarge = true @@ -415,6 +422,7 @@ define [ event_tracking.sendMBSampled "editor-recompile-sampled", options $scope.pdf.compiling = true + $scope.pdf.isAutoCompile = options?.isAutoCompile # initial autocompile if options?.force # for forced compile, turn off validation check and ignore errors From 8366ea271f50b2c4791d7cb903b78baa1d5b6ac3 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 3 Oct 2017 17:08:19 +0100 Subject: [PATCH 47/99] Restrict autocompile onboarding to users in rollout (factor of 100) --- .../coffee/Features/Project/ProjectController.coffee | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 17adeae4c1..89b47b5782 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -252,8 +252,15 @@ module.exports = ProjectController = cb = underscore.once(cb) if !user_id? return cb() - timestamp = user_id.toString().substring(0,8) - userSignupDate = new Date( parseInt( timestamp, 16 ) * 1000 ) + + # Extract data from user's ObjectId + timestamp = parseInt(user_id.toString().substring(0, 8), 16) + counter = parseInt(user_id.toString().substring(18, 24), 16) + + if counter % 5000 != 0 + # Don't show if user is not part of roll out + return cb(null, false) + userSignupDate = new Date(timestamp * 1000) if userSignupDate > new Date("2017-10-03") # Don't show for users who registered after it was released return cb(null, false) From 550e7d75ca703a66214cdb6c9605ddae5daf7fd9 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 3 Oct 2017 17:19:51 +0100 Subject: [PATCH 48/99] Check if user is part of autocompile rollout when showing setting or running autocompile --- services/web/app/views/project/editor/pdf.pug | 2 +- .../web/public/coffee/ide/pdf/controllers/PdfController.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 69fc28cc54..2e0bc3701f 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -27,7 +27,7 @@ div.full-size.pdf(ng-controller="PdfController") span.caret ul.dropdown-menu.dropdown-menu-left // Only show on beta program? - if user.betaProgram + if user.betaProgram || showAutoCompileOnboarding li.dropdown-header | #{translate("auto_compile")} span.beta-feature-badge diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 1e0403bb76..1a482e8ede 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -109,7 +109,7 @@ define [ toggleAutoCompile(newValue) event_tracking.sendMB "autocompile-setting-changed", { value: newValue } - if window.user?.betaProgram and $scope.autocompile_enabled + if (window.user?.betaProgram or window.showAutoCompileOnboarding) and $scope.autocompile_enabled toggleAutoCompile(true) # abort compile if syntax checks fail From 8b4843cf8b655eb8798a4604f0862983f3374292 Mon Sep 17 00:00:00 2001 From: Nate Stemen Date: Tue, 3 Oct 2017 17:32:34 +0100 Subject: [PATCH 49/99] cleaning up usepackage completion --- .../auto-complete/CommandManager.coffee | 4 ++-- .../auto-complete/PackageManager.coffee | 20 ++++++------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee index c513f6854d..88cd3a2e84 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee @@ -12,7 +12,7 @@ define [], () -> 'Lambda', 'Xi', 'Pi', 'Sigma', 'Upsilon', 'Phi', 'Psi', 'Omega' ] singleArgumentCommands = [ - 'chapter', 'usepackage', 'section', 'label', 'textbf', 'subsection', + 'chapter', 'section', 'label', 'textbf', 'subsection', 'vspace', 'cite', 'textit', 'documentclass', 'includegraphics', 'input', 'emph','caption', 'ref', 'title', 'author', 'texttt', 'include', 'hspace', 'bibitem', 'url', 'large', 'subsubsection', 'textsc', 'date', @@ -172,7 +172,7 @@ define [], () -> commands = parser.parse() completions = [] for command in commands - if command[0] not in rawCommands + if command[0] not in rawCommands and command[0] != "usepackage" caption = "\\#{command[0]}" score = if caption == prefix then 99 else 50 snippet = caption diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee index af8cac861a..ac30d5a431 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee @@ -27,20 +27,12 @@ define () -> meta: "pkg" } - parseLoadedPackages = (text) -> - re = /^\\usepackage(?:\[(.*?)])?.*?{((?:.|\n)*?)}/gm - result = [] - iterations = 0 - while match = re.exec(text) - if match[2] - for pkg in match[2].split(",") - cleaned = pkg.replace(/%.*\n/gm,'').trim() - if cleaned not in result - result.push cleaned - iterations += 1 - if iterations >= 1000 - return result - return result + packageSnippets.push { + caption: "\\usepackage{}" + snippet: "\\usepackage{}" + meta: "pkg" + score: 70 + } class PackageManager getCompletions: (editor, session, pos, prefix, callback) -> From afe40809ad0daa8fbd5e8df72726e85d147b0e69 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 4 Oct 2017 14:57:08 +0100 Subject: [PATCH 50/99] Add in account merge module to build step --- services/web/Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 6421174e68..5c7b4e160f 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -42,6 +42,7 @@ pipeline { checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'modules/templates'], [$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[credentialsId: 'GIT_DEPLOY_KEY', url: 'git@github.com:sharelatex/templates-webmodule.git']]]) checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'modules/track-changes'], [$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[credentialsId: 'GIT_DEPLOY_KEY', url: 'git@github.com:sharelatex/track-changes-web-module.git']]]) checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'modules/overleaf-integration'], [$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[credentialsId: 'GIT_DEPLOY_KEY', url: 'git@github.com:sharelatex/overleaf-integration-web-module.git']]]) + checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'modules/overleaf-account-merge'], [$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[credentialsId: 'GIT_DEPLOY_KEY', url: 'git@github.com:sharelatex/overleaf-account-merge.git']]]) } } From 9c1faa43950c36b86c0745cda85eb7aa5f1daa3a Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 5 Oct 2017 14:26:34 +0100 Subject: [PATCH 51/99] Add method to transfer projects from one user_id to another --- .../Collaborators/CollaboratorsHandler.coffee | 70 ++++++++++++ .../CollaboratorsHandlerTests.coffee | 100 ++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee index 44b6bd9ec2..ff6a52e471 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee @@ -157,3 +157,73 @@ module.exports = CollaboratorsHandler = return callback(error) {owner, members} = ProjectEditorHandler.buildOwnerAndMembersViews(rawMembers) callback(null, members) + + transferProjects: (from_user_id, to_user_id, callback=(err, projects) ->) -> + MEMBER_KEYS = ['collaberator_refs', 'readOnly_refs'] + + # jobs = [] + # project_ids = [] + # jobs.push (cb) -> + # Project.find { owner_ref: from_user_id }, { _id: 1 }, (error, projects = []) -> + # return callback(error) if error? + # project_ids = project_ids.concat(projects.map (p) -> p._id) + # Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb + + # for key in MEMBER_KEYS + # do (key) -> + # jobs.push (cb) -> + # query = {} + # query[] + # Project.find { owner_ref: from_user_id }, { _id: 1 }, (error, projects = []) -> + # return callback(error) if error? + # project_ids = project_ids.concat(projects.map (p) -> p._id) + # Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb + + # Find all the projects this user is part of so we can flush them to TPDS + query = + $or: + [{ owner_ref: from_user_id }] + .concat( + MEMBER_KEYS.map (key) -> + q = {} + q[key] = from_user_id + return q + ) # [{ collaberator_refs: from_user_id }, ...] + Project.find query, { _id: 1 }, (error, projects = []) -> + return callback(error) if error? + + project_ids = projects.map (p) -> p._id + logger.log {project_ids, from_user_id, to_user_id}, "transferring projects" + + update_jobs = [] + update_jobs.push (cb) -> + Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb + for key in MEMBER_KEYS + do (key) -> + update_jobs.push (cb) -> + query = {} + addNewUserUpdate = $addToSet: {} + removeOldUserUpdate = $pull: {} + query[key] = from_user_id + removeOldUserUpdate.$pull[key] = from_user_id + addNewUserUpdate.$addToSet[key] = to_user_id + # Mongo won't let us pull and addToSet in the same query, so do it in + # two. Note we need to add first, since the query is based on the old user. + Project.update query, addNewUserUpdate, { multi: true }, (error) -> + return cb(error) if error? + Project.update query, removeOldUserUpdate, { multi: true }, cb + + # Flush each project to TPDS to add files to new user's Dropbox + ProjectEntityHandler = require("../Project/ProjectEntityHandler") + flush_jobs = [] + for project_id in project_ids + do (project_id) -> + flush_jobs.push (cb) -> + ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, cb + + # Flush in background, no need to block on this + async.series flush_jobs, (error) -> + if error? + logger.err {err: error, project_ids, from_user_id, to_user_id}, "error flushing tranferred projects to TPDS" + + async.series update_jobs, callback diff --git a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee index 9ba099f60b..ee231f7c9f 100644 --- a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee @@ -344,3 +344,103 @@ describe "CollaboratorsHandler", -> it 'should not call ProjectEditorHandler.buildOwnerAndMembersViews', -> @ProjectEditorHandler.buildOwnerAndMembersViews.callCount.should.equal 0 + + describe 'transferProjects', -> + beforeEach -> + @from_user_id = "from-user-id" + @to_user_id = "to-user-id" + @projects = [{ + _id: "project-id-1" + }, { + _id: "project-id-2" + }] + @Project.find = sinon.stub().yields(null, @projects) + @Project.update = sinon.stub().yields() + @ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().yields() + + describe "successfully", -> + beforeEach -> + @CollaboratorHandler.transferProjects @from_user_id, @to_user_id, @callback + + it "should look up the affected projects", -> + @Project.find + .calledWith({ + $or : [ + { owner_ref: @from_user_id } + { collaberator_refs: @from_user_id } + { readOnly_refs: @from_user_id } + ] + }) + .should.equal true + + it "should transfer owned projects", -> + @Project.update + .calledWith({ + owner_ref: @from_user_id + }, { + $set: { owner_ref: @to_user_id } + }, { + multi: true + }) + .should.equal true + + it "should transfer collaborator projects", -> + @Project.update + .calledWith({ + collaberator_refs: @from_user_id + }, { + $addToSet: { collaberator_refs: @to_user_id } + }, { + multi: true + }) + .should.equal true + @Project.update + .calledWith({ + collaberator_refs: @from_user_id + }, { + $pull: { collaberator_refs: @from_user_id } + }, { + multi: true + }) + .should.equal true + + it "should transfer read only collaborator projects", -> + @Project.update + .calledWith({ + readOnly_refs: @from_user_id + }, { + $addToSet: { readOnly_refs: @to_user_id } + }, { + multi: true + }) + .should.equal true + @Project.update + .calledWith({ + readOnly_refs: @from_user_id + }, { + $pull: { readOnly_refs: @from_user_id } + }, { + multi: true + }) + .should.equal true + + it "should flush each project to the TPDS", -> + for project in @projects + @ProjectEntityHandler.flushProjectToThirdPartyDataStore + .calledWith(project._id) + .should.equal true + + it "should call the callback", -> + @callback.called.should.equal true + + describe "when flushing to TPDS fails", -> + beforeEach -> + @ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().yields(new Error('oops')) + @CollaboratorHandler.transferProjects @from_user_id, @to_user_id, @callback + + it "should log an error", -> + @logger.err.called.should.equal true + + it "should not return an error since it happens in the background", -> + @callback.called.should.equal true + @callback.calledWith(new Error('oops')).should.equal false \ No newline at end of file From 3c54419eb338ae17acfd42c85499b982f33f2fa5 Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 5 Oct 2017 16:12:26 +0100 Subject: [PATCH 52/99] Remove commented debug code --- .../Collaborators/CollaboratorsHandler.coffee | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee index ff6a52e471..a38d5370e4 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee @@ -161,24 +161,6 @@ module.exports = CollaboratorsHandler = transferProjects: (from_user_id, to_user_id, callback=(err, projects) ->) -> MEMBER_KEYS = ['collaberator_refs', 'readOnly_refs'] - # jobs = [] - # project_ids = [] - # jobs.push (cb) -> - # Project.find { owner_ref: from_user_id }, { _id: 1 }, (error, projects = []) -> - # return callback(error) if error? - # project_ids = project_ids.concat(projects.map (p) -> p._id) - # Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb - - # for key in MEMBER_KEYS - # do (key) -> - # jobs.push (cb) -> - # query = {} - # query[] - # Project.find { owner_ref: from_user_id }, { _id: 1 }, (error, projects = []) -> - # return callback(error) if error? - # project_ids = project_ids.concat(projects.map (p) -> p._id) - # Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb - # Find all the projects this user is part of so we can flush them to TPDS query = $or: From 9eec24535873996db00cb2c63fb470ea4035716f Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 9 Oct 2017 14:17:28 +0100 Subject: [PATCH 53/99] allow docupdater to flush docs in background --- .../web/app/coffee/Features/Compile/ClsiManager.coffee | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 46cb4e35e3..d5f9b2e16c 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -146,13 +146,8 @@ module.exports = ClsiManager = logger.log project_id: project_id, projectStateHash: projectStateHash, docs: docUpdaterDocs?, "checked project state" # see if we can send an incremental update to the CLSI if docUpdaterDocs? and (options.syncType isnt "full") and not error? - # Workaround: for now, always flush project to mongo on compile - # until we have automatic periodic flushing on the docupdater - # side, to prevent documents staying in redis too long. - DocumentUpdaterHandler.flushProjectToMongo project_id, (error) -> - return callback(error) if error? - Metrics.inc "compile-from-redis" - ClsiManager._buildRequestFromDocupdater project_id, options, project, projectStateHash, docUpdaterDocs, callback + Metrics.inc "compile-from-redis" + ClsiManager._buildRequestFromDocupdater project_id, options, project, projectStateHash, docUpdaterDocs, callback else Metrics.inc "compile-from-mongo" ClsiManager._buildRequestFromMongo project_id, options, project, projectStateHash, callback From 8c9ad69dfe967344377d16de333a1b4f4be3c085 Mon Sep 17 00:00:00 2001 From: James Allen Date: Mon, 9 Oct 2017 14:22:04 +0100 Subject: [PATCH 54/99] Always npm install translations from master --- services/web/Jenkinsfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 5c7b4e160f..714adc5f3d 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -60,6 +60,9 @@ pipeline { sh 'mv app/views/external/googlebdb0f8f7f4a17241.html public/googlebdb0f8f7f4a17241.html' sh 'npm install' sh 'npm rebuild' + // It's too easy to end shrinkwrapping to a local, outdated version of translations. + // Ensure translations are always latest, regardless of shrinkwrap + sh 'npm install git+https://github.com/sharelatex/translations-sharelatex.git#master' sh 'npm install --quiet grunt' sh 'npm install --quiet grunt-cli' sh 'ls -l node_modules/.bin' From 24dd89bc3861e943f0add5bc1cbc3b6c962584b9 Mon Sep 17 00:00:00 2001 From: James Allen Date: Mon, 9 Oct 2017 14:23:05 +0100 Subject: [PATCH 55/99] Adjust wording --- services/web/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 714adc5f3d..50ced29d60 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -60,7 +60,7 @@ pipeline { sh 'mv app/views/external/googlebdb0f8f7f4a17241.html public/googlebdb0f8f7f4a17241.html' sh 'npm install' sh 'npm rebuild' - // It's too easy to end shrinkwrapping to a local, outdated version of translations. + // It's too easy to end up shrinkwrapping to an outdated version of translations. // Ensure translations are always latest, regardless of shrinkwrap sh 'npm install git+https://github.com/sharelatex/translations-sharelatex.git#master' sh 'npm install --quiet grunt' From 15e2deed7321a1edcb3410a5d317cb25a0f143a2 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 9 Oct 2017 15:18:55 +0100 Subject: [PATCH 56/99] rename isAutoCompile and isBackgroundAutoCompile changed to isAutoCompileOnLoad and isAutoCompileOnChange --- .../coffee/ide/pdf/controllers/PdfController.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index e77d4a22cb..bb27057fc7 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -68,7 +68,7 @@ define [ $scope.$on "project:joined", () -> return if !autoCompile autoCompile = false - $scope.recompile(isAutoCompile: true) + $scope.recompile(isAutoCompileOnLoad: true) $scope.hasPremiumCompile = $scope.project.features.compileGroup == "priority" $scope.$on "pdf:error:display", () -> @@ -86,7 +86,7 @@ define [ if isTimeNonMonotonic || timeSinceLastCompile >= AUTO_COMPILE_TIMEOUT if (!ide.$scope.hasLintingError) - $scope.recompile(isBackgroundAutoCompile: true) + $scope.recompile(isAutoCompileOnChange: true) else # Extend remainder of timeout autoCompileTimeout = setTimeout () -> @@ -127,7 +127,7 @@ define [ sendCompileRequest = (options = {}) -> url = "/project/#{$scope.project_id}/compile" params = {} - if options.isAutoCompile or options.isBackgroundAutoCompile + if options.isAutoCompileOnLoad or options.isAutoCompileOnChange params["auto_compile"]=true # if the previous run was a check, clear the error logs $scope.pdf.logEntries = [] if $scope.check @@ -207,7 +207,7 @@ define [ $scope.shouldShowLogs = true fetchLogs(fileByPath) else if response.status == "autocompile-backoff" - if $scope.pdf.isAutoCompile # initial autocompile + if $scope.pdf.isAutoCompileOnLoad # initial autocompile $scope.pdf.view = 'uncompiled' else # background autocompile from typing $scope.pdf.view = 'errors' @@ -422,7 +422,7 @@ define [ event_tracking.sendMBSampled "editor-recompile-sampled", options $scope.pdf.compiling = true - $scope.pdf.isAutoCompile = options?.isAutoCompile # initial autocompile + $scope.pdf.isAutoCompileOnLoad = options?.isAutoCompileOnLoad # initial autocompile if options?.force # for forced compile, turn off validation check and ignore errors From ea896380106b51c6ef45f401fb9f314d8fca28b9 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 9 Oct 2017 15:21:01 +0100 Subject: [PATCH 57/99] rename autocompile_disabled to autoCompileDisabled for consistency --- services/web/app/views/project/editor/pdf.pug | 2 +- .../public/coffee/ide/pdf/controllers/PdfController.coffee | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 02531e9584..f48171c7d0 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -392,7 +392,7 @@ div.full-size.pdf(ng-controller="PdfController") ) #{translate("start_free_trial")} - .alert.alert-danger(ng-show="pdf.autocompile_disabled") + .alert.alert-danger(ng-show="pdf.autoCompileDisabled") p strong #{translate("autocompile_disabled")}. span #{translate("autocompile_disabled_reason")} diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index bb27057fc7..2eb1a59eb2 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -168,7 +168,7 @@ define [ $scope.pdf.compileExited = false $scope.pdf.failedCheck = false $scope.pdf.compileInProgress = false - $scope.pdf.autocompile_disabled = false + $scope.pdf.autoCompileDisabled = false # make a cache to look up files by name fileByPath = {} @@ -211,7 +211,7 @@ define [ $scope.pdf.view = 'uncompiled' else # background autocompile from typing $scope.pdf.view = 'errors' - $scope.pdf.autocompile_disabled = true + $scope.pdf.autoCompileDisabled = true $scope.autocompile_enabled = false # disable any further autocompiles event_tracking.sendMB "autocompile-rate-limited", {hasPremiumCompile: $scope.hasPremiumCompile} else if response.status == "project-too-large" From 5b0d3d1429cfc369bd6bcd1d0f21ac8f46645c7f Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 9 Oct 2017 16:31:01 +0100 Subject: [PATCH 58/99] simplify rate-limit checking code --- .../Features/Compile/CompileManager.coffee | 47 ++++++------------- services/web/config/settings.defaults.coffee | 5 ++ .../coffee/Compile/CompileManagerTests.coffee | 16 +++---- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index 756222121a..9e50b280e2 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -18,7 +18,7 @@ module.exports = CompileManager = timer.done() _callback(args...) - @_checkIfAutoCompileLimitHasBeenHit options.isAutoCompile, (err, canCompile)-> + @_checkIfAutoCompileLimitHasBeenHit options.isAutoCompile, "everyone", (err, canCompile)-> if !canCompile return callback null, "autocompile-backoff", [] logger.log project_id: project_id, user_id: user_id, "compiling project" @@ -34,8 +34,8 @@ module.exports = CompileManager = return callback(error) if error? for key, value of limits options[key] = value - # Put a lower limit on autocompiles for free users - CompileManager._checkIfFreeAutoCompileLimitHasBeenHit options.isAutoCompile, limits.compileGroup, (err, canCompile)-> + # Put a lower limit on autocompiles for free users, based on compileGroup + CompileManager._checkCompileGroupAutoCompileLimit options.isAutoCompile, limits.compileGroup, (err, canCompile)-> if !canCompile return callback null, "autocompile-backoff", [] # only pass user_id down to clsi if this is a per-user compile @@ -76,44 +76,27 @@ module.exports = CompileManager = else return callback null, true - _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, callback = (err, canCompile)->)-> + _checkCompileGroupAutoCompileLimit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> + if compileGroup is "default" + CompileManager._checkIfAutoCompileLimitHasBeenHit isAutoCompile, compileGroup, callback + else + Metrics.inc "auto-compile-#{compileGroup}" + return callback(null, true) # always allow priority group users to compile + + _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> if !isAutoCompile return callback(null, true) - Metrics.inc "auto-compile" + Metrics.inc "auto-compile-#{compileGroup}" opts = endpointName:"auto_compile" timeInterval:20 - subjectName:"everyone" - throttle: 200 + subjectName:compileGroup + throttle: Settings?.rateLimit?.autoCompile?[compileGroup] || 25 rateLimiter.addCount opts, (err, canCompile)-> if err? canCompile = false - logger.log canCompile:canCompile, opts:opts, "checking if auto compile limit has been hit" if !canCompile - Metrics.inc "auto-compile-rate-limited" - callback err, canCompile - - - _checkIfFreeAutoCompileLimitHasBeenHit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> - if !isAutoCompile - return callback(null, true) - - if compileGroup is "priority" - Metrics.inc "auto-compile-priority" - return callback(null, true) - - Metrics.inc "auto-compile-free" - opts = - endpointName:"auto_compile" - timeInterval:20 - subjectName:"free" - throttle: 100 - rateLimiter.addCount opts, (err, canCompile)-> - if err? - canCompile = false - logger.log canCompile:canCompile, opts:opts, "checking if free users auto compile limit has been hit" - if !canCompile - Metrics.inc "auto-compile-free-rate-limited" + Metrics.inc "auto-compile-#{compileGroup}-limited" callback err, canCompile _ensureRootDocumentIsSet: (project_id, callback = (error) ->) -> diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 2456590709..94e9ae5007 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -437,3 +437,8 @@ module.exports = settings = # name : "all projects", # url: "/templates/all" #}] + + rateLimits: + autoCompile: + everyone: 100 + standard: 25 diff --git a/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee index 21327a50c9..195da8b850 100644 --- a/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/CompileManagerTests.coffee @@ -44,7 +44,7 @@ describe "CompileManager", -> describe "succesfully", -> beforeEach -> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = (_, cb)-> cb(null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = (isAutoCompile, compileGroup, cb)-> cb(null, true) @CompileManager.compile @project_id, @user_id, {}, @callback it "should check the project has not been recently compiled", -> @@ -84,7 +84,7 @@ describe "CompileManager", -> describe "when the project has been recently compiled", -> it "should return", (done)-> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = (_, cb)-> cb(null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = (isAutoCompile, compileGroup, cb)-> cb(null, true) @CompileManager._checkIfRecentlyCompiled = sinon.stub().callsArgWith(2, null, true) @CompileManager.compile @project_id, @user_id, {}, (err, status)-> status.should.equal "too-recently-compiled" @@ -92,7 +92,7 @@ describe "CompileManager", -> describe "should check the rate limit", -> it "should return", (done)-> - @CompileManager._checkIfAutoCompileLimitHasBeenHit = sinon.stub().callsArgWith(1, null, false) + @CompileManager._checkIfAutoCompileLimitHasBeenHit = sinon.stub().callsArgWith(2, null, false) @CompileManager.compile @project_id, @user_id, {}, (err, status)-> status.should.equal "autocompile-backoff" done() @@ -222,14 +222,14 @@ describe "CompileManager", -> describe "_checkIfAutoCompileLimitHasBeenHit", -> it "should be able to compile if it is not an autocompile", (done)-> - @ratelimiter.addCount.callsArgWith(1, null, true) - @CompileManager._checkIfAutoCompileLimitHasBeenHit false, (err, canCompile)=> + @ratelimiter.addCount.callsArgWith(2, null, true) + @CompileManager._checkIfAutoCompileLimitHasBeenHit false, "everyone", (err, canCompile)=> canCompile.should.equal true done() it "should be able to compile if rate limit has remianing", (done)-> @ratelimiter.addCount.callsArgWith(1, null, true) - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> args = @ratelimiter.addCount.args[0][0] args.throttle.should.equal 25 args.subjectName.should.equal "everyone" @@ -240,13 +240,13 @@ describe "CompileManager", -> it "should be not able to compile if rate limit has no remianing", (done)-> @ratelimiter.addCount.callsArgWith(1, null, false) - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> canCompile.should.equal false done() it "should return false if there is an error in the rate limit", (done)-> @ratelimiter.addCount.callsArgWith(1, "error") - @CompileManager._checkIfAutoCompileLimitHasBeenHit true, (err, canCompile)=> + @CompileManager._checkIfAutoCompileLimitHasBeenHit true, "everyone", (err, canCompile)=> canCompile.should.equal false done() From f017a94b7ebb5afe409716ef40d94262f9cfe465 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 11 Oct 2017 11:18:20 +0100 Subject: [PATCH 59/99] remove unused HistoryManager --- .../Features/History/HistoryManager.coffee | 28 --------- .../coffee/History/HistoryManagerTests.coffee | 63 ------------------- 2 files changed, 91 deletions(-) delete mode 100644 services/web/app/coffee/Features/History/HistoryManager.coffee delete mode 100644 services/web/test/UnitTests/coffee/History/HistoryManagerTests.coffee diff --git a/services/web/app/coffee/Features/History/HistoryManager.coffee b/services/web/app/coffee/Features/History/HistoryManager.coffee deleted file mode 100644 index ea3f492613..0000000000 --- a/services/web/app/coffee/Features/History/HistoryManager.coffee +++ /dev/null @@ -1,28 +0,0 @@ -settings = require "settings-sharelatex" -request = require "request" -logger = require "logger-sharelatex" - -module.exports = HistoryManager = - flushProject: (project_id, callback = (error) ->) -> - logger.log project_id: project_id, "flushing project in track-changes api" - url = "#{settings.apis.trackchanges.url}/project/#{project_id}/flush" - request.post url, (error, res, body) -> - return callback(error) if error? - if 200 <= res.statusCode < 300 - callback(null) - else - error = new Error("track-changes api responded with non-success code: #{res.statusCode} #{url}") - logger.error err: error, project_id: project_id, "error flushing project in track-changes api" - callback(error) - - archiveProject: (project_id, callback = ()->)-> - logger.log project_id: project_id, "archving project in track-changes api" - url = "#{settings.apis.trackchanges.url}/project/#{project_id}/archive" - request.post url, (error, res, body) -> - return callback(error) if error? - if 200 <= res.statusCode < 300 - callback(null) - else - error = new Error("track-changes api responded with non-success code: #{res.statusCode} #{url}") - logger.error err: error, project_id: project_id, "error archving project in track-changes api" - callback(error) \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/History/HistoryManagerTests.coffee b/services/web/test/UnitTests/coffee/History/HistoryManagerTests.coffee deleted file mode 100644 index 65b22812ea..0000000000 --- a/services/web/test/UnitTests/coffee/History/HistoryManagerTests.coffee +++ /dev/null @@ -1,63 +0,0 @@ -chai = require('chai') -expect = chai.expect -chai.should() -sinon = require("sinon") -modulePath = "../../../../app/js/Features/History/HistoryManager" -SandboxedModule = require('sandboxed-module') - -describe "HistoryManager", -> - beforeEach -> - @HistoryManager = SandboxedModule.require modulePath, requires: - "request" : @request = sinon.stub() - "settings-sharelatex": @settings = - apis: - trackchanges: - url: "trackchanges.sharelatex.com" - "logger-sharelatex": @logger = {log: sinon.stub(), error: sinon.stub()} - @project_id = "project-id-123" - @callback = sinon.stub() - @request.post = sinon.stub() - - describe "flushProject", -> - describe "with a successful response code", -> - beforeEach -> - @request.post = sinon.stub().callsArgWith(1, null, statusCode: 204, "") - @HistoryManager.flushProject @project_id, @callback - - it "should flush the project in the track changes api", -> - @request.post - .calledWith("#{@settings.apis.trackchanges.url}/project/#{@project_id}/flush") - .should.equal true - - it "should call the callback without an error", -> - @callback.calledWith(null).should.equal true - - describe "with a failed response code", -> - beforeEach -> - @request.post = sinon.stub().callsArgWith(1, null, statusCode: 500, "") - @HistoryManager.flushProject @project_id, @callback - - it "should call the callback with an error", -> - @callback.calledWith(new Error("track-changes api responded with a non-success code: 500")).should.equal true - - it "should log the error", -> - @logger.error - .calledWith({ - err: new Error("track-changes api responded with a non-success code: 500") - project_id: @project_id - }, "error flushing project in track-changes api") - .should.equal true - - describe "ArchiveProject", -> - - it "should call the post endpoint", (done)-> - @request.post.callsArgWith(1, null, {}) - @HistoryManager.archiveProject @project_id, (err)=> - @request.post.calledWith("#{@settings.apis.trackchanges.url}/project/#{@project_id}/archive") - done() - - it "should return an error on a non success", (done)-> - @request.post.callsArgWith(1, null, {statusCode:500}) - @HistoryManager.archiveProject @project_id, (err)=> - expect(err).to.exist - done() \ No newline at end of file From 5047213c3c6e261db08f1fec5e38d0b6f5802b6e Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Wed, 11 Oct 2017 14:47:39 +0100 Subject: [PATCH 60/99] Change rollout detection to account for changes in proportion preserving rolled out users --- .../web/app/coffee/Features/Project/ProjectController.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 89b47b5782..5915fef8fd 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -257,7 +257,8 @@ module.exports = ProjectController = timestamp = parseInt(user_id.toString().substring(0, 8), 16) counter = parseInt(user_id.toString().substring(18, 24), 16) - if counter % 5000 != 0 + rolloutProportion = 10 + if counter % 1000 < rolloutProportion # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) From 38b3626014186ef5b0f50797bf4fc91c7314fc7a Mon Sep 17 00:00:00 2001 From: Joe Green Date: Wed, 11 Oct 2017 15:21:21 +0100 Subject: [PATCH 61/99] Try email only on master branch (#47) --- services/web/Jenkinsfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 50ced29d60..2da3a825f7 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -160,6 +160,10 @@ pipeline { post { failure { + when { + branch 'master' + } + mail(from: "${EMAIL_ALERT_FROM}", to: "${EMAIL_ALERT_TO}", subject: "Jenkins build failed: ${JOB_NAME}:${BUILD_NUMBER}", From cf25ff058ffa1ca8b0fb31a01758e8a60f2c2a2c Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Wed, 11 Oct 2017 15:50:21 +0100 Subject: [PATCH 62/99] use new endpoint docupdater get_and_flush_if_old --- .../Features/DocumentUpdater/DocumentUpdaterHandler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index 466152924e..e806ddf8dd 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -128,9 +128,9 @@ module.exports = DocumentUpdaterHandler = # docs from redis via the docupdater. Otherwise we will need to # fall back to getting them from mongo. timer = new metrics.Timer("get-project-docs") - url = "#{settings.apis.documentupdater.url}/project/#{project_id}/doc?state=#{projectStateHash}" + url = "#{settings.apis.documentupdater.url}/project/#{project_id}/get_and_flush_if_old?state=#{projectStateHash}" logger.log project_id:project_id, "getting project docs from document updater" - request.get url, (error, res, body)-> + request.post url, (error, res, body)-> timer.done() if error? logger.error err:error, url:url, project_id:project_id, "error getting project docs from doc updater" From fdffc92de214c7f36df4d3dbcd5038ed25e7b286 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 12 Oct 2017 15:01:11 +0100 Subject: [PATCH 63/99] fix unit tests --- .../coffee/Compile/ClsiManagerTests.coffee | 6 +++--- .../DocumentUpdaterHandlerTests.coffee | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee index 32deed5522..59c3e3d018 100644 --- a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee @@ -247,12 +247,12 @@ describe "ClsiManager", -> .calledWith(@project_id, {compiler:1, rootDoc_id: 1, imageName: 1, rootFolder: 1}) .should.equal true - it "should flush the project to the database", -> + it "should not explicitly flush the project to the database", -> @DocumentUpdaterHandler.flushProjectToMongo .calledWith(@project_id) - .should.equal true + .should.equal false - it "should get only the live docs from the docupdater", -> + it "should get only the live docs from the docupdater with a background flush in docupdater", -> @DocumentUpdaterHandler.getProjectDocsIfMatch .calledWith(@project_id) .should.equal true diff --git a/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index b2cbeeba16..d7e88a6615 100644 --- a/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -265,19 +265,19 @@ describe 'DocumentUpdaterHandler', -> v: @version @docs = [ @doc0, @doc0, @doc0 ] @body = JSON.stringify @docs - @request.get = sinon.stub().callsArgWith(1, null, {statusCode: 200}, @body) + @request.post = sinon.stub().callsArgWith(1, null, {statusCode: 200}, @body) @handler.getProjectDocsIfMatch @project_id, @project_state_hash, @callback it 'should get the documenst from the document updater', -> - url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}/doc?state=#{@project_state_hash}" - @request.get.calledWith(url).should.equal true + url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}/get_and_flush_if_old?state=#{@project_state_hash}" + @request.post.calledWith(url).should.equal true it "should call the callback with the documents", -> @callback.calledWithExactly(null, @docs).should.equal true describe "when the document updater API returns an error", -> beforeEach -> - @request.get = sinon.stub().callsArgWith(1, @error = new Error("something went wrong"), null, null) + @request.post = sinon.stub().callsArgWith(1, @error = new Error("something went wrong"), null, null) @handler.getProjectDocsIfMatch @project_id, @project_state_hash, @callback it "should return an error to the callback", -> @@ -285,7 +285,7 @@ describe 'DocumentUpdaterHandler', -> describe "when the document updater returns a conflict error code", -> beforeEach -> - @request.get = sinon.stub().callsArgWith(1, null, { statusCode: 409 }, "Conflict") + @request.post = sinon.stub().callsArgWith(1, null, { statusCode: 409 }, "Conflict") @handler.getProjectDocsIfMatch @project_id, @project_state_hash, @callback it "should return the callback with no documents", -> @@ -312,7 +312,7 @@ describe 'DocumentUpdaterHandler', -> describe "when the document updater API returns an error", -> beforeEach -> - @request.get = sinon.stub().callsArgWith(1, @error = new Error("something went wrong"), null, null) + @request.post = sinon.stub().callsArgWith(1, @error = new Error("something went wrong"), null, null) @handler.getProjectDocsIfMatch @project_id, @project_state_hash, @callback it "should return an error to the callback", -> @@ -320,7 +320,7 @@ describe 'DocumentUpdaterHandler', -> describe "when the document updater returns a conflict error code", -> beforeEach -> - @request.get = sinon.stub().callsArgWith(1, null, { statusCode: 409 }, "Conflict") + @request.post = sinon.stub().callsArgWith(1, null, { statusCode: 409 }, "Conflict") @handler.getProjectDocsIfMatch @project_id, @project_state_hash, @callback it "should return the callback with no documents", -> From 8cf328818715ba7963eb6c121ef82c559b2e2aa0 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 12 Oct 2017 16:03:12 +0100 Subject: [PATCH 64/99] avoid exception in validateProjectName --- .../coffee/Features/Project/ProjectDetailsHandler.coffee | 2 +- .../coffee/Project/ProjectDetailsHandlerTests.coffee | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee index 5819e03472..09783c58c7 100644 --- a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee @@ -57,7 +57,7 @@ module.exports = ProjectDetailsHandler = MAX_PROJECT_NAME_LENGTH: 150 validateProjectName: (name, callback = (error) ->) -> - if name.length == 0 + if !name? or name.length == 0 return callback(new Errors.InvalidNameError("Project name cannot be blank")) else if name.length > @MAX_PROJECT_NAME_LENGTH return callback(new Errors.InvalidNameError("Project name is too long")) diff --git a/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee index abb0b505d0..8d2973e235 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee @@ -126,6 +126,12 @@ describe 'ProjectDetailsHandler', -> done() describe "validateProjectName", -> + + it "should reject undefined names", (done) -> + @handler.validateProjectName undefined, (error) -> + expect(error).to.exist + done() + it "should reject empty names", (done) -> @handler.validateProjectName "", (error) -> expect(error).to.exist From fc3ecddd0e6b8a406be9b6de3f0de2771be30f87 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 12 Oct 2017 16:18:14 +0100 Subject: [PATCH 65/99] fix two bugs in auto compile limit logic 1. the compileGroup is "standard" not default 2. was not excluding normal compiles from metrics --- .../web/app/coffee/Features/Compile/CompileManager.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index 9e50b280e2..f18dc56c7b 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -77,7 +77,10 @@ module.exports = CompileManager = return callback null, true _checkCompileGroupAutoCompileLimit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> - if compileGroup is "default" + if !isAutoCompile + return callback(null, true) + if compileGroup is "standard" + # apply extra limits to the standard compile group CompileManager._checkIfAutoCompileLimitHasBeenHit isAutoCompile, compileGroup, callback else Metrics.inc "auto-compile-#{compileGroup}" From 36e1fafb60da85cc3ce636e6e5bbeadc9fbd434e Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 12 Oct 2017 17:10:41 +0100 Subject: [PATCH 66/99] Set proportion to 0 --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 5915fef8fd..e7c9ac9bc9 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -257,7 +257,7 @@ module.exports = ProjectController = timestamp = parseInt(user_id.toString().substring(0, 8), 16) counter = parseInt(user_id.toString().substring(18, 24), 16) - rolloutProportion = 10 + rolloutProportion = 0 if counter % 1000 < rolloutProportion # Don't show if user is not part of roll out return cb(null, false) From d5fba2cc7115eafc715c7ad0d01f319715fcb925 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Fri, 13 Oct 2017 08:23:16 +0100 Subject: [PATCH 67/99] enable incremental compiles for all users --- .../public/coffee/ide/pdf/controllers/PdfController.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index b4cf9f6358..f244b55204 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -144,9 +144,9 @@ define [ rootDoc_id: options.rootDocOverride_id or null draft: $scope.draft check: checkType - # use incremental compile for beta users but revert to a full + # use incremental compile for all users but revert to a full # compile if there is a server error - incrementalCompilesEnabled: window.user?.betaProgram and not $scope.pdf.error + incrementalCompilesEnabled: not $scope.pdf.error _csrf: window.csrfToken }, {params: params} From 2efb6b69e5014a5c16fe669ea90fb6179e72cebd Mon Sep 17 00:00:00 2001 From: Nate Stemen Date: Fri, 13 Oct 2017 17:42:10 +0100 Subject: [PATCH 68/99] removing comment --- .../aceEditor/auto-complete/PackageManager.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee index ac30d5a431..c0e1cf5e8f 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee @@ -23,7 +23,7 @@ define () -> packageSnippets = for pkg in packages { caption: "\\usepackage{#{pkg}}" - snippet: """\\usepackage{#{pkg}}""" + snippet: "\\usepackage{#{pkg}}" meta: "pkg" } @@ -31,14 +31,13 @@ define () -> caption: "\\usepackage{}" snippet: "\\usepackage{}" meta: "pkg" - score: 70 + score: 55 } class PackageManager getCompletions: (editor, session, pos, prefix, callback) -> docText = session.getValue() - loaded = parseLoadedPackages(docText) - # console.log loaded + loaded = parseLoadedPackages docText callback null, packageSnippets return PackageManager From 6c3ceb48df33ceeb75935e20745e4986431e2fc1 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 10:25:52 +0100 Subject: [PATCH 69/99] Allow onboarding to be shown outside of beta program --- services/web/public/coffee/ide.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index 4aaaecc53b..0a83a2dbab 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -78,7 +78,7 @@ define [ miniReviewPanelVisible: false, } $scope.onboarding = { - autoCompile: if window.user.betaProgram and window.showAutoCompileOnboarding then 'unseen' else 'dismissed' + autoCompile: if window.showAutoCompileOnboarding then 'unseen' else 'dismissed' } $scope.user = window.user From e02c3bbb09798b702f990e43490bea1ab3dd68b4 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 10:27:33 +0100 Subject: [PATCH 70/99] Remove beta program badge --- services/web/app/views/project/editor/editor.pug | 4 +--- services/web/app/views/project/editor/pdf.pug | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 89ec5c7828..86cc63a5e5 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -101,9 +101,7 @@ div.full-size( ng-class="placement" ) .popover-inner - h3.popover-title - | #{translate("auto_compile")} - span.beta-feature-badge + h3.popover-title #{translate("auto_compile")} .popover-content p #{translate("try_out_auto_compile_setting")} img(src="/img/onboarding/autocompile/setting-dropdown.png" width="100%") diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 2e0bc3701f..43416b8991 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -26,11 +26,9 @@ div.full-size.pdf(ng-controller="PdfController") ) span.caret ul.dropdown-menu.dropdown-menu-left - // Only show on beta program? + // Only show if on beta program or part of rollout if user.betaProgram || showAutoCompileOnboarding - li.dropdown-header - | #{translate("auto_compile")} - span.beta-feature-badge + li.dropdown-header #{translate("auto_compile")} li a(href, ng-click="autocompile_enabled = true") i.fa.fa-fw(ng-class="{'fa-check': autocompile_enabled}") From 625f52c24877613c8a2679e20c2642eaeb7b22b1 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 10:28:42 +0100 Subject: [PATCH 71/99] Update cutoff date --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index e7c9ac9bc9..205ac0d718 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -262,7 +262,7 @@ module.exports = ProjectController = # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) - if userSignupDate > new Date("2017-10-03") + if userSignupDate > new Date("2017-10-16") # Don't show for users who registered after it was released return cb(null, false) timeout = setTimeout cb, 500 From bd6bc42a9a36ec4b9a83966e27056bb3f1aa2943 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 11:42:15 +0100 Subject: [PATCH 72/99] Don't Show autocompile on load --- .../web/public/coffee/ide/pdf/controllers/PdfController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index ce2c3eec05..640c224e7b 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -419,7 +419,7 @@ define [ $scope.recompile = (options = {}) -> return if $scope.pdf.compiling - if !options.isAutoCompile and $scope.onboarding.autoCompile == 'unseen' + if !options.isAutoCompileOnLoad and $scope.onboarding.autoCompile == 'unseen' $scope.onboarding.autoCompile = 'show' event_tracking.sendMBSampled "editor-recompile-sampled", options From abb21ac96b371b34888704873e5be3e6fbf32d99 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 12:44:11 +0100 Subject: [PATCH 73/99] Fix autocompile rollout logic --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 205ac0d718..63478f385d 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -258,7 +258,7 @@ module.exports = ProjectController = counter = parseInt(user_id.toString().substring(18, 24), 16) rolloutProportion = 0 - if counter % 1000 < rolloutProportion + if counter % 1000 > rolloutProportion # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) From 60c297eac88cdf0f94e710b87ae753fdd8e8e527 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 16 Oct 2017 13:40:09 +0100 Subject: [PATCH 74/99] Also prevent rollout to modulo 0 users --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 63478f385d..68d2c49bca 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -258,7 +258,7 @@ module.exports = ProjectController = counter = parseInt(user_id.toString().substring(18, 24), 16) rolloutProportion = 0 - if counter % 1000 > rolloutProportion + if counter % 1000 >= rolloutProportion # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) From 67b13d2583054b06d5f648a2ada1fdad52b7ecda Mon Sep 17 00:00:00 2001 From: Joe Green Date: Mon, 16 Oct 2017 14:07:49 +0100 Subject: [PATCH 75/99] Update Jenkinsfile --- services/web/Jenkinsfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/services/web/Jenkinsfile b/services/web/Jenkinsfile index 2da3a825f7..50ced29d60 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -160,10 +160,6 @@ pipeline { post { failure { - when { - branch 'master' - } - mail(from: "${EMAIL_ALERT_FROM}", to: "${EMAIL_ALERT_TO}", subject: "Jenkins build failed: ${JOB_NAME}:${BUILD_NUMBER}", From d6d76f132eb1e6a760db35fee066325c63fb7f1e Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Fri, 13 Oct 2017 16:49:22 +0100 Subject: [PATCH 76/99] replace unzip with yauzl --- .../Features/Uploads/ArchiveManager.coffee | 130 +- services/web/npm-shrinkwrap.json | 5631 ++++++++++++----- services/web/package.json | 4 +- 3 files changed, 4013 insertions(+), 1752 deletions(-) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index a7f0ccdbeb..b71b5cd2bc 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -3,54 +3,96 @@ logger = require "logger-sharelatex" metrics = require "metrics-sharelatex" fs = require "fs" Path = require "path" +fse = require "fs-extra" +yauzl = require "yauzl" +Settings = require "settings-sharelatex" _ = require("underscore") ONE_MEG = 1024 * 1024 module.exports = ArchiveManager = - _isZipTooLarge: (source, callback = (err, isTooLarge)->)-> callback = _.once callback - unzip = child.spawn("unzip", ["-l", source]) + totalSizeInBytes = 0 + yauzl.open source, {lazyEntries: true}, (err, zipfile) -> + return callback(err) if err? - output = "" - unzip.stdout.on "data", (d)-> - output += d + if Settings.maxEntitiesPerProject? and zipfile.entryCount > Settings.maxEntitiesPerProject + return callback(null, true) # too many files in zip file - error = null - unzip.stderr.on "data", (chunk) -> - error ||= "" - error += chunk + zipfile.on "error", callback - unzip.on "error", (err) -> - logger.error {err, source}, "unzip failed" - if err.code == "ENOENT" - logger.error "unzip command not found. Please check the unzip command is installed" - callback(err) + # read all the entries + zipfile.readEntry() + zipfile.on "entry", (entry) -> + totalSizeInBytes += entry.uncompressedSize + zipfile.readEntry() # get the next entry - unzip.on "close", (exitCode) -> - if error? - error = new Error(error) - logger.warn err:error, source: source, "error checking zip size" + # no more entries to read + zipfile.on "end", () -> + if !totalSizeInBytes? or isNaN(totalSizeInBytes) + logger.err source:source, totalSizeInBytes:totalSizeInBytes, "error getting bytes of zip" + return callback(new Error("error getting bytes of zip")) + isTooLarge = totalSizeInBytes > (ONE_MEG * 300) + callback(null, isTooLarge) - lines = output.split("\n") - lastLine = lines[lines.length - 2]?.trim() - totalSizeInBytes = lastLine?.split(" ")?[0] + _checkFilePath: (entry, destination, callback = (err, destFile) ->) -> + # check if the entry is a directory + if /\/$/.test(entry.fileName) + return callback() # don't give a destfile for directory + # check that the file does not use a relative path + for dir in entry.fileName.split('/') + if dir == '..' + return callback(new Error("relative path")) + # check that the destination file path is normalized + dest = "#{destination}/#{entry.fileName}" + if dest != Path.normalize(dest) + return callback(new Error("unnormalized path")) + else + return callback(null, dest) - totalSizeInBytesAsInt = parseInt(totalSizeInBytes) + _writeFileEntry: (zipfile, entry, destFile, callback = (err)->) -> + callback = _.once callback - if !totalSizeInBytesAsInt? or isNaN(totalSizeInBytesAsInt) - logger.err source:source, totalSizeInBytes:totalSizeInBytes, totalSizeInBytesAsInt:totalSizeInBytesAsInt, lastLine:lastLine, exitCode:exitCode, "error getting bytes of zip" - return callback(new Error("error getting bytes of zip")) + zipfile.openReadStream entry, (err, readStream) -> + return callback(err) if err? + readStream.on "error", callback + readStream.on "end", callback - isTooLarge = totalSizeInBytes > (ONE_MEG * 300) + fse.ensureDir Path.dirname(destFile), (err) -> + return callback(err) if err? + writeStream = fs.createWriteStream destFile + writeStream.on 'error', (err) -> + return callback(err) + readStream.pipe(writeStream) - callback(error, isTooLarge) + _extractZipFiles: (source, destination, callback = (err) ->) -> + callback = _.once callback + yauzl.open source, {lazyEntries: true}, (err, zipfile) -> + return callback(err) if err? + zipfile.on "error", callback + # read all the entries + zipfile.readEntry() + zipfile.on "entry", (entry) -> + ArchiveManager._checkFilePath entry, destination, (err, destFile) -> + if err? + logger.warn err:err, source:source, destination:destination, "skipping bad file path" + zipfile.readEntry() # bad path, just skip to the next file + return + if destFile? # only write files + ArchiveManager._writeFileEntry zipfile, entry, destFile, (err) -> + if err? + logger.error err:err, source:source, destFile:destFile, "error unzipping file entry" + zipfile.close() # bail out, stop reading file entries + return callback(err) + else + zipfile.readEntry() # continue to the next file + # no more entries to read + zipfile.on "end", callback - extractZipArchive: (source, destination, _callback = (err) ->) -> callback = (args...) -> _callback(args...) @@ -62,36 +104,18 @@ module.exports = ArchiveManager = return callback(err) if isTooLarge - return callback(new Error("zip_too_large")) - + return callback(new Error("zip_too_large")) timer = new metrics.Timer("unzipDirectory") logger.log source: source, destination: destination, "unzipping file" - unzip = child.spawn("unzip", [source, "-d", destination]) + ArchiveManager._extractZipFiles source, destination, (err) -> + if err? + logger.error {err, source, destination}, "unzip failed" + callback(err) + else + callback() - # don't remove this line, some zips need - # us to listen on this for some unknow reason - unzip.stdout.on "data", (d)-> - - error = null - unzip.stderr.on "data", (chunk) -> - error ||= "" - error += chunk - - unzip.on "error", (err) -> - logger.error {err, source, destination}, "unzip failed" - if err.code == "ENOENT" - logger.error "unzip command not found. Please check the unzip command is installed" - callback(err) - - unzip.on "close", () -> - timer.done() - if error? - error = new Error(error) - logger.error err:error, source: source, destination: destination, "error unzipping file" - callback(error) - findTopLevelDirectory: (directory, callback = (error, topLevelDir) ->) -> fs.readdir directory, (error, files) -> return callback(error) if error? diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json index 5c26a8431e..277e022779 100644 --- a/services/web/npm-shrinkwrap.json +++ b/services/web/npm-shrinkwrap.json @@ -1,2305 +1,3244 @@ { "name": "web-sharelatex", "version": "0.1.4", + "lockfileVersion": 1, + "requires": true, "dependencies": { "@types/geojson": { "version": "1.0.3", - "from": "@types/geojson@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.3.tgz", + "integrity": "sha1-+89/pett0QjVE4XMaYfsHyQhRSM=" }, "abbrev": { "version": "1.1.0", - "from": "abbrev@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" }, "accepts": { "version": "1.2.13", - "from": "accepts@>=1.2.9 <1.3.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz" + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.5.3" + } }, "acorn": { "version": "3.3.0", - "from": "acorn@>=3.1.0 <4.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" }, "acorn-globals": { "version": "3.1.0", - "from": "acorn-globals@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "requires": { + "acorn": "4.0.13" + }, "dependencies": { "acorn": { "version": "4.0.13", - "from": "acorn@>=4.0.4 <5.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" } } }, "addressparser": { "version": "0.2.1", - "from": "addressparser@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz", + "integrity": "sha1-0RpbLu2gTP7+vfMZbBCuE9ts1gc=" }, "ajv": { "version": "4.11.8", - "from": "ajv@>=4.9.1 <5.0.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz" + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } }, "align-text": { "version": "0.1.4", - "from": "align-text@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } }, "amdefine": { "version": "1.0.1", - "from": "amdefine@>=0.0.4", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ansi-regex": { "version": "2.1.1", - "from": "ansi-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "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", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "aproba": { "version": "1.1.2", - "from": "aproba@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha1-RcZikJTeTpb2k+9+q3SuB5wkD8E=" }, "archiver": { "version": "0.9.0", - "from": "archiver@0.9.0", "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.9.0.tgz", + "integrity": "sha1-ov0RBXpYi8lPAeXrfNPpN+pNjOU=", + "requires": { + "buffer-crc32": "0.2.13", + "file-utils": "0.1.5", + "lazystream": "0.1.0", + "lodash": "2.4.2", + "readable-stream": "1.0.34", + "tar-stream": "0.3.3", + "zip-stream": "0.3.7" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" } } }, "are-we-there-yet": { "version": "1.1.4", - "from": "are-we-there-yet@>=1.1.2 <1.2.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + }, "dependencies": { "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.3", - "from": "readable-stream@>=2.0.6 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "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" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } } } }, "argparse": { "version": "0.1.16", - "from": "argparse@>=0.1.11 <0.2.0", "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "requires": { + "underscore": "1.7.0", + "underscore.string": "2.4.0" + }, "dependencies": { "underscore": { "version": "1.7.0", - "from": "underscore@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" }, "underscore.string": { "version": "2.4.0", - "from": "underscore.string@>=2.4.0 <2.5.0", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz" + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=" } } }, "array-flatten": { "version": "1.1.0", - "from": "array-flatten@1.1.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.0.tgz", + "integrity": "sha1-rD76xxew57vcd4zgvec4GsZgQ5M=" }, "asap": { "version": "2.0.6", - "from": "asap@>=2.0.3 <2.1.0", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, "asn1": { "version": "0.2.3", - "from": "asn1@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "assert-plus": { "version": "0.2.0", - "from": "assert-plus@>=0.2.0 <0.3.0", - "resolved": "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", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, "assertion-error": { "version": "1.0.2", - "from": "assertion-error@^1.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=" }, "async": { "version": "0.6.2", - "from": "async@0.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.6.2.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.6.2.tgz", + "integrity": "sha1-Qf0DijgSwKi8GELs8IumPrA5K+8=" }, "asynckit": { "version": "0.4.0", - "from": "asynckit@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "autoprefixer": { "version": "6.7.7", - "from": "autoprefixer@>=6.6.1 <7.0.0", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "dev": true + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000740", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.17", + "postcss-value-parser": "3.3.0" + } }, "aws-sdk": { "version": "2.113.0", - "from": "aws-sdk@>=2.2.36 <3.0.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.113.0.tgz", + "integrity": "sha1-j7lfRlToUcdhYDFXx896Qxr2/W0=", + "requires": { + "buffer": "4.9.1", + "crypto-browserify": "1.0.9", + "events": "1.1.1", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.0.1", + "xml2js": "0.4.17", + "xmlbuilder": "4.2.1" + }, "dependencies": { "uuid": { "version": "3.0.1", - "from": "uuid@3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" }, "xml2js": { "version": "0.4.17", - "from": "xml2js@0.4.17", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz" + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "4.2.1" + } } } }, "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" + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" }, "aws4": { "version": "1.6.0", - "from": "aws4@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, "axo": { "version": "0.0.2", - "from": "axo@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/axo/-/axo-0.0.2.tgz" + "resolved": "https://registry.npmjs.org/axo/-/axo-0.0.2.tgz", + "integrity": "sha1-STVfu+qzhEm8ppahqsxGml7p/Uc=" }, "babel-runtime": { "version": "6.3.19", - "from": "babel-runtime@>=6.3.19 <6.4.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.3.19.tgz" + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.3.19.tgz", + "integrity": "sha1-8ttpbDyMN5iB4qU2ZeAhhwdNxoE=", + "requires": { + "core-js": "1.2.7" + } }, "backoff": { "version": "2.5.0", - "from": "backoff@>=2.5.0 <3.0.0", - "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz" + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "requires": { + "precond": "0.2.3" + } }, "balanced-match": { "version": "1.0.0", - "from": "balanced-match@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.2.1", - "from": "base64-js@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=" }, "base64-stream": { "version": "0.1.3", - "from": "base64-stream@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-0.1.3.tgz", + "integrity": "sha1-drA3C3ebuBbRL9QXZKa4Vz61/sM=", + "requires": { + "readable-stream": "2.3.3" + }, "dependencies": { "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.3", - "from": "readable-stream@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "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" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } } } }, "base64url": { "version": "2.0.0", - "from": "base64url@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" }, "basic-auth-connect": { "version": "1.0.0", - "from": "basic-auth-connect@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" }, "bcrypt": { "version": "1.0.1", - "from": "bcrypt@1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.1.tgz", + "integrity": "sha1-RTt6oeBeA/zEi442iGUSOuP8MT8=", + "requires": { + "bindings": "1.2.1", + "nan": "2.3.5", + "node-pre-gyp": "0.6.30" + } }, "bcrypt-pbkdf": { "version": "1.0.1", - "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "optional": true + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } }, "bcryptjs": { "version": "2.3.0", - "from": "bcryptjs@2.3.0", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.3.0.tgz" + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.3.0.tgz", + "integrity": "sha1-WCaQDP73q680JccuTUZN5Qm4wuw=" }, "bindings": { "version": "1.2.1", - "from": "bindings@1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" }, "bl": { "version": "0.6.0", - "from": "bl@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.6.0.tgz" + "resolved": "https://registry.npmjs.org/bl/-/bl-0.6.0.tgz", + "integrity": "sha1-MJECmZNylBM4RO40qkeaU0S0zSk=", + "requires": { + "readable-stream": "1.0.34" + } }, "block-stream": { "version": "0.0.9", - "from": "block-stream@*", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz" + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } }, "bluebird": { "version": "3.5.0", - "from": "bluebird@>=3.3.4 <4.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz" + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" }, "body-parser": { "version": "1.18.0", - "from": "body-parser@>=1.13.1 <2.0.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.0.tgz", + "integrity": "sha1-07Ik1Gf6LOjUNYnAJFBDJnwJNjQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.8", + "depd": "1.1.1", + "http-errors": "1.6.2", + "iconv-lite": "0.4.18", + "on-finished": "2.3.0", + "qs": "6.5.0", + "raw-body": "2.3.1", + "type-is": "1.6.15" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "iconv-lite": { "version": "0.4.18", - "from": "iconv-lite@0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=" }, "qs": { "version": "6.5.0", - "from": "qs@6.5.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "integrity": "sha1-jQSVTTZN7z78VbWgeT4eLIsebkk=" } } }, "boom": { "version": "2.10.1", - "from": "boom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } }, "brace-expansion": { "version": "1.1.8", - "from": "brace-expansion@>=1.1.7 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } }, "broadway": { "version": "0.3.6", - "from": "broadway@>=0.3.2 <0.4.0", "resolved": "https://registry.npmjs.org/broadway/-/broadway-0.3.6.tgz", + "integrity": "sha1-fb7waLlUt5B5Jf1USWO1eKkCuno=", "dev": true, + "requires": { + "cliff": "0.1.9", + "eventemitter2": "0.4.14", + "nconf": "0.6.9", + "utile": "0.2.1", + "winston": "0.8.0" + }, "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, "cliff": { "version": "0.1.9", - "from": "cliff@0.1.9", "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.9.tgz", - "dev": true + "integrity": "sha1-ohHgnGo947oa8n0EnTASUNGIErw=", + "dev": true, + "requires": { + "colors": "0.6.2", + "eyes": "0.1.8", + "winston": "0.8.0" + } }, "winston": { "version": "0.8.0", - "from": "winston@0.8.0", "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.0.tgz", - "dev": true + "integrity": "sha1-YdCDD6aZcGISIGsKK1ymmpMENmg=", + "dev": true, + "requires": { + "async": "0.2.10", + "colors": "0.6.2", + "cycle": "1.0.3", + "eyes": "0.1.8", + "pkginfo": "0.3.1", + "stack-trace": "0.0.9" + } } } }, "browserslist": { "version": "1.7.7", - "from": "browserslist@>=1.7.6 <2.0.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "dev": true + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000740", + "electron-to-chromium": "1.3.24" + } }, "bson": { "version": "1.0.4", - "from": "bson@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", + "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" }, "buffer": { "version": "4.9.1", - "from": "buffer@4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + }, "dependencies": { "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" } } }, "buffer-crc32": { "version": "0.2.13", - "from": "buffer-crc32@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-equal-constant-time": { "version": "1.0.1", - "from": "buffer-equal-constant-time@1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" }, "bufferedstream": { "version": "1.6.0", - "from": "bufferedstream@1.6.0", - "resolved": "https://registry.npmjs.org/bufferedstream/-/bufferedstream-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/bufferedstream/-/bufferedstream-1.6.0.tgz", + "integrity": "sha1-G1a+ZxMhYtn0aLyIbdLJFg3fKII=" }, "buildmail": { "version": "3.3.2", - "from": "buildmail@3.3.2", "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-3.3.2.tgz", + "integrity": "sha1-fJ4pDUKoWAiUrzUoG8xt6D3+Ehw=", + "requires": { + "addressparser": "1.0.0", + "libbase64": "0.1.0", + "libmime": "2.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.2.1", + "nodemailer-shared": "1.0.3" + }, "dependencies": { "addressparser": { "version": "1.0.0", - "from": "addressparser@1.0.0", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.0.tgz", + "integrity": "sha1-ighXVDABSXZoaqG3bgx0xadwKj4=" } } }, "bunyan": { "version": "0.22.1", - "from": "bunyan@0.22.1", - "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-0.22.1.tgz" + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-0.22.1.tgz", + "integrity": "sha1-Agw4O+1iWvXGyINN2MSsoN0Pdlw=", + "requires": { + "dtrace-provider": "0.2.8", + "mv": "0.0.5" + } }, "busboy": { "version": "0.2.14", - "from": "busboy@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.14" + }, "dependencies": { "readable-stream": { "version": "1.1.14", - "from": "readable-stream@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } } } }, "bytes": { "version": "3.0.0", - "from": "bytes@3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "camelcase": { "version": "1.2.1", - "from": "camelcase@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" }, "camelize": { "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" }, "caniuse-db": { "version": "1.0.30000740", - "from": "caniuse-db@>=1.0.30000634 <2.0.0", "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000740.tgz", + "integrity": "sha1-A/yqoXbj7QdYlfctRsGhIUm76sk=", "dev": true }, "caseless": { "version": "0.12.0", - "from": "caseless@>=0.12.0 <0.13.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "center-align": { "version": "0.1.3", - "from": "center-align@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } }, "chai": { "version": "3.5.0", - "from": "chai@3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "dev": true + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } }, "chai-spies": { "version": "0.7.1", - "from": "chai-spies@latest", - "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-0.7.1.tgz", + "integrity": "sha1-ND2Z9RJEIS6LF+ZLk5lv97LCqbE=" }, "chalk": { "version": "1.1.3", - "from": "chalk@>=1.1.3 <2.0.0", "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" + }, "dependencies": { "supports-color": { "version": "2.0.0", - "from": "supports-color@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true } } }, "character-parser": { "version": "1.2.0", - "from": "character-parser@1.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz", + "integrity": "sha1-lBNNbl2HCjm+NZ99IkYJNRhN3vY=" }, "check-error": { "version": "1.0.2", - "from": "check-error@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "clean-css": { "version": "3.4.28", - "from": "clean-css@>=3.3.0 <4.0.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + }, "dependencies": { "commander": { "version": "2.8.1", - "from": "commander@>=2.8.0 <2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": "1.0.1" + } }, "source-map": { "version": "0.4.4", - "from": "source-map@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } } } }, "cliff": { "version": "0.1.10", - "from": "cliff@>=0.1.9 <0.2.0", "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz", + "integrity": "sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM=", "dev": true, + "requires": { + "colors": "1.0.3", + "eyes": "0.1.8", + "winston": "0.8.3" + }, "dependencies": { "colors": { "version": "1.0.3", - "from": "colors@>=1.0.3 <1.1.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", "dev": true } } }, "cliui": { "version": "2.1.0", - "from": "cliui@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.2", - "from": "clone@1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" }, "cluster-key-slot": { "version": "1.0.8", - "from": "cluster-key-slot@>=1.0.6 <2.0.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz" + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz", + "integrity": "sha1-dlRVYIWmUzCTKi6LWXb44tCz5BQ=" }, "co": { "version": "4.6.0", - "from": "co@>=4.6.0 <5.0.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", - "from": "code-point-at@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "coffee-script": { "version": "1.12.4", - "from": "coffee-script@1.12.4", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.4.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.4.tgz", + "integrity": "sha1-/hvO2X/h+zknuZjytFYW4GWL4f8=" }, "colors": { "version": "0.6.2", - "from": "colors@>=0.6.2 <0.7.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" }, "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" + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } }, "commander": { "version": "2.1.0", - "from": "commander@2.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=" }, "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" + "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": "1.0.34", + "typedarray": "0.0.6" + } }, "connect": { "version": "3.6.2", - "from": "connect@3.6.2", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.2.tgz", + "integrity": "sha1-aU6NIGgb/kkCgsiriGvpjwn0L+c=", + "requires": { + "debug": "2.6.7", + "finalhandler": "1.0.3", + "parseurl": "1.3.2", + "utils-merge": "1.0.0" + }, "dependencies": { "debug": { "version": "2.6.7", - "from": "debug@2.6.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "requires": { + "ms": "2.0.0" + } }, "escape-html": { "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "finalhandler": { "version": "1.0.3", - "from": "finalhandler@1.0.3", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", + "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", + "requires": { + "debug": "2.6.7", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } } } }, "connect-redis": { "version": "3.3.0", - "from": "connect-redis@>=3.1.0 <4.0.0", "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-3.3.0.tgz", + "integrity": "sha1-yVEMGlZ/9xDrJRDmp1CfqSsiMt8=", + "requires": { + "debug": "2.6.8", + "redis": "2.8.0" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "redis": { "version": "2.8.0", - "from": "redis@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz" + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.1", + "redis-parser": "2.6.0" + } } } }, "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" + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "constantinople": { "version": "2.0.1", - "from": "constantinople@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-2.0.1.tgz", + "integrity": "sha1-WCn4VvMBqb2xB9k1932OuMzsTHk=", + "requires": { + "uglify-js": "2.4.24" + } }, "content-disposition": { "version": "0.5.0", - "from": "content-disposition@0.5.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz" + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz", + "integrity": "sha1-QoT+auBjCHRjnkToCkGMKTQTXp4=" }, "content-security-policy-builder": { "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz", + "integrity": "sha1-2R8bB2I2wRmFDH3umSS/VeBXcrM=", + "requires": { + "dashify": "0.2.2" + } }, "content-type": { "version": "1.0.4", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" }, "contentful": { "version": "3.8.1", - "from": "contentful@>=3.3.14 <4.0.0", "resolved": "https://registry.npmjs.org/contentful/-/contentful-3.8.1.tgz", + "integrity": "sha1-ulMsADKhZcIqJRzpZKfznUARwhs=", + "requires": { + "babel-runtime": "6.3.19", + "contentful-sdk-core": "2.5.0", + "json-stringify-safe": "5.0.1", + "lodash": "4.2.1" + }, "dependencies": { "lodash": { "version": "4.2.1", - "from": "lodash@>=4.2.0 <4.3.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.2.1.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.2.1.tgz", + "integrity": "sha1-Fx/c+7ww1onFRM0YwFKfVt5sGqk=" } } }, "contentful-sdk-core": { "version": "2.5.0", - "from": "contentful-sdk-core@>=2.5.0 <2.6.0", - "resolved": "https://registry.npmjs.org/contentful-sdk-core/-/contentful-sdk-core-2.5.0.tgz" + "resolved": "https://registry.npmjs.org/contentful-sdk-core/-/contentful-sdk-core-2.5.0.tgz", + "integrity": "sha1-4crWt2YGVLsQlbOF/Vq8IlGZJz8=", + "requires": { + "babel-runtime": "6.3.19", + "follow-redirects": "0.0.7", + "lodash": "4.17.4", + "qs": "6.4.0" + } }, "cookie": { "version": "0.2.4", - "from": "cookie@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.2.4.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.2.4.tgz", + "integrity": "sha1-qMFVqnubLPLE0y68e5oKoojMxr0=" }, "cookie-parser": { "version": "1.3.5", - "from": "cookie-parser@1.3.5", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "requires": { + "cookie": "0.1.3", + "cookie-signature": "1.0.6" + }, "dependencies": { "cookie": { "version": "0.1.3", - "from": "cookie@0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=" } } }, "cookie-signature": { "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookies": { "version": "0.7.1", - "from": "cookies@>=0.2.2", "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", - "dev": true + "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=", + "dev": true, + "requires": { + "depd": "1.1.1", + "keygrip": "1.0.2" + } }, "core-js": { "version": "1.2.7", - "from": "core-js@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" }, "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" + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "crc": { "version": "3.4.4", - "from": "crc@3.4.4", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz" + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" }, "crc32-stream": { "version": "0.2.0", - "from": "crc32-stream@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.2.0.tgz", + "integrity": "sha1-XIDUgMhoL5BLbxVTDbvguMBj274=", + "requires": { + "buffer-crc32": "0.2.13", + "readable-stream": "1.0.34" + } }, "cryptiles": { "version": "2.0.5", - "from": "cryptiles@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } }, "crypto-browserify": { "version": "1.0.9", - "from": "crypto-browserify@1.0.9", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-1.0.9.tgz", + "integrity": "sha1-zFRJaF37hesRyYKKzHy4erW7/MA=" }, "csrf": { "version": "3.0.6", - "from": "csrf@>=3.0.3 <3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz" + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } }, "css": { "version": "1.0.8", - "from": "css@>=1.0.8 <1.1.0", - "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz" + "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=", + "requires": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + } }, "css-parse": { "version": "1.0.4", - "from": "css-parse@1.0.4", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", + "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90=" }, "css-stringify": { "version": "1.0.5", - "from": "css-stringify@1.0.5", - "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", + "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE=" }, "csurf": { "version": "1.9.0", - "from": "csurf@>=1.8.3 <2.0.0", "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.9.0.tgz", + "integrity": "sha1-SdLGkl/87Ht95VlZfBU/pTM2QTM=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "csrf": "3.0.6", + "http-errors": "1.5.1" + }, "dependencies": { "cookie": { "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "http-errors": { "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": "1.3.1" + } }, "setprototypeof": { "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" } } }, "ctype": { "version": "0.5.3", - "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", "dev": true, "optional": true }, "cycle": { "version": "1.0.3", - "from": "cycle@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", "dev": true }, "dashdash": { "version": "1.14.1", - "from": "dashdash@>=1.12.0 <2.0.0", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "dasherize": { "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" }, "dashify": { "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz", + "integrity": "sha1-agdBWgHJH69KMuONnfunH2HLIP4=" }, "dateformat": { "version": "1.0.4-1.2.3", - "from": "dateformat@1.0.4-1.2.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.4-1.2.3.tgz" + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.4-1.2.3.tgz", + "integrity": "sha1-TBKxAb3buIgMI1babkVEWaXri3U=" }, "debug": { "version": "1.0.5", - "from": "debug@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.5.tgz", + "integrity": "sha1-9yQSF0MPmd7EwrRz6rkiKOh0wqw=", + "requires": { + "ms": "2.0.0" + } }, "decamelize": { "version": "1.2.0", - "from": "decamelize@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "deep-eql": { "version": "0.1.3", - "from": "deep-eql@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, + "requires": { + "type-detect": "0.1.1" + }, "dependencies": { "type-detect": { "version": "0.1.1", - "from": "type-detect@0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", "dev": true } } }, "deep-equal": { "version": "1.0.1", - "from": "deep-equal@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, "deep-extend": { "version": "0.4.2", - "from": "deep-extend@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz" + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" }, "define-properties": { "version": "1.1.2", - "from": "define-properties@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz" + "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": "1.0.0", - "from": "defined@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "deflate-crc32-stream": { "version": "0.1.2", - "from": "deflate-crc32-stream@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/deflate-crc32-stream/-/deflate-crc32-stream-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/deflate-crc32-stream/-/deflate-crc32-stream-0.1.2.tgz", + "integrity": "sha1-l16g5zA7ddhSMhmKt7QFwtR7qtU=", + "requires": { + "buffer-crc32": "0.2.13" + } }, "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" + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", - "from": "delegates@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "depd": { "version": "1.1.1", - "from": "depd@>=1.1.1 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "destroy": { "version": "1.0.3", - "from": "destroy@1.0.3", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz", + "integrity": "sha1-tDO0ck5x/YVR2YhRdIUcX8N34sk=" }, "dicer": { "version": "0.2.5", - "from": "dicer@0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.14", + "streamsearch": "0.1.2" + }, "dependencies": { "readable-stream": { "version": "1.1.14", - "from": "readable-stream@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } } } }, "diff": { "version": "1.0.7", - "from": "diff@1.0.7", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz" + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz", + "integrity": "sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ=" }, "director": { "version": "1.2.7", - "from": "director@1.2.7", "resolved": "https://registry.npmjs.org/director/-/director-1.2.7.tgz", + "integrity": "sha1-v9N0EHX9f7GlsuE2WMX0vsd3NvM=", "dev": true }, "dns-prefetch-control": { "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz", + "integrity": "sha1-YN20V3dOF48flBXwyrsOhbCzALI=" }, "doctypes": { "version": "1.1.0", - "from": "doctypes@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" }, "dom-serializer": { "version": "0.1.0", - "from": "dom-serializer@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, "dependencies": { "domelementtype": { "version": "1.1.3", - "from": "domelementtype@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", "dev": true } } }, "domelementtype": { "version": "1.3.0", - "from": "domelementtype@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "dev": true }, "domhandler": { "version": "2.4.1", - "from": "domhandler@>=2.3.0 <3.0.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "dev": true + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } }, "domutils": { "version": "1.6.2", - "from": "domutils@>=1.5.1 <2.0.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", - "dev": true + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } }, "dont-sniff-mimetype": { "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz", + "integrity": "sha1-WTKJDcn04vGeXrAqIAJuXl78j1g=" }, "dottie": { "version": "1.1.1", - "from": "dottie@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/dottie/-/dottie-1.1.1.tgz", + "integrity": "sha1-RcKj9IvWUo7u0memmoSOqspvqmo=" }, "double-ended-queue": { "version": "2.1.0-0", - "from": "double-ended-queue@>=2.1.0-0 <3.0.0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz" + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "dtrace-provider": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.2.8.tgz", + "integrity": "sha1-4kPxkhmqlfvw2PL/sH9b1k6U/iA=", + "optional": true }, "each-series": { "version": "1.0.0", - "from": "each-series@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz", + "integrity": "sha1-+Ibmxm39sl7x/nNWQUbuXLR4r8s=" }, "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", - "optional": true + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } }, "ecdsa-sig-formatter": { "version": "1.0.9", - "from": "ecdsa-sig-formatter@1.0.9", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz" + "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", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { "version": "0.8.8", - "from": "ejs@>=0.8.3 <0.9.0", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz" + "resolved": "https://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz", + "integrity": "sha1-/9xW3MNdApJt1QrRNDm7xUBh1Zg=" }, "electron-to-chromium": { "version": "1.3.24", - "from": "electron-to-chromium@>=1.2.7 <2.0.0", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz", + "integrity": "sha1-m3uIuwXOufoBahd4M8wt3jiPIbY=", "dev": true }, "encodeurl": { "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" }, "encoding": { "version": "0.1.12", - "from": "encoding@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + }, "dependencies": { "iconv-lite": { "version": "0.4.19", - "from": "iconv-lite@>=0.4.13 <0.5.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" } } }, "end-of-stream": { "version": "0.1.5", - "from": "end-of-stream@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "requires": { + "once": "1.3.3" + } }, "entities": { "version": "1.1.1", - "from": "entities@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", "dev": true }, "es-abstract": { "version": "1.8.2", - "from": "es-abstract@>=1.5.0 <2.0.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.2.tgz" + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.2.tgz", + "integrity": "sha1-JRAyY9xN7L2mDgxzfKMjE1GAJ+4=", + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } }, "es-to-primitive": { "version": "1.1.1", - "from": "es-to-primitive@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } }, "es6-promise": { "version": "4.1.1", - "from": "es6-promise@>=4.0.5 <5.0.0", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "integrity": "sha1-iBHpCRXZoNujYnTwskLb2nj5ySo=", "dev": true }, "escape-html": { "version": "1.0.2", - "from": "escape-html@1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", + "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=" }, "escape-string-regexp": { "version": "1.0.5", - "from": "escape-string-regexp@^1.0.2", - "resolved": "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", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esprima": { "version": "1.0.4", - "from": "esprima@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" }, "etag": { "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" }, "event-stream": { "version": "0.5.3", - "from": "event-stream@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-0.5.3.tgz", + "integrity": "sha1-t3uTCfcQet3+q2PwwOr9jbC9jBw=", "dev": true, + "requires": { + "optimist": "0.2.8" + }, "dependencies": { "optimist": { "version": "0.2.8", - "from": "optimist@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.2.8.tgz", - "dev": true + "integrity": "sha1-6YGrfiaLRXlIWTtVZ0wJmoFcrDE=", + "dev": true, + "requires": { + "wordwrap": "0.0.2" + } } } }, "eventemitter2": { "version": "0.4.14", - "from": "eventemitter2@>=0.4.13 <0.5.0", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz" + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" }, "eventemitter3": { "version": "1.2.0", - "from": "eventemitter3@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" }, "events": { "version": "1.1.1", - "from": "events@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, "exit": { "version": "0.1.2", - "from": "exit@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" }, "expect-ct": { "version": "0.1.0", - "from": "expect-ct@0.1.0", - "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.0.tgz", + "integrity": "sha1-UnNWeN4YUwiQ2Ne5XwrGNkCVgJQ=" }, "express": { "version": "4.13.0", - "from": "express@4.13.0", "resolved": "https://registry.npmjs.org/express/-/express-4.13.0.tgz", + "integrity": "sha1-Bni9vHJxUXCz/MkXBS8EbLlomt0=", + "requires": { + "accepts": "1.2.13", + "array-flatten": "1.1.0", + "content-disposition": "0.5.0", + "content-type": "1.0.4", + "cookie": "0.1.3", + "cookie-signature": "1.0.6", + "debug": "2.2.0", + "depd": "1.0.1", + "escape-html": "1.0.2", + "etag": "1.7.0", + "finalhandler": "0.4.0", + "fresh": "0.3.0", + "merge-descriptors": "1.0.0", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.6", + "proxy-addr": "1.0.10", + "qs": "2.4.2", + "range-parser": "1.0.3", + "send": "0.13.0", + "serve-static": "1.10.3", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.0.1" + }, "dependencies": { "cookie": { "version": "0.1.3", - "from": "cookie@0.1.3", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", + "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=" }, "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "depd": { "version": "1.0.1", - "from": "depd@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" }, "qs": { "version": "2.4.2", - "from": "qs@2.4.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz", + "integrity": "sha1-9854jld33wtQENp/fE5zujJHD1o=" } } }, "express-session": { "version": "1.15.5", - "from": "express-session@>=1.14.2 <2.0.0", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.5.tgz", + "integrity": "sha1-9JoYInJjsxb2+FRNpf7iWlQCWew=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.4", + "debug": "2.6.8", + "depd": "1.1.1", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.1.4", + "utils-merge": "1.0.0" + }, "dependencies": { "cookie": { "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "debug": { "version": "2.6.8", - "from": "debug@2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } } } }, "extend": { "version": "3.0.1", - "from": "extend@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "extendible": { "version": "0.1.1", - "from": "extendible@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/extendible/-/extendible-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/extendible/-/extendible-0.1.1.tgz", + "integrity": "sha1-4qN+2HEp+0+VM+io11BiMKU5yQU=" + }, + "extract-zip": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", + "integrity": "sha1-maBnNbbqIOqbcF13ms/8yHz/BEA=", + "requires": { + "concat-stream": "1.6.0", + "debug": "1.0.5", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + }, + "dependencies": { + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "requires": { + "fd-slicer": "1.0.1" + } + } + } }, "extsprintf": { "version": "1.3.0", - "from": "extsprintf@1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "eyes": { "version": "0.1.8", - "from": "eyes@>=0.1.8 <0.2.0", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", "dev": true }, "failure": { "version": "1.1.1", - "from": "failure@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz", + "integrity": "sha1-qOg9OxYC0kaL/2rU2QceAQO4Goc=" }, "faye-websocket": { "version": "0.10.0", - "from": "faye-websocket@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "dev": true + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "1.2.0" + } }, "file-utils": { "version": "0.1.5", - "from": "file-utils@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", + "integrity": "sha1-3IFTyFU4fLTaywoXJVMfpESmtIw=", + "requires": { + "findup-sync": "0.1.3", + "glob": "3.2.11", + "iconv-lite": "0.2.11", + "isbinaryfile": "0.1.9", + "lodash": "2.1.0", + "minimatch": "0.2.14", + "rimraf": "2.2.6" + }, "dependencies": { "lodash": { "version": "2.1.0", - "from": "lodash@>=2.1.0 <2.2.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz", + "integrity": "sha1-Bjfqqjaooc/IZcOt+5Qhib+wmY0=" } } }, "finalhandler": { "version": "0.4.0", - "from": "finalhandler@0.4.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.2", + "on-finished": "2.3.0", + "unpipe": "1.0.0" + }, "dependencies": { "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" } } }, "findup-sync": { "version": "0.1.3", - "from": "findup-sync@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "requires": { + "glob": "3.2.11", + "lodash": "2.4.2" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" } } }, "flatiron": { "version": "0.4.3", - "from": "flatiron@>=0.4.2 <0.5.0", "resolved": "https://registry.npmjs.org/flatiron/-/flatiron-0.4.3.tgz", + "integrity": "sha1-JIz3mj2n19w3nioRySonGcu1QPY=", "dev": true, + "requires": { + "broadway": "0.3.6", + "director": "1.2.7", + "optimist": "0.6.0", + "prompt": "0.2.14" + }, "dependencies": { "optimist": { "version": "0.6.0", - "from": "optimist@0.6.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", - "dev": true + "integrity": "sha1-aUJIJvNAX3nxQub8PZrljU27kgA=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.2" + } } } }, "flexbuffer": { "version": "0.0.6", - "from": "flexbuffer@0.0.6", - "resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz" + "resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz", + "integrity": "sha1-A5/fI/iCPkQMOPMnfm/vEXQhWzA=" }, "follow-redirects": { "version": "0.0.7", - "from": "follow-redirects@0.0.7", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", + "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", + "requires": { + "debug": "2.6.8", + "stream-consume": "0.1.0" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } } } }, "for-each": { "version": "0.3.2", - "from": "for-each@>=0.3.2 <0.4.0", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "requires": { + "is-function": "1.0.1" + } }, "foreach": { "version": "2.0.5", - "from": "foreach@>=2.0.5 <3.0.0", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "forever": { "version": "0.14.2", - "from": "forever@>=0.14.1 <0.15.0", "resolved": "https://registry.npmjs.org/forever/-/forever-0.14.2.tgz", - "dev": true + "integrity": "sha1-6Tsr2UxXBavBmxXlTDEz1puinGs=", + "dev": true, + "requires": { + "cliff": "0.1.10", + "colors": "0.6.2", + "flatiron": "0.4.3", + "forever-monitor": "1.5.2", + "nconf": "0.6.9", + "nssocket": "0.5.3", + "optimist": "0.6.1", + "timespan": "2.3.0", + "utile": "0.2.1", + "winston": "0.8.3" + } }, "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" + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "forever-monitor": { "version": "1.5.2", - "from": "forever-monitor@>=1.5.1 <1.6.0", "resolved": "https://registry.npmjs.org/forever-monitor/-/forever-monitor-1.5.2.tgz", + "integrity": "sha1-J5OI36k7CFNj1rKKgj7wpq7rNdc=", "dev": true, + "requires": { + "broadway": "0.3.6", + "minimatch": "1.0.0", + "ps-tree": "0.0.3", + "utile": "0.2.1", + "watch": "0.13.0" + }, "dependencies": { "minimatch": { "version": "1.0.0", - "from": "minimatch@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", - "dev": true + "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } } } }, "form-data": { "version": "2.1.4", - "from": "form-data@>=2.1.1 <2.2.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } }, "formatio": { "version": "1.1.1", - "from": "formatio@1.1.1", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "dev": true + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "1.1.2" + } }, "forwarded": { "version": "0.1.1", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.1.tgz", + "integrity": "sha1-ik4wxkCwU5U5mjVJxzAldygEiWE=" }, "frameguard": { "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz", + "integrity": "sha1-e8rUae57lukdEs6zlZx4I1qScuk=" }, "fresh": { "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" }, "fs-extra": { - "version": "0.9.1", - "from": "fs-extra@>=0.9.1 <0.10.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.9.1.tgz", - "dependencies": { - "glob": { - "version": "7.1.2", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" - }, - "minimatch": { - "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - }, - "ncp": { - "version": "0.5.1", - "from": "ncp@>=0.5.1 <0.6.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz" - }, - "rimraf": { - "version": "2.6.2", - "from": "rimraf@>=2.2.8 <3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - } + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" } }, "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" + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { "version": "1.0.11", - "from": "fstream@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz" + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.2.6" + } }, "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", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + }, "dependencies": { "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } } } }, "function-bind": { "version": "1.1.1", - "from": "function-bind@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" }, "gauge": { "version": "2.7.4", - "from": "gauge@>=2.7.3 <2.8.0", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.1.2", + "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" + } }, "gaze": { "version": "1.1.2", - "from": "gaze@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "dev": true + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "1.2.0" + } }, "generic-pool": { "version": "2.4.2", - "from": "generic-pool@2.4.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.2.tgz", + "integrity": "sha1-iGvFvwvrfblugby7oHiBjeWmJoM=" }, "get-func-name": { "version": "2.0.0", - "from": "get-func-name@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "getobject": { "version": "0.1.0", - "from": "getobject@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=" }, "getpass": { "version": "0.1.7", - "from": "getpass@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "glob": { "version": "3.2.11", - "from": "glob@>=3.2.6 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + }, "dependencies": { "minimatch": { "version": "0.3.0", - "from": "minimatch@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } } } }, "globule": { "version": "1.2.0", - "from": "globule@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + }, "dependencies": { "glob": { "version": "7.1.2", - "from": "glob@>=7.1.1 <7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "dev": true + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.2 <3.1.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "dev": true + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } } } }, "graceful-fs": { "version": "4.1.11", - "from": "graceful-fs@>=4.1.2 <5.0.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { "version": "1.0.1", - "from": "graceful-readlink@>=1.0.0", - "resolved": "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", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "growl": { "version": "1.7.0", - "from": "growl@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=" }, "grunt": { "version": "0.4.5", - "from": "grunt@>=0.4.5 <0.5.0", "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "requires": { + "async": "0.1.22", + "coffee-script": "1.3.3", + "colors": "0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.1.3", + "getobject": "0.1.0", + "glob": "3.1.21", + "grunt-legacy-log": "0.1.3", + "grunt-legacy-util": "0.2.0", + "hooker": "0.2.3", + "iconv-lite": "0.2.11", + "js-yaml": "2.0.5", + "lodash": "0.9.2", + "minimatch": "0.2.14", + "nopt": "1.0.10", + "rimraf": "2.2.8", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, "dependencies": { "async": { "version": "0.1.22", - "from": "async@>=0.1.22 <0.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=" }, "coffee-script": { "version": "1.3.3", - "from": "coffee-script@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=" }, "dateformat": { "version": "1.0.2-1.2.3", - "from": "dateformat@1.0.2-1.2.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz" + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=" }, "glob": { "version": "3.1.21", - "from": "glob@>=3.1.21 <3.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } }, "graceful-fs": { "version": "1.2.3", - "from": "graceful-fs@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" }, "inherits": { "version": "1.0.2", - "from": "inherits@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" }, "lodash": { "version": "0.9.2", - "from": "lodash@>=0.9.2 <0.10.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=" }, "nopt": { "version": "1.0.10", - "from": "nopt@>=1.0.10 <1.1.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1.1.0" + } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@>=2.2.8 <2.3.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" } } }, "grunt-available-tasks": { "version": "0.4.1", - "from": "grunt-available-tasks@0.4.1", "resolved": "https://registry.npmjs.org/grunt-available-tasks/-/grunt-available-tasks-0.4.1.tgz", + "integrity": "sha1-fyAoBUn6OFZxLp68Uj3YjBE7hZQ=", "dev": true, + "requires": { + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", "dev": true }, "underscore.string": { "version": "2.3.3", - "from": "underscore.string@>=2.3.3 <2.4.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", "dev": true } } }, "grunt-bunyan": { "version": "0.5.0", - "from": "grunt-bunyan@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/grunt-bunyan/-/grunt-bunyan-0.5.0.tgz", + "integrity": "sha1-aCnXbgGZQ9owQTk2MaNuKsgpsWw=", + "requires": { + "lodash": "2.4.2" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" } } }, "grunt-contrib-clean": { "version": "0.5.0", - "from": "grunt-contrib-clean@0.5.0", "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz", - "dev": true + "integrity": "sha1-9T397ghJsce0Dp67umn0jExgecU=", + "dev": true, + "requires": { + "rimraf": "2.2.6" + } }, "grunt-contrib-coffee": { "version": "0.10.0", - "from": "grunt-contrib-coffee@0.10.0", "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.10.0.tgz", + "integrity": "sha1-1UntlxHN1mkWOWwRisf9LRF4C9E=", "dev": true, + "requires": { + "chalk": "0.4.0", + "coffee-script": "1.7.1", + "lodash": "2.4.2" + }, "dependencies": { "ansi-styles": { "version": "1.0.0", - "from": "ansi-styles@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", "dev": true }, "chalk": { "version": "0.4.0", - "from": "chalk@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "dev": true + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } }, "coffee-script": { "version": "1.7.1", - "from": "coffee-script@>=1.7.0 <1.8.0", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", - "dev": true + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "dev": true, + "requires": { + "mkdirp": "0.3.5" + } }, "lodash": { "version": "2.4.2", - "from": "lodash@~2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", "dev": true }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true }, "strip-ansi": { "version": "0.1.1", - "from": "strip-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", "dev": true } } }, "grunt-contrib-less": { "version": "0.9.0", - "from": "grunt-contrib-less@0.9.0", "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-0.9.0.tgz", + "integrity": "sha1-rx5udlEcK8Mo740oQFhkPKWIdnU=", "dev": true, + "requires": { + "chalk": "0.4.0", + "grunt-lib-contrib": "0.6.1", + "less": "1.6.3" + }, "dependencies": { "ansi-styles": { "version": "1.0.0", - "from": "ansi-styles@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", "dev": true }, "chalk": { "version": "0.4.0", - "from": "chalk@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "dev": true + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } }, "strip-ansi": { "version": "0.1.1", - "from": "strip-ansi@~0.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", "dev": true } } }, "grunt-contrib-requirejs": { "version": "0.4.1", - "from": "grunt-contrib-requirejs@0.4.1", "resolved": "https://registry.npmjs.org/grunt-contrib-requirejs/-/grunt-contrib-requirejs-0.4.1.tgz", - "dev": true + "integrity": "sha1-hiuhZxQbio82r1RE/qsycruM9L0=", + "dev": true, + "requires": { + "requirejs": "2.1.22" + } }, "grunt-contrib-watch": { "version": "1.0.0", - "from": "grunt-contrib-watch@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=", "dev": true, + "requires": { + "async": "1.5.2", + "gaze": "1.1.2", + "lodash": "3.10.1", + "tiny-lr": "0.2.1" + }, "dependencies": { "async": { "version": "1.5.2", - "from": "async@>=1.5.0 <2.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "lodash": { "version": "3.10.1", - "from": "lodash@>=3.10.1 <4.0.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true } } }, "grunt-env": { "version": "0.4.4", - "from": "grunt-env@0.4.4", "resolved": "https://registry.npmjs.org/grunt-env/-/grunt-env-0.4.4.tgz", + "integrity": "sha1-OziEOo1zcXfdyfiTh5+2nOGgvC8=", "dev": true, + "requires": { + "ini": "1.3.4", + "lodash": "2.4.2" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@~2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", "dev": true } } }, "grunt-exec": { "version": "0.4.7", - "from": "grunt-exec@>=0.4.7 <0.5.0", "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.7.tgz", + "integrity": "sha1-QAUf+k6wyWV+BTuV6I1ENSocLCU=", "dev": true }, "grunt-execute": { "version": "0.2.2", - "from": "grunt-execute@>=0.2.2 <0.3.0", - "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz" + "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz", + "integrity": "sha1-TpRf5XlZzA3neZCDtrQq7ZYWNQo=" }, "grunt-file-append": { "version": "0.0.6", - "from": "grunt-file-append@0.0.6", "resolved": "https://registry.npmjs.org/grunt-file-append/-/grunt-file-append-0.0.6.tgz", + "integrity": "sha1-2nH07qPtOylROCKIWaFFZ2NX7z8=", "dev": true }, "grunt-forever": { "version": "0.4.7", - "from": "grunt-forever@>=0.4.7 <0.5.0", "resolved": "https://registry.npmjs.org/grunt-forever/-/grunt-forever-0.4.7.tgz", - "dev": true + "integrity": "sha1-dHDb4a2hFFAhZKTCoAOHXfj+EzA=", + "dev": true, + "requires": { + "forever": "0.14.2" + } }, "grunt-git-rev-parse": { "version": "0.1.5", - "from": "grunt-git-rev-parse@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/grunt-git-rev-parse/-/grunt-git-rev-parse-0.1.5.tgz", + "integrity": "sha1-ntSngs7jCa9DHiKXGX6vyTOQa80=", "dev": true }, "grunt-legacy-log": { "version": "0.1.3", - "from": "grunt-legacy-log@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "requires": { + "colors": "0.6.2", + "grunt-legacy-log-utils": "0.1.1", + "hooker": "0.2.3", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" }, "underscore.string": { "version": "2.3.3", - "from": "underscore.string@>=2.3.3 <2.4.0", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=" } } }, "grunt-legacy-log-utils": { "version": "0.1.1", - "from": "grunt-legacy-log-utils@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "requires": { + "colors": "0.6.2", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" }, "underscore.string": { "version": "2.3.3", - "from": "underscore.string@>=2.3.3 <2.4.0", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=" } } }, "grunt-legacy-util": { "version": "0.2.0", - "from": "grunt-legacy-util@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "requires": { + "async": "0.1.22", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "0.9.2", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, "dependencies": { "async": { "version": "0.1.22", - "from": "async@>=0.1.22 <0.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=" }, "lodash": { "version": "0.9.2", - "from": "lodash@>=0.9.2 <0.10.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=" } } }, "grunt-lib-contrib": { "version": "0.6.1", - "from": "grunt-lib-contrib@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz", - "dev": true + "integrity": "sha1-P1att9oG6BR5XuJBWw6+X7iQPrs=", + "dev": true, + "requires": { + "zlib-browserify": "0.0.1" + } }, "grunt-mocha-test": { "version": "0.9.0", - "from": "grunt-mocha-test@0.9.0", "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.9.0.tgz", - "dev": true + "integrity": "sha1-BNFfMl8OKJcrLMZB9OMEwGxFwQs=", + "dev": true, + "requires": { + "hooker": "0.2.3", + "mocha": "1.17.1" + } }, "grunt-newer": { "version": "1.3.0", - "from": "grunt-newer@>=1.2.0 <2.0.0", "resolved": "https://registry.npmjs.org/grunt-newer/-/grunt-newer-1.3.0.tgz", + "integrity": "sha1-g8y3od2ny9irI7BZAk6+YUrS80I=", "dev": true, + "requires": { + "async": "1.5.2", + "rimraf": "2.6.2" + }, "dependencies": { "async": { "version": "1.5.2", - "from": "async@^1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "glob": { "version": "7.1.2", - "from": "glob@^7.0.5", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "dev": true + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@^3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "dev": true + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } }, "rimraf": { "version": "2.6.2", - "from": "rimraf@>=2.5.2 <3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "dev": true + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "7.1.2" + } } } }, "grunt-parallel": { "version": "0.5.1", - "from": "grunt-parallel@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/grunt-parallel/-/grunt-parallel-0.5.1.tgz", + "integrity": "sha1-X3ozdvYYVCQSjEsqLPLi0Hw39dk=", "dev": true, + "requires": { + "lpad": "0.1.0", + "q": "0.8.12" + }, "dependencies": { "q": { "version": "0.8.12", - "from": "q@>=0.8.12 <0.9.0", "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "integrity": "sha1-kWKpHhGBnEvNp9oVz1/vqtB3iCM=", "dev": true } } }, "grunt-postcss": { "version": "0.8.0", - "from": "grunt-postcss@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.8.0.tgz", + "integrity": "sha1-jzCor2B5A84MRfAfC+QsYOMc6w4=", "dev": true, + "requires": { + "chalk": "1.1.3", + "diff": "2.2.3", + "postcss": "5.2.17" + }, "dependencies": { "diff": { "version": "2.2.3", - "from": "diff@>=2.0.2 <3.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=", "dev": true } } }, "grunt-sed": { "version": "0.1.1", - "from": "grunt-sed@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/grunt-sed/-/grunt-sed-0.1.1.tgz", - "dev": true + "integrity": "sha1-JhPUhpCTGbP49L112vtGpkLsP4I=", + "dev": true, + "requires": { + "replace": "0.2.10" + } }, "grunt-shell": { "version": "2.1.0", - "from": "grunt-shell@>=2.1.0 <3.0.0", "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-2.1.0.tgz", - "dev": true + "integrity": "sha1-Q595FZ7RHmSmUaacyKPQK+v17MI=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "npm-run-path": "2.0.2" + } }, "hang": { "version": "1.0.0", - "from": "hang@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/hang/-/hang-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/hang/-/hang-1.0.0.tgz", + "integrity": "sha1-ZwUIeYRENeAq4ECcT0VTxkOOHXE=" }, "har-schema": { "version": "1.0.5", - "from": "har-schema@>=1.0.5 <2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" }, "har-validator": { "version": "4.2.1", - "from": "har-validator@>=4.2.1 <4.3.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz" + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } }, "has": { "version": "1.0.1", - "from": "has@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } }, "has-ansi": { "version": "2.0.0", - "from": "has-ansi@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "dev": true + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } }, "has-color": { "version": "0.1.7", - "from": "has-color@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", "dev": true }, "has-flag": { "version": "1.0.0", - "from": "has-flag@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "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" + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "hawk": { "version": "3.1.3", - "from": "hawk@>=3.1.3 <3.2.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } }, "heapdump": { "version": "0.3.9", - "from": "heapdump@>=0.3.7 <0.4.0", - "resolved": "https://registry.npmjs.org/heapdump/-/heapdump-0.3.9.tgz" + "resolved": "https://registry.npmjs.org/heapdump/-/heapdump-0.3.9.tgz", + "integrity": "sha1-A8dOsN9dZ74Jgug0KbqcnSs7f3g=" }, "helmet": { "version": "3.8.1", - "from": "helmet@>=3.8.1 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.8.1.tgz" + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.8.1.tgz", + "integrity": "sha1-vvK2j/uqGXWehYwZzKfbITu1iy0=", + "requires": { + "connect": "3.6.2", + "dns-prefetch-control": "0.1.0", + "dont-sniff-mimetype": "1.0.0", + "expect-ct": "0.1.0", + "frameguard": "3.0.0", + "helmet-csp": "2.5.1", + "hide-powered-by": "1.0.0", + "hpkp": "2.0.0", + "hsts": "2.1.0", + "ienoopen": "1.0.0", + "nocache": "2.0.0", + "referrer-policy": "1.1.0", + "x-xss-protection": "1.0.0" + } }, "helmet-csp": { "version": "2.5.1", - "from": "helmet-csp@2.5.1", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.5.1.tgz" + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.5.1.tgz", + "integrity": "sha1-Xz3uyPki+n4HTbw5h8FopQVzw20=", + "requires": { + "camelize": "1.0.0", + "content-security-policy-builder": "1.1.0", + "dasherize": "2.0.0", + "lodash.reduce": "4.6.0", + "platform": "1.3.4" + } }, "hide-powered-by": { "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz", + "integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=" }, "hoek": { "version": "2.16.3", - "from": "hoek@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, "hooker": { "version": "0.2.3", - "from": "hooker@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" }, "hooks-fixed": { "version": "2.0.0", - "from": "hooks-fixed@2.0.0", - "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.0.tgz", + "integrity": "sha1-oB2JTVKsf2WZu7H2PfycQR33DLo=" }, "hpkp": { "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz", + "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" }, "hsts": { "version": "2.1.0", - "from": "hsts@2.1.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.1.0.tgz", + "integrity": "sha1-y9bJGKI4X+4d1WgL+ys6GUwBIcw=" }, "htmlparser2": { "version": "3.9.2", - "from": "htmlparser2@>=3.9.0 <4.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, "dependencies": { "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { "version": "2.3.3", - "from": "readable-stream@>=2.0.2 <3.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "dev": true + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": 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" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.3 <1.1.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "dev": true + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } } } }, "http-errors": { "version": "1.6.2", - "from": "http-errors@>=1.6.2 <1.7.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz" + "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" + } }, "http-parser-js": { "version": "0.4.8", - "from": "http-parser-js@>=0.4.0", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.8.tgz", + "integrity": "sha1-dj91xLdxoLtEZTsHBwv/bKe8VWE=", "dev": true }, "http-proxy": { "version": "1.16.2", - "from": "http-proxy@>=1.8.1 <2.0.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz" + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } }, "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" + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } }, "i": { "version": "0.3.5", - "from": "i@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/i/-/i-0.3.5.tgz", + "integrity": "sha1-HSuFQVjsgWkRPGy39raAHpniEdU=", "dev": true }, "i18next": { "version": "1.7.10", - "from": "i18next@>=1.7.1 <1.8.0", "resolved": "https://registry.npmjs.org/i18next/-/i18next-1.7.10.tgz", - "dev": true + "integrity": "sha1-K8HOLMG8LpP6c7WINZ2gIZczaHU=", + "dev": true, + "requires": { + "cookies": "0.7.1", + "json5": "0.2.0" + } }, "iconv-lite": { "version": "0.2.11", - "from": "iconv-lite@>=0.2.11 <0.3.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=" }, "ieee754": { "version": "1.1.8", - "from": "ieee754@>=1.1.4 <2.0.0", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz" + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" }, "ienoopen": { "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz", + "integrity": "sha1-NGpCj0dKrI9QzzeE6i0PFvYr2ms=" }, "inflection": { "version": "1.12.0", - "from": "inflection@>=1.6.0 <2.0.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz" + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" }, "inflight": { "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } }, "inherits": { "version": "2.0.3", - "from": "inherits@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.4", - "from": "ini@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" }, "ioredis": { "version": "2.5.0", - "from": "ioredis@>=2.4.0 <3.0.0", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-2.5.0.tgz", + "integrity": "sha1-+2/fChp+CXRhTGe25eETCKjPlbk=", + "requires": { + "bluebird": "3.5.0", + "cluster-key-slot": "1.0.8", + "debug": "2.6.8", + "double-ended-queue": "2.1.0-0", + "flexbuffer": "0.0.6", + "lodash": "4.17.4", + "redis-commands": "1.3.1", + "redis-parser": "1.3.0" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "redis-parser": { "version": "1.3.0", - "from": "redis-parser@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-1.3.0.tgz", + "integrity": "sha1-gG6+e7+3005NfB6e8oLvz60EEmo=" } } }, "ipaddr.js": { "version": "1.0.5", - "from": "ipaddr.js@1.0.5", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz", + "integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c=" }, "is-buffer": { "version": "1.1.5", - "from": "is-buffer@>=1.1.5 <2.0.0", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz" + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" }, "is-callable": { "version": "1.1.3", - "from": "is-callable@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz" + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" }, "is-date-object": { "version": "1.0.1", - "from": "is-date-object@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-expression": { "version": "2.1.0", - "from": "is-expression@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-2.1.0.tgz", + "integrity": "sha1-kb6dR968/vB3l36XIr5tz7RGXvA=", + "requires": { + "acorn": "3.3.0", + "object-assign": "4.1.1" + } }, "is-fullwidth-code-point": { "version": "1.0.0", - "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + "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-function": { "version": "1.0.1", - "from": "is-function@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, "is-promise": { "version": "1.0.1", - "from": "is-promise@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" }, "is-regex": { "version": "1.0.4", - "from": "is-regex@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } }, "is-symbol": { "version": "1.0.1", - "from": "is-symbol@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" }, "is-typedarray": { "version": "1.0.0", - "from": "is-typedarray@>=1.0.0 <1.1.0", - "resolved": "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", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "isbinaryfile": { "version": "0.1.9", - "from": "isbinaryfile@>=0.1.9 <0.2.0", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz" + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz", + "integrity": "sha1-Fe7ONcSrcI2JJNqZ+4dPK1zAtsQ=" }, "isstream": { "version": "0.1.2", - "from": "isstream@>=0.1.2 <0.2.0", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "jade": { "version": "1.3.1", - "from": "jade@>=1.3.1 <1.4.0", "resolved": "https://registry.npmjs.org/jade/-/jade-1.3.1.tgz", + "integrity": "sha1-dIPYSLhxTcUKQNqYsECXkLN0IWs=", + "requires": { + "character-parser": "1.2.0", + "commander": "2.1.0", + "constantinople": "2.0.1", + "mkdirp": "0.3.5", + "monocle": "1.1.51", + "transformers": "2.1.0", + "with": "3.0.1" + }, "dependencies": { "mkdirp": { "version": "0.3.5", - "from": "mkdirp@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" } } }, "jmespath": { "version": "0.15.0", - "from": "jmespath@0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz" + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, "js-base64": { "version": "2.3.2", - "from": "js-base64@>=2.1.9 <3.0.0", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", + "integrity": "sha1-p5qSNmY3K1gPjif1GEXG9+j7+68=", "dev": true }, "js-stringify": { "version": "1.0.2", - "from": "js-stringify@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" }, "js-yaml": { "version": "2.0.5", - "from": "js-yaml@>=2.0.5 <2.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "requires": { + "argparse": "0.1.16", + "esprima": "1.0.4" + } }, "jsbn": { "version": "0.1.1", - "from": "jsbn@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, "json-schema": { "version": "0.2.3", - "from": "json-schema@0.2.3", - "resolved": "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", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-stable-stringify": { "version": "1.0.1", - "from": "json-stable-stringify@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } }, "json-stringify-safe": { "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.1 <5.1.0", - "resolved": "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", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "0.2.0", - "from": "json5@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/json5/-/json5-0.2.0.tgz", + "integrity": "sha1-ttcDXHDEVw+IPH7cdZ3jrgPbM0M=", "dev": true }, "jsonfile": { - "version": "1.1.1", - "from": "jsonfile@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.1.1.tgz" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.11" + } }, "jsonify": { "version": "0.0.0", - "from": "jsonify@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsonwebtoken": { "version": "8.0.1", - "from": "jsonwebtoken@latest", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz" + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz", + "integrity": "sha1-UNrvjQqMfeLNBrwQE7dbBMzz8M8=", + "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.0.0", + "xtend": "4.0.1" + } }, "jsprim": { "version": "1.4.1", - "from": "jsprim@>=1.2.2 <2.0.0", "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" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@1.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "jstransformer": { "version": "1.0.0", - "from": "jstransformer@1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "requires": { + "is-promise": "2.1.0", + "promise": "7.3.1" + }, "dependencies": { "is-promise": { "version": "2.1.0", - "from": "is-promise@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "promise": { "version": "7.3.1", - "from": "promise@>=7.0.1 <8.0.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz" + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "requires": { + "asap": "2.0.6" + } } } }, "just-extend": { "version": "1.1.22", - "from": "just-extend@>=1.1.22 <2.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.22.tgz" + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.22.tgz", + "integrity": "sha1-MzCvdWyralQnAMZLLk5KoGLVL/8=" }, "jwa": { "version": "1.1.5", - "from": "jwa@>=1.1.4 <2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz" + "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", - "from": "jws@>=3.1.4 <4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz" + "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" + } }, "kareem": { "version": "1.5.0", - "from": "kareem@1.5.0", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz" + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", + "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" }, "keygrip": { "version": "1.0.2", - "from": "keygrip@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E=", "dev": true }, "kind-of": { "version": "3.2.2", - "from": "kind-of@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.5" + } }, "lazy": { "version": "1.0.11", - "from": "lazy@>=1.0.11 <1.1.0", "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=", "dev": true }, "lazy-cache": { "version": "1.0.4", - "from": "lazy-cache@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" }, "lazystream": { "version": "0.1.0", - "from": "lazystream@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "requires": { + "readable-stream": "1.0.34" + } }, "ldap-filter": { "version": "0.2.2", - "from": "ldap-filter@0.2.2", "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz", + "integrity": "sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=", + "requires": { + "assert-plus": "0.1.5" + }, "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "assert-plus@0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" } } }, "ldapauth-fork": { "version": "2.5.5", - "from": "ldapauth-fork@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-2.5.5.tgz", + "integrity": "sha1-qsK0cCLloj1nYLHVGKlpaVju5ns=", + "requires": { + "bcryptjs": "2.3.0", + "ldapjs": "1.0.1", + "lru-cache": "3.2.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "bunyan": { "version": "1.8.12", - "from": "bunyan@>=1.8.3 <2.0.0", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", + "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "requires": { + "dtrace-provider": "0.8.5", + "moment": "2.18.1", + "mv": "2.1.1", + "safe-json-stringify": "1.0.4" + }, "dependencies": { "dtrace-provider": { "version": "0.8.5", - "from": "dtrace-provider@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.5.tgz", - "optional": true + "integrity": "sha1-mOu6Ihr6xG4cOf02hY2Pk2dSS5I=", + "optional": true, + "requires": { + "nan": "2.3.5" + } } } }, "dtrace-provider": { "version": "0.7.1", - "from": "dtrace-provider@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.7.1.tgz", - "optional": true + "integrity": "sha1-wGswjy8Q1dWDiuycVx5dWI3HHQQ=", + "optional": true, + "requires": { + "nan": "2.3.5" + } }, "extsprintf": { "version": "1.2.0", - "from": "extsprintf@1.2.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", + "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" }, "glob": { "version": "6.0.4", - "from": "glob@>=6.0.1 <7.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "optional": true + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "optional": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } }, "ldapjs": { "version": "1.0.1", - "from": "ldapjs@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.1.tgz", + "integrity": "sha1-NSuBKudLCo6WVJpLiWBg7uG5pUY=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "backoff": "2.5.0", + "bunyan": "1.8.12", + "dashdash": "1.14.1", + "dtrace-provider": "0.7.1", + "ldap-filter": "0.2.2", + "once": "1.4.0", + "vasync": "1.6.4", + "verror": "1.10.0" + } }, "lru-cache": { "version": "3.2.0", - "from": "lru-cache@3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "requires": { + "pseudomap": "1.0.2" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "optional": true + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "optional": true, + "requires": { + "brace-expansion": "1.1.8" + } }, "mv": { "version": "2.1.1", - "from": "mv@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "optional": true + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "ncp": "2.0.0", + "rimraf": "2.4.5" + } }, "once": { "version": "1.4.0", - "from": "once@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } }, "rimraf": { "version": "2.4.5", - "from": "rimraf@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "optional": true + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "optional": true, + "requires": { + "glob": "6.0.4" + } }, "vasync": { "version": "1.6.4", - "from": "vasync@>=1.6.4 <2.0.0", "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz", + "integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=", + "requires": { + "verror": "1.6.0" + }, "dependencies": { "verror": { "version": "1.6.0", - "from": "verror@1.6.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", + "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=", + "requires": { + "extsprintf": "1.2.0" + } } } } @@ -2307,57 +3246,78 @@ }, "ldapjs": { "version": "0.7.1", - "from": "ldapjs@>=0.7.1 <0.8.0", "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-0.7.1.tgz", + "integrity": "sha1-aEeYpodkC6sa+9gCz1MvMEkt+1Y=", + "requires": { + "asn1": "0.2.1", + "assert-plus": "0.1.5", + "bunyan": "0.22.1", + "dtrace-provider": "0.2.8", + "nopt": "2.1.1", + "pooling": "0.4.6" + }, "dependencies": { "asn1": { "version": "0.2.1", - "from": "asn1@0.2.1", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.1.tgz", + "integrity": "sha1-7Mc/ddMeo8btnUdCjbNf7Meyxtw=" }, "assert-plus": { "version": "0.1.5", - "from": "assert-plus@0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" }, "nopt": { "version": "2.1.1", - "from": "nopt@2.1.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.1.tgz" + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.1.tgz", + "integrity": "sha1-ket8SwF+fACtytH9bWOUTQ/bdcE=", + "requires": { + "abbrev": "1.1.0" + } } } }, "less": { "version": "1.6.3", - "from": "less@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/less/-/less-1.6.3.tgz", + "integrity": "sha1-cc6J7DC3dLNWfyVMZ5WPLywZO94=", "dev": true, + "requires": { + "clean-css": "2.0.8", + "mime": "1.2.11", + "mkdirp": "0.3.5", + "request": "2.81.0", + "source-map": "0.1.34" + }, "dependencies": { "clean-css": { "version": "2.0.8", - "from": "clean-css@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.0.8.tgz", + "integrity": "sha1-6TfN/cxXgaAIF67EB56Fs+wVeiA=", "dev": true, - "optional": true + "optional": true, + "requires": { + "commander": "2.0.0" + } }, "commander": { "version": "2.0.0", - "from": "commander@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=", "dev": true, "optional": true }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", "dev": true, "optional": true }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@~0.3.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", "dev": true, "optional": true } @@ -2365,1063 +3325,1529 @@ }, "libbase64": { "version": "0.1.0", - "from": "libbase64@0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=" }, "libmime": { "version": "2.0.0", - "from": "libmime@2.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-2.0.0.tgz", + "integrity": "sha1-oXpo3E+igwu2SZ6x2jUJlnbIxyQ=", + "requires": { + "iconv-lite": "0.4.13", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, "dependencies": { "iconv-lite": { "version": "0.4.13", - "from": "iconv-lite@0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" } } }, "libqp": { "version": "1.1.0", - "from": "libqp@1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" }, "livereload-js": { "version": "2.2.2", - "from": "livereload-js@>=2.2.0 <3.0.0", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", "dev": true }, "loads": { "version": "0.0.4", - "from": "loads@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/loads/-/loads-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/loads/-/loads-0.0.4.tgz", + "integrity": "sha1-l/MBY5fnDd/0gLgexjjO6iKgqZw=", + "requires": { + "failure": "1.1.1", + "one-time": "0.0.4", + "xhr-response": "1.0.1", + "xhr-status": "1.0.0" + } }, "lodash": { "version": "4.17.4", - "from": "lodash@>=4.13.1 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "lodash.includes": { "version": "4.3.0", - "from": "lodash.includes@>=4.3.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" }, "lodash.isboolean": { "version": "3.0.3", - "from": "lodash.isboolean@>=3.0.3 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, "lodash.isinteger": { "version": "4.0.4", - "from": "lodash.isinteger@>=4.0.4 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" }, "lodash.isnumber": { "version": "3.0.3", - "from": "lodash.isnumber@>=3.0.3 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" }, "lodash.isplainobject": { "version": "4.0.6", - "from": "lodash.isplainobject@>=4.0.6 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" }, "lodash.isstring": { "version": "4.0.1", - "from": "lodash.isstring@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, "lodash.once": { "version": "4.1.1", - "from": "lodash.once@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, "lodash.reduce": { "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" }, "logger-sharelatex": { - "version": "1.5.6", - "from": "git+https://github.com/sharelatex/logger-sharelatex.git#master", - "resolved": "git+https://github.com/sharelatex/logger-sharelatex.git#b2956ec56b582b9f4fc8fdda8dc00c06e77c5537", + "version": "git+https://github.com/sharelatex/logger-sharelatex.git#b2956ec56b582b9f4fc8fdda8dc00c06e77c5537", + "requires": { + "bunyan": "1.5.1", + "chai": "4.1.2", + "coffee-script": "1.12.4", + "grunt": "0.4.5", + "grunt-bunyan": "0.5.0", + "grunt-contrib-clean": "0.6.0", + "grunt-contrib-coffee": "0.11.1", + "grunt-execute": "0.2.2", + "grunt-mocha-test": "0.11.0", + "raven": "1.2.1", + "sandboxed-module": "2.0.3", + "sinon": "3.2.1", + "timekeeper": "1.0.0" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" }, "ansi-styles": { "version": "1.1.0", - "from": "ansi-styles@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" }, "bunyan": { "version": "1.5.1", - "from": "bunyan@1.5.1", - "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.5.1.tgz", + "integrity": "sha1-X259RMQ7lS9WsPQTCeOrEjkbTi0=", + "requires": { + "dtrace-provider": "0.6.0", + "mv": "2.1.1", + "safe-json-stringify": "1.0.4" + } }, "chai": { "version": "4.1.2", - "from": "chai@latest", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz" + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.3" + } }, "chalk": { "version": "0.5.1", - "from": "chalk@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz" + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } }, "commander": { "version": "2.0.0", - "from": "commander@2.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=" }, "deep-eql": { "version": "3.0.1", - "from": "deep-eql@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "requires": { + "type-detect": "4.0.3" + } }, "dtrace-provider": { "version": "0.6.0", - "from": "dtrace-provider@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", - "optional": true + "integrity": "sha1-CweNVReTfYcxAUUtkUZzdVe3XlE=", + "optional": true, + "requires": { + "nan": "2.3.5" + } }, "formatio": { "version": "1.2.0", - "from": "formatio@1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "requires": { + "samsam": "1.2.1" + } }, "glob": { "version": "6.0.4", - "from": "glob@>=6.0.1 <7.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "optional": true + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "graceful-fs": { "version": "2.0.3", - "from": "graceful-fs@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=" }, "grunt-contrib-clean": { "version": "0.6.0", - "from": "grunt-contrib-clean@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.6.0.tgz", + "integrity": "sha1-9TLbpLghJnTHwBPhRr2mY4uQSPY=", + "requires": { + "rimraf": "2.2.8" + }, "dependencies": { "rimraf": { "version": "2.2.8", - "from": "rimraf@>=2.2.1 <2.3.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" } } }, "grunt-contrib-coffee": { "version": "0.11.1", - "from": "grunt-contrib-coffee@>=0.11.0 <0.12.0", "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.11.1.tgz", + "integrity": "sha1-+v48nuikQryNF9WlwZ/I5i2fP0U=", + "requires": { + "chalk": "0.5.1", + "coffee-script": "1.7.1", + "lodash": "2.4.2" + }, "dependencies": { "coffee-script": { "version": "1.7.1", - "from": "coffee-script@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "requires": { + "mkdirp": "0.3.5" + } }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" } } }, "grunt-mocha-test": { "version": "0.11.0", - "from": "grunt-mocha-test@>=0.11.0 <0.12.0", - "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.11.0.tgz" - }, - "has-ansi": { - "version": "0.1.0", - "from": "has-ansi@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz" - }, - "jade": { - "version": "0.26.3", - "from": "jade@0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.11.0.tgz", + "integrity": "sha1-deQboQdZDkrL0phgklwBLkQ8oyI=", + "requires": { + "fs-extra": "0.9.1", + "hooker": "0.2.3", + "mocha": "1.20.1" + }, "dependencies": { - "commander": { - "version": "0.6.1", - "from": "commander@0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" + "fs-extra": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.9.1.tgz", + "integrity": "sha1-h9v8ATg6jdzn2dVJbzYIVkiJ8VY=", + "requires": { + "jsonfile": "1.1.1", + "mkdirp": "0.5.1", + "ncp": "0.5.1", + "rimraf": "2.4.5" + } }, - "mkdirp": { - "version": "0.3.0", - "from": "mkdirp@0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + "ncp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", + "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=" } } }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "requires": { + "ansi-regex": "0.2.1" + } + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" + } + } + }, + "jsonfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.1.1.tgz", + "integrity": "sha1-2k/WrXfxolUgPqY8e8Mtwx72RDM=" + }, "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" }, "lolex": { "version": "2.1.2", - "from": "lolex@>=2.1.2 <3.0.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.1.2.tgz" + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.1.2.tgz", + "integrity": "sha1-JpS5U8nqTQE+W4v7qJHJkQJbJik=" }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "optional": true + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "mocha": { "version": "1.20.1", - "from": "mocha@>=1.20.0 <1.21.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.20.1.tgz", + "integrity": "sha1-80ODLZ/gx9l8ZPxwRI9RNt+f7Vs=", + "requires": { + "commander": "2.0.0", + "debug": "1.0.5", + "diff": "1.0.7", + "glob": "3.2.3", + "growl": "1.7.0", + "jade": "0.26.3", + "mkdirp": "0.3.5" + }, "dependencies": { "glob": { "version": "3.2.3", - "from": "glob@3.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } }, "minimatch": { "version": "0.2.14", - "from": "minimatch@>=0.2.11 <0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" } } }, "mv": { "version": "2.1.1", - "from": "mv@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "optional": true + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "ncp": "2.0.0", + "rimraf": "2.4.5" + } }, "path-to-regexp": { "version": "1.7.0", - "from": "path-to-regexp@>=1.7.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } }, "rimraf": { "version": "2.4.5", - "from": "rimraf@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "optional": true + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "requires": { + "glob": "6.0.4" + } }, "samsam": { "version": "1.2.1", - "from": "samsam@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.2.1.tgz", + "integrity": "sha1-7dOQk6MYQ3DLhZJDsr3yVefY6mc=" }, "sandboxed-module": { "version": "2.0.3", - "from": "sandboxed-module@latest", - "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-2.0.3.tgz", + "integrity": "sha1-x+VFkzm7y6KMUwPusz9ug4e/upY=", + "requires": { + "require-like": "0.1.2", + "stack-trace": "0.0.9" + } }, "sinon": { "version": "3.2.1", - "from": "sinon@latest", "resolved": "https://registry.npmjs.org/sinon/-/sinon-3.2.1.tgz", + "integrity": "sha1-2K2r2QBzD9SXeIoCcEnGSwi+kcI=", + "requires": { + "diff": "3.3.1", + "formatio": "1.2.0", + "lolex": "2.1.2", + "native-promise-only": "0.8.1", + "nise": "1.0.1", + "path-to-regexp": "1.7.0", + "samsam": "1.2.1", + "text-encoding": "0.6.4", + "type-detect": "4.0.3" + }, "dependencies": { "diff": { "version": "3.3.1", - "from": "diff@>=3.1.0 <4.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz" + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=" } } }, "strip-ansi": { "version": "0.3.0", - "from": "strip-ansi@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "requires": { + "ansi-regex": "0.2.1" + } }, "supports-color": { "version": "0.2.0", - "from": "supports-color@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" }, "timekeeper": { "version": "1.0.0", - "from": "timekeeper@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-1.0.0.tgz", + "integrity": "sha1-Lziu4elLEd1m2FgP8aqdzGoroNg=" }, "type-detect": { "version": "4.0.3", - "from": "type-detect@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz" + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=" } } }, "lolex": { "version": "1.3.2", - "from": "lolex@1.3.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, "longest": { "version": "1.0.1", - "from": "longest@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "lpad": { "version": "0.1.0", - "from": "lpad@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lpad/-/lpad-0.1.0.tgz", + "integrity": "sha1-5MYMKROTIcWXDeSTtJauDXdM0qc=", "dev": true }, "lru-cache": { "version": "2.7.3", - "from": "lru-cache@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" }, "lsmod": { "version": "1.0.0", - "from": "lsmod@1.0.0", - "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz", + "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks=" }, "lynx": { "version": "0.1.1", - "from": "lynx@0.1.1", - "resolved": "https://registry.npmjs.org/lynx/-/lynx-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/lynx/-/lynx-0.1.1.tgz", + "integrity": "sha1-Mxjc7xaQi4KG6Bisz9sxzXQkj50=", + "requires": { + "mersenne": "0.0.4", + "statsd-parser": "0.0.4" + } }, "mailcomposer": { "version": "3.3.2", - "from": "mailcomposer@3.3.2", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-3.3.2.tgz" + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-3.3.2.tgz", + "integrity": "sha1-IFUjzIcu39UOyAp1F1SeCxuug00=", + "requires": { + "buildmail": "3.3.2", + "libmime": "2.0.0" + } }, "marked": { "version": "0.3.6", - "from": "marked@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz" + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", + "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=" }, "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "merge-descriptors": { "version": "1.0.0", - "from": "merge-descriptors@1.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.0.tgz", + "integrity": "sha1-IWnPdTjhsMyH+4jhUC2EdLv3mGQ=" }, "mersenne": { "version": "0.0.4", - "from": "mersenne@>=0.0.3 <0.1.0", - "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.4.tgz", + "integrity": "sha1-QB/ex+whzbngPNPTAhOY2iGycIU=" }, "method-override": { "version": "2.3.9", - "from": "method-override@>=2.3.3 <3.0.0", "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.9.tgz", + "integrity": "sha1-vRUfLONM8Bp2ykAKuVwBKxAtj3E=", + "requires": { + "debug": "2.6.8", + "methods": "1.1.2", + "parseurl": "1.3.2", + "vary": "1.1.1" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "vary": { "version": "1.1.1", - "from": "vary@>=1.1.1 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=" } } }, "methods": { "version": "1.1.2", - "from": "methods@>=1.1.1 <1.2.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "metrics-sharelatex": { - "version": "1.7.1", - "from": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.7.1", - "resolved": "git+https://github.com/sharelatex/metrics-sharelatex.git#166961924c599b1f9468f2e17846fa2a9d12372d", + "version": "git+https://github.com/sharelatex/metrics-sharelatex.git#166961924c599b1f9468f2e17846fa2a9d12372d", + "requires": { + "coffee-script": "1.6.0", + "lynx": "0.1.1", + "underscore": "1.6.0" + }, "dependencies": { "coffee-script": { "version": "1.6.0", - "from": "coffee-script@1.6.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz", + "integrity": "sha1-gIs5bhEPU9AhoZpO8fZb4OjjX6M=" } } }, "microtime-nodejs": { "version": "1.0.0", - "from": "microtime-nodejs@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/microtime-nodejs/-/microtime-nodejs-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/microtime-nodejs/-/microtime-nodejs-1.0.0.tgz", + "integrity": "sha1-iFlASvLipGKhXJzWvyxORo2r2+g=" }, "mime": { "version": "1.3.4", - "from": "mime@1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" }, "mime-db": { "version": "1.30.0", - "from": "mime-db@>=1.30.0 <1.31.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" }, "mime-types": { "version": "2.1.17", - "from": "mime-types@>=2.1.7 <2.2.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + "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" + } }, "mimelib": { "version": "0.2.14", - "from": "mimelib@0.2.14", - "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz" + "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz", + "integrity": "sha1-KhqnJL0ZC4W9Um5jF6thBu39aDE=", + "requires": { + "addressparser": "0.2.1", + "encoding": "0.1.12" + } }, "minimatch": { "version": "0.2.14", - "from": "minimatch@>=0.2.12 <0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } }, "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", - "from": "mkdirp@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } }, "mocha": { "version": "1.17.1", - "from": "mocha@1.17.1", "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.17.1.tgz", + "integrity": "sha1-f3Zx1oUm0HS3uuZgyQmfh+DqHMs=", + "requires": { + "commander": "2.0.0", + "debug": "1.0.5", + "diff": "1.0.7", + "glob": "3.2.3", + "growl": "1.7.0", + "jade": "0.26.3", + "mkdirp": "0.3.5" + }, "dependencies": { "commander": { "version": "2.0.0", - "from": "commander@2.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=" }, "glob": { "version": "3.2.3", - "from": "glob@3.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } }, "graceful-fs": { "version": "2.0.3", - "from": "graceful-fs@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=" }, "jade": { "version": "0.26.3", - "from": "jade@0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, "dependencies": { "commander": { "version": "0.6.1", - "from": "commander@0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" }, "mkdirp": { "version": "0.3.0", - "from": "mkdirp@0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" } } }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" } } }, "moment": { "version": "2.18.1", - "from": "moment@>=2.10.6 <3.0.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz" + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" }, "moment-timezone": { "version": "0.5.13", - "from": "moment-timezone@>=0.5.4 <0.6.0", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.13.tgz" + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.13.tgz", + "integrity": "sha1-mc5cfYJyYusPH3AgRBd/YHRde5A=", + "requires": { + "moment": "2.18.1" + } }, "mongodb": { "version": "2.2.31", - "from": "mongodb@>=2.0.45 <3.0.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.31.tgz", + "integrity": "sha1-GUBEXGYeGSF7s7+CRdmFSq71SNs=", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.15", + "readable-stream": "2.2.7" + }, "dependencies": { "es6-promise": { "version": "3.2.1", - "from": "es6-promise@3.2.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz" + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" }, "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.2.7", - "from": "readable-stream@2.2.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } } } }, "mongodb-core": { "version": "2.1.15", - "from": "mongodb-core@2.1.15", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz" + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz", + "integrity": "sha1-hB9TuH//9MdFgYnDXIroJ+EWl2Q=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" + } }, "mongojs": { "version": "2.4.0", - "from": "mongojs@2.4.0", "resolved": "https://registry.npmjs.org/mongojs/-/mongojs-2.4.0.tgz", + "integrity": "sha1-8of7/UV/7fWItakBHmhRPZ3TK/s=", + "requires": { + "each-series": "1.0.0", + "mongodb": "2.2.31", + "once": "1.3.3", + "parse-mongo-url": "1.1.1", + "readable-stream": "2.3.3", + "thunky": "0.1.0", + "to-mongodb-core": "2.0.0", + "xtend": "4.0.1" + }, "dependencies": { "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.3", - "from": "readable-stream@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "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" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } } } }, "mongoose": { "version": "4.11.4", - "from": "mongoose@4.11.4", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.11.4.tgz", + "integrity": "sha1-PXQREQXui2GescHXkOe/xOjLp7s=", + "requires": { + "async": "2.1.4", + "bson": "1.0.4", + "hooks-fixed": "2.0.0", + "kareem": "1.5.0", + "mongodb": "2.2.27", + "mpath": "0.3.0", + "mpromise": "0.5.5", + "mquery": "2.3.1", + "ms": "2.0.0", + "muri": "1.2.2", + "regexp-clone": "0.0.1", + "sliced": "1.0.1" + }, "dependencies": { "async": { "version": "2.1.4", - "from": "async@2.1.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", + "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", + "requires": { + "lodash": "4.17.4" + } }, "es6-promise": { "version": "3.2.1", - "from": "es6-promise@3.2.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz" + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" }, "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "mongodb": { "version": "2.2.27", - "from": "mongodb@2.2.27", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.27.tgz" + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.27.tgz", + "integrity": "sha1-NBIgNNtm2YO89qta2yaiSnD+9uY=", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.11", + "readable-stream": "2.2.7" + } }, "mongodb-core": { "version": "2.1.11", - "from": "mongodb-core@2.1.11", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.11.tgz" + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.11.tgz", + "integrity": "sha1-HDh3bOsXSZepnCiGDu2QKNqbPho=", + "requires": { + "bson": "1.0.4", + "require_optional": "1.0.1" + } }, "readable-stream": { "version": "2.2.7", - "from": "readable-stream@2.2.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } } } }, "monocle": { "version": "1.1.51", - "from": "monocle@1.1.51", - "resolved": "https://registry.npmjs.org/monocle/-/monocle-1.1.51.tgz" + "resolved": "https://registry.npmjs.org/monocle/-/monocle-1.1.51.tgz", + "integrity": "sha1-Iu0W4RLpsFZ2nFzKySDjdSSdicA=", + "requires": { + "readdirp": "0.2.5" + } }, "mpath": { "version": "0.3.0", - "from": "mpath@0.3.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", + "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" }, "mpromise": { "version": "0.5.5", - "from": "mpromise@0.5.5", - "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz" + "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", + "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" }, "mquery": { "version": "2.3.1", - "from": "mquery@2.3.1", "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.1.tgz", + "integrity": "sha1-mrNnSXFIAP8LtTpoHOS8TV8HyHs=", + "requires": { + "bluebird": "2.10.2", + "debug": "2.6.8", + "regexp-clone": "0.0.1", + "sliced": "0.0.5" + }, "dependencies": { "bluebird": { "version": "2.10.2", - "from": "bluebird@2.10.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz" + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", + "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=" }, "debug": { "version": "2.6.8", - "from": "debug@2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "sliced": { "version": "0.0.5", - "from": "sliced@0.0.5", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", + "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" } } }, "ms": { "version": "2.0.0", - "from": "ms@2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multer": { "version": "0.1.8", - "from": "multer@>=0.1.8 <0.2.0", "resolved": "https://registry.npmjs.org/multer/-/multer-0.1.8.tgz", + "integrity": "sha1-VRuKYBUJNwG8rMlkkWsa4GV483s=", + "requires": { + "busboy": "0.2.14", + "mkdirp": "0.3.5", + "qs": "1.2.2", + "type-is": "1.5.7" + }, "dependencies": { "mime-db": { "version": "1.12.0", - "from": "mime-db@>=1.12.0 <1.13.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz" + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=" }, "mime-types": { "version": "2.0.14", - "from": "mime-types@>=2.0.9 <2.1.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz" + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "requires": { + "mime-db": "1.12.0" + } }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" }, "qs": { "version": "1.2.2", - "from": "qs@>=1.2.2 <1.3.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=" }, "type-is": { "version": "1.5.7", - "from": "type-is@>=1.5.2 <1.6.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz" + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", + "integrity": "sha1-uTaKWTzG730GReeLL0xky+zQXpA=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.0.14" + } } } }, "muri": { "version": "1.2.2", - "from": "muri@1.2.2", - "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz", + "integrity": "sha1-YxmBMmUNsIoEzHnM0A3Tia/SYxw=" }, "mute-stream": { "version": "0.0.7", - "from": "mute-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "mv": { "version": "0.0.5", - "from": "mv@0.0.5", "resolved": "https://registry.npmjs.org/mv/-/mv-0.0.5.tgz", + "integrity": "sha1-FerHWUeYhN8RMdbeVrziC2VPU5E=", "optional": true }, "nan": { "version": "2.3.5", - "from": "nan@2.3.5", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz" + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz", + "integrity": "sha1-gioNwmYpDOTNOhIoLKPn42Rmigg=" }, "native-promise-only": { "version": "0.8.1", - "from": "native-promise-only@>=0.8.1 <0.9.0", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz" + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=" }, "nconf": { "version": "0.6.9", - "from": "nconf@>=0.6.9 <0.7.0", "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.6.9.tgz", + "integrity": "sha1-lXDvFe1vmuays8jV5xtm0xk81mE=", "dev": true, + "requires": { + "async": "0.2.9", + "ini": "1.3.4", + "optimist": "0.6.0" + }, "dependencies": { "async": { "version": "0.2.9", - "from": "async@0.2.9", "resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz", + "integrity": "sha1-32MGD789Myhqdqr21Vophtn/hhk=", "dev": true }, "optimist": { "version": "0.6.0", - "from": "optimist@0.6.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", - "dev": true + "integrity": "sha1-aUJIJvNAX3nxQub8PZrljU27kgA=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.2" + } } } }, "ncp": { "version": "2.0.0", - "from": "ncp@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "optional": true }, "negotiator": { "version": "0.5.3", - "from": "negotiator@0.5.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=" }, "nise": { "version": "1.0.1", - "from": "nise@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/nise/-/nise-1.0.1.tgz", + "integrity": "sha1-DakrEKhU6XwPSW9sKEWjASgLPu8=", + "requires": { + "formatio": "1.2.0", + "just-extend": "1.1.22", + "lolex": "1.6.0", + "path-to-regexp": "1.7.0" + }, "dependencies": { "formatio": { "version": "1.2.0", - "from": "formatio@^1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "requires": { + "samsam": "1.1.2" + } }, "lolex": { "version": "1.6.0", - "from": "lolex@>=1.6.0 <2.0.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=" }, "path-to-regexp": { "version": "1.7.0", - "from": "path-to-regexp@^1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } } } }, "nocache": { "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", + "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, "node-forge": { "version": "0.2.24", - "from": "node-forge@0.2.24", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.2.24.tgz" + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.2.24.tgz", + "integrity": "sha1-+m+Eb0L6k/Y6CjDJ+/97ThMOCFg=" }, "node-html-encoder": { "version": "0.0.2", - "from": "node-html-encoder@0.0.2", - "resolved": "https://registry.npmjs.org/node-html-encoder/-/node-html-encoder-0.0.2.tgz" + "resolved": "https://registry.npmjs.org/node-html-encoder/-/node-html-encoder-0.0.2.tgz", + "integrity": "sha1-iXNhjXJ9pVJqgwtH0HwNgD4KFcY=" }, "node-pre-gyp": { "version": "0.6.30", - "from": "node-pre-gyp@0.6.30", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.30.tgz", + "integrity": "sha1-ZNMHOm9XMANxfM/jDIkCMpe6u6E=", + "requires": { + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "rc": "1.1.7", + "request": "2.81.0", + "rimraf": "2.5.4", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.1.4" + }, "dependencies": { "glob": { "version": "7.1.2", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "rimraf": { "version": "2.5.4", - "from": "rimraf@>=2.5.0 <2.6.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "requires": { + "glob": "7.1.2" + } } } }, "nodemailer": { "version": "2.1.0", - "from": "nodemailer@2.1.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.1.0.tgz", + "integrity": "sha1-zxCt/eblwfEL6pcAcavZ6DoJ0/Q=", + "requires": { + "libmime": "2.0.0", + "mailcomposer": "3.3.2", + "nodemailer-direct-transport": "2.0.1", + "nodemailer-shared": "1.0.3", + "nodemailer-smtp-pool": "2.1.0", + "nodemailer-smtp-transport": "2.0.1" + } }, "nodemailer-direct-transport": { "version": "2.0.1", - "from": "nodemailer-direct-transport@2.0.1", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-2.0.1.tgz", + "integrity": "sha1-qcb0mhz//84F3jaPOJojmP+TzLM=", + "requires": { + "nodemailer-shared": "1.0.3", + "smtp-connection": "2.0.1" + } }, "nodemailer-fetch": { "version": "1.2.1", - "from": "nodemailer-fetch@1.2.1", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.2.1.tgz", + "integrity": "sha1-78GM7CBbT/BR0gWHPXkGStGFCeM=" }, "nodemailer-sendgrid-transport": { "version": "0.2.0", - "from": "nodemailer-sendgrid-transport@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/nodemailer-sendgrid-transport/-/nodemailer-sendgrid-transport-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-sendgrid-transport/-/nodemailer-sendgrid-transport-0.2.0.tgz", + "integrity": "sha1-pRZZO/49HyeM/hcGDh2yNlio9Pw=", + "requires": { + "sendgrid": "1.9.2" + } }, "nodemailer-ses-transport": { "version": "1.5.1", - "from": "nodemailer-ses-transport@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/nodemailer-ses-transport/-/nodemailer-ses-transport-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-ses-transport/-/nodemailer-ses-transport-1.5.1.tgz", + "integrity": "sha1-3AWYwb9T6GUuYy6PMWks4CLX3qk=", + "requires": { + "aws-sdk": "2.113.0" + } }, "nodemailer-shared": { "version": "1.0.3", - "from": "nodemailer-shared@1.0.3", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.0.3.tgz", + "integrity": "sha1-99Zf9ywCnY8d2KaLgBGGIZLcogA=", + "requires": { + "nodemailer-fetch": "1.2.1" + } }, "nodemailer-smtp-pool": { "version": "2.1.0", - "from": "nodemailer-smtp-pool@2.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.1.0.tgz", + "integrity": "sha1-Nn10/pyJ8SnJnXuhbnJqa++u7Mg=", + "requires": { + "clone": "1.0.2", + "nodemailer-shared": "1.0.3", + "nodemailer-wellknown": "0.1.7", + "smtp-connection": "2.0.1" + } }, "nodemailer-smtp-transport": { "version": "2.0.1", - "from": "nodemailer-smtp-transport@2.0.1", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.0.1.tgz", + "integrity": "sha1-KZqulFCpAxjDSPrSc26ihIFURGY=", + "requires": { + "clone": "1.0.2", + "nodemailer-shared": "1.0.3", + "nodemailer-wellknown": "0.1.7", + "smtp-connection": "2.0.1" + } }, "nodemailer-wellknown": { "version": "0.1.7", - "from": "nodemailer-wellknown@0.1.7", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz" + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz", + "integrity": "sha1-qmQZkKmfqAqdqKI1YpBUd8zu5V8=" }, "nomnom": { "version": "1.6.2", - "from": "nomnom@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", + "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", "dev": true, + "requires": { + "colors": "0.5.1", + "underscore": "1.4.4" + }, "dependencies": { "colors": { "version": "0.5.1", - "from": "colors@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", "dev": true }, "underscore": { "version": "1.4.4", - "from": "underscore@>=1.4.4 <1.5.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", "dev": true } } }, "nopt": { "version": "3.0.6", - "from": "nopt@>=3.0.1 <3.1.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.0" + } }, "normalize-range": { "version": "0.1.2", - "from": "normalize-range@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, "npm-run-path": { "version": "2.0.2", - "from": "npm-run-path@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "dev": true + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } }, "npmlog": { "version": "4.1.2", - "from": "npmlog@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } }, "nssocket": { "version": "0.5.3", - "from": "nssocket@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.5.3.tgz", - "dev": true + "integrity": "sha1-iDyi7GBfXtZKTVGQsmJUAZKPj40=", + "dev": true, + "requires": { + "eventemitter2": "0.4.14", + "lazy": "1.0.11" + } }, "num2fraction": { "version": "1.2.2", - "from": "num2fraction@>=1.2.2 <2.0.0", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, "number-is-nan": { "version": "1.0.1", - "from": "number-is-nan@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth": { "version": "0.9.15", - "from": "oauth@>=0.9.0 <0.10.0", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz" + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" }, "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" + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.1", - "from": "object-assign@>=4.1.0 <5.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { "version": "1.3.0", - "from": "object-inspect@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.3.0.tgz", + "integrity": "sha1-Wx645nQuLugzQqY3A02ESSi6L20=" }, "object-keys": { "version": "1.0.11", - "from": "object-keys@>=1.0.8 <2.0.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" }, "on-finished": { "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } }, "on-headers": { "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, "once": { "version": "1.3.3", - "from": "once@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1.0.2" + } }, "one-time": { "version": "0.0.4", - "from": "one-time@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" }, "onesky": { "version": "0.1.6", - "from": "onesky@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/onesky/-/onesky-0.1.6.tgz", + "integrity": "sha1-fw1oy4DN/51ETHzVURZdgow0zaw=", "dev": true, + "requires": { + "request": "2.40.0", + "underscore": "1.6.0" + }, "dependencies": { "asn1": { "version": "0.1.11", - "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", "dev": true, "optional": true }, "assert-plus": { "version": "0.1.5", - "from": "assert-plus@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", "dev": true, "optional": true }, "async": { "version": "0.9.2", - "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true, "optional": true }, "aws-sign2": { "version": "0.5.0", - "from": "aws-sign2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", "dev": true, "optional": true }, "boom": { "version": "0.4.2", - "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "dev": true + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } }, "combined-stream": { "version": "0.0.7", - "from": "combined-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", "dev": true, - "optional": true + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", "dev": true, - "optional": true + "optional": true, + "requires": { + "boom": "0.4.2" + } }, "delayed-stream": { "version": "0.0.5", - "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", "dev": true, "optional": true }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", "dev": true }, "form-data": { "version": "0.1.4", - "from": "form-data@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + } }, "hawk": { "version": "1.1.1", - "from": "hawk@1.1.1", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", "dev": true, - "optional": true + "optional": true, + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } }, "hoek": { "version": "0.9.1", - "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", "dev": true }, "http-signature": { "version": "0.10.1", - "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", "dev": true, - "optional": true + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", "dev": true, "optional": true }, "mime-types": { "version": "1.0.2", - "from": "mime-types@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", "dev": true }, "node-uuid": { "version": "1.4.8", - "from": "node-uuid@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", "dev": true, "optional": true }, "qs": { "version": "1.0.2", - "from": "qs@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "integrity": "sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g=", "dev": true }, "request": { "version": "2.40.0", - "from": "request@>=2.40.0 <2.41.0", "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", - "dev": true + "integrity": "sha1-TdZw9pbx5uhC5mtLXoOTAaub62c=", + "dev": true, + "requires": { + "aws-sign2": "0.5.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.3.0", + "qs": "1.0.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.4.3" + } }, "sntp": { "version": "0.2.4", - "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", "dev": true, - "optional": true + "optional": true, + "requires": { + "hoek": "0.9.1" + } }, "tunnel-agent": { "version": "0.4.3", - "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true, "optional": true } @@ -3429,1263 +4855,1866 @@ }, "optimist": { "version": "0.6.1", - "from": "optimist@0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz" + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.2" + } }, "os-homedir": { "version": "1.0.2", - "from": "os-homedir@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { "version": "1.0.2", - "from": "os-tmpdir@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { "version": "0.1.4", - "from": "osenv@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } }, "parse-mongo-url": { "version": "1.1.1", - "from": "parse-mongo-url@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz", + "integrity": "sha1-ZiON9fjnwMjKTNlw1KtqE3PrdbU=" }, "parseurl": { "version": "1.3.2", - "from": "parseurl@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "passport": { "version": "0.3.2", - "from": "passport@>=0.3.2 <0.4.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/passport/-/passport-0.3.2.tgz", + "integrity": "sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI=", + "requires": { + "passport-strategy": "1.0.0", + "pause": "0.0.1" + } }, "passport-ldapauth": { "version": "0.6.0", - "from": "passport-ldapauth@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-0.6.0.tgz" + "resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-0.6.0.tgz", + "integrity": "sha1-SCnrBz4fRjL649F5Xn4PSa9Gv5I=", + "requires": { + "ldapauth-fork": "2.5.5", + "passport-strategy": "1.0.0" + } }, "passport-local": { "version": "1.0.0", - "from": "passport-local@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.0.0" + } }, "passport-oauth2": { "version": "1.4.0", - "from": "passport-oauth2@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz", + "integrity": "sha1-9i+BWDy+EmCb585vFguTlaJ7hq0=", + "requires": { + "oauth": "0.9.15", + "passport-strategy": "1.0.0", + "uid2": "0.0.3", + "utils-merge": "1.0.0" + } }, "passport-oauth2-refresh": { "version": "1.0.0", - "from": "passport-oauth2-refresh@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/passport-oauth2-refresh/-/passport-oauth2-refresh-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/passport-oauth2-refresh/-/passport-oauth2-refresh-1.0.0.tgz", + "integrity": "sha1-hvOFco9dbTPrkRwlKcG+I60yS88=" }, "passport-saml": { "version": "0.15.0", - "from": "passport-saml@>=0.15.0 <0.16.0", "resolved": "https://registry.npmjs.org/passport-saml/-/passport-saml-0.15.0.tgz", + "integrity": "sha1-fUXAe6r4DY4s+Jg2cTKl5MBTXK0=", + "requires": { + "passport-strategy": "1.0.0", + "q": "1.1.2", + "xml-crypto": "0.8.5", + "xml-encryption": "0.7.4", + "xml2js": "0.4.19", + "xmlbuilder": "2.5.2", + "xmldom": "0.1.27" + }, "dependencies": { "lodash": { "version": "3.2.0", - "from": "lodash@>=3.2.0 <3.3.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", + "integrity": "sha1-S/UKMkP5rrC6xBpV09WZBnWkYvs=" }, "xml2js": { "version": "0.4.19", - "from": "xml2js@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "9.0.4" + }, "dependencies": { "xmlbuilder": { "version": "9.0.4", - "from": "xmlbuilder@>=9.0.1 <9.1.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz" + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", + "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=" } } }, "xmlbuilder": { "version": "2.5.2", - "from": "xmlbuilder@>=2.5.0 <2.6.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.5.2.tgz" + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.5.2.tgz", + "integrity": "sha1-WriPxQirL/FIcwELVhY9P5KxkyU=", + "requires": { + "lodash": "3.2.0" + } } } }, "passport-strategy": { "version": "1.0.0", - "from": "passport-strategy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" }, "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" + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "2.0.1", - "from": "path-key@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { "version": "1.0.5", - "from": "path-parse@>=1.0.5 <2.0.0", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, "path-to-regexp": { "version": "0.1.6", - "from": "path-to-regexp@0.1.6", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.6.tgz" + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.6.tgz", + "integrity": "sha1-8B/Vc0BHtr+8XyCMYTWjPXrwnDY=" }, "pathval": { "version": "1.1.0", - "from": "pathval@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "pause": { "version": "0.0.1", - "from": "pause@0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, "performance-now": { "version": "0.2.0", - "from": "performance-now@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" }, "pkginfo": { "version": "0.3.1", - "from": "pkginfo@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", "dev": true }, "platform": { "version": "1.3.4", - "from": "platform@1.3.4", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz" + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", + "integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0=" }, "pooling": { "version": "0.4.6", - "from": "pooling@0.4.6", "resolved": "https://registry.npmjs.org/pooling/-/pooling-0.4.6.tgz", + "integrity": "sha1-dqMXNx6oo2O0hY+keZ5gJF8w5mQ=", + "requires": { + "assert-plus": "0.1.5", + "bunyan": "0.22.1", + "dtrace-provider": "0.2.8", + "once": "1.3.0", + "vasync": "1.4.0" + }, "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "assert-plus@0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" }, "once": { "version": "1.3.0", - "from": "once@1.3.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/once/-/once-1.3.0.tgz", + "integrity": "sha1-FRr4a/wfCMS58H0GqyUP/L61ZYE=" } } }, "postcss": { "version": "5.2.17", - "from": "postcss@>=5.2.16 <6.0.0", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", + "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=", "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.3.2", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, "dependencies": { "source-map": { "version": "0.5.7", - "from": "source-map@>=0.5.6 <0.6.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "postcss-value-parser": { "version": "3.3.0", - "from": "postcss-value-parser@>=3.2.3 <4.0.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", "dev": true }, "precond": { "version": "0.2.3", - "from": "precond@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" }, "process-nextick-args": { "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "promise": { "version": "2.0.0", - "from": "promise@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz", + "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=", + "requires": { + "is-promise": "1.0.1" + } }, "prompt": { "version": "0.2.14", - "from": "prompt@0.2.14", "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", - "dev": true + "integrity": "sha1-V3VPZPVD/XsIRXB8gY7OYY8F/9w=", + "dev": true, + "requires": { + "pkginfo": "0.3.1", + "read": "1.0.7", + "revalidator": "0.1.8", + "utile": "0.2.1", + "winston": "0.8.3" + } }, "proxy-addr": { "version": "1.0.10", - "from": "proxy-addr@>=1.0.8 <1.1.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz" + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", + "integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=", + "requires": { + "forwarded": "0.1.1", + "ipaddr.js": "1.0.5" + } }, "ps-tree": { "version": "0.0.3", - "from": "ps-tree@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-0.0.3.tgz", - "dev": true + "integrity": "sha1-2/jXUqf+Ivp9WGNWiUmWEOknbdw=", + "dev": true, + "requires": { + "event-stream": "0.5.3" + } }, "pseudomap": { "version": "1.0.2", - "from": "pseudomap@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "pug": { "version": "2.0.0-rc.4", - "from": "pug@>=2.0.0-beta6 <3.0.0", - "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.4.tgz" + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.4.tgz", + "integrity": "sha1-t7CPZZm9UwJWgEK3Q2mE+yjIChM=", + "requires": { + "pug-code-gen": "2.0.0", + "pug-filters": "2.1.5", + "pug-lexer": "3.1.0", + "pug-linker": "3.0.3", + "pug-load": "2.0.9", + "pug-parser": "4.0.0", + "pug-runtime": "2.0.3", + "pug-strip-comments": "1.0.2" + } }, "pug-attrs": { "version": "2.0.2", - "from": "pug-attrs@>=2.0.2 <3.0.0", "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.2.tgz", + "integrity": "sha1-i+KyIlVo/6ddG4Zpgr/59BEa/8s=", + "requires": { + "constantinople": "3.1.0", + "js-stringify": "1.0.2", + "pug-runtime": "2.0.3" + }, "dependencies": { "constantinople": { "version": "3.1.0", - "from": "constantinople@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz" + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", + "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", + "requires": { + "acorn": "3.3.0", + "is-expression": "2.1.0" + } } } }, "pug-code-gen": { "version": "2.0.0", - "from": "pug-code-gen@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.0.tgz", + "integrity": "sha1-lq6jmp5i8exdK2pbQqKdUoxwtD0=", + "requires": { + "constantinople": "3.1.0", + "doctypes": "1.1.0", + "js-stringify": "1.0.2", + "pug-attrs": "2.0.2", + "pug-error": "1.3.2", + "pug-runtime": "2.0.3", + "void-elements": "2.0.1", + "with": "5.1.1" + }, "dependencies": { "constantinople": { "version": "3.1.0", - "from": "constantinople@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz" + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", + "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", + "requires": { + "acorn": "3.3.0", + "is-expression": "2.1.0" + } }, "with": { "version": "5.1.1", - "from": "with@>=5.0.0 <6.0.0", - "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz" + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", + "requires": { + "acorn": "3.3.0", + "acorn-globals": "3.1.0" + } } } }, "pug-error": { "version": "1.3.2", - "from": "pug-error@>=1.3.2 <2.0.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz" + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz", + "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" }, "pug-filters": { "version": "2.1.5", - "from": "pug-filters@>=2.1.5 <3.0.0", "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz", + "integrity": "sha1-Zr9ugNl/vvgpurCqNe3f8z/JZPM=", + "requires": { + "clean-css": "3.4.28", + "constantinople": "3.1.0", + "jstransformer": "1.0.0", + "pug-error": "1.3.2", + "pug-walk": "1.1.5", + "resolve": "1.4.0", + "uglify-js": "2.8.29" + }, "dependencies": { "constantinople": { "version": "3.1.0", - "from": "constantinople@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz" + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", + "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", + "requires": { + "acorn": "3.3.0", + "is-expression": "2.1.0" + } }, "source-map": { "version": "0.5.7", - "from": "source-map@>=0.5.1 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "uglify-js": { "version": "2.8.29", - "from": "uglify-js@>=2.6.1 <3.0.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz" + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } }, "yargs": { "version": "3.10.0", - "from": "yargs@>=3.10.0 <3.11.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } } } }, "pug-lexer": { "version": "3.1.0", - "from": "pug-lexer@>=3.1.0 <4.0.0", "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", + "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", + "requires": { + "character-parser": "2.2.0", + "is-expression": "3.0.0", + "pug-error": "1.3.2" + }, "dependencies": { "acorn": { "version": "4.0.13", - "from": "acorn@>=4.0.2 <4.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" }, "character-parser": { "version": "2.2.0", - "from": "character-parser@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "requires": { + "is-regex": "1.0.4" + } }, "is-expression": { "version": "3.0.0", - "from": "is-expression@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", + "requires": { + "acorn": "4.0.13", + "object-assign": "4.1.1" + } } } }, "pug-linker": { "version": "3.0.3", - "from": "pug-linker@>=3.0.3 <4.0.0", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.3.tgz", + "integrity": "sha1-JfWet1AjfwNo5ZwzeXZCKcAYnEE=", + "requires": { + "pug-error": "1.3.2", + "pug-walk": "1.1.5" + } }, "pug-load": { "version": "2.0.9", - "from": "pug-load@>=2.0.9 <3.0.0", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.9.tgz" + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.9.tgz", + "integrity": "sha1-7iF8kUzB2TJNRLhsMtHfJB023no=", + "requires": { + "object-assign": "4.1.1", + "pug-walk": "1.1.5" + } }, "pug-parser": { "version": "4.0.0", - "from": "pug-parser@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.0.tgz", + "integrity": "sha1-yfUjIuTqvkv1vuumTtGDc7tieAE=", + "requires": { + "pug-error": "1.3.2", + "token-stream": "0.0.1" + } }, "pug-runtime": { "version": "2.0.3", - "from": "pug-runtime@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz", + "integrity": "sha1-mBYmB7D86eJU1CfzOYelrucWi9o=" }, "pug-strip-comments": { "version": "1.0.2", - "from": "pug-strip-comments@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz", + "integrity": "sha1-0xOvoBvMN0mA4TmeI+vy65vchRM=", + "requires": { + "pug-error": "1.3.2" + } }, "pug-walk": { "version": "1.1.5", - "from": "pug-walk@>=1.1.5 <2.0.0", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.5.tgz" + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.5.tgz", + "integrity": "sha1-kOlDrLz3Ah5kVM8bMiRYkcum+FE=" }, "punycode": { "version": "1.4.1", - "from": "punycode@>=1.4.1 <2.0.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "q": { "version": "1.1.2", - "from": "q@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", + "integrity": "sha1-Y1fikSBnAdmfGXq4TlforRlvKok=" }, "qs": { "version": "6.4.0", - "from": "qs@>=6.4.0 <6.5.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" }, "querystring": { "version": "0.2.0", - "from": "querystring@0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "random-bytes": { "version": "1.0.0", - "from": "random-bytes@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" }, "range-parser": { "version": "1.0.3", - "from": "range-parser@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=" }, "raven": { "version": "1.2.1", - "from": "raven@>=1.1.3 <2.0.0", "resolved": "https://registry.npmjs.org/raven/-/raven-1.2.1.tgz", + "integrity": "sha1-lJwTTbAooZC3u/j3kKrlQbfAIL0=", + "requires": { + "cookie": "0.3.1", + "json-stringify-safe": "5.0.1", + "lsmod": "1.0.0", + "stack-trace": "0.0.9", + "uuid": "3.0.0" + }, "dependencies": { "cookie": { "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "uuid": { "version": "3.0.0", - "from": "uuid@3.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz", + "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg=" } } }, "raw-body": { "version": "2.3.1", - "from": "raw-body@2.3.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.1.tgz", + "integrity": "sha1-MPleKmehTi5EE9jVH92SyHfo8u0=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.18", + "unpipe": "1.0.0" + }, "dependencies": { "iconv-lite": { "version": "0.4.18", - "from": "iconv-lite@0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=" } } }, "rc": { "version": "1.1.7", - "from": "rc@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.7.tgz", + "integrity": "sha1-xepWS7B6/5/TpbMukGwdOmWUD+o=", + "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", - "from": "minimist@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, "read": { "version": "1.0.7", - "from": "read@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "dev": true + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "0.0.7" + } }, "readable-stream": { "version": "1.0.34", - "from": "readable-stream@>=1.0.24 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" + "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" + } }, "readdirp": { "version": "0.2.5", - "from": "readdirp@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-0.2.5.tgz" + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-0.2.5.tgz", + "integrity": "sha1-xMJ25Sl3riXbUZH+UdAIVQ8V2bs=", + "requires": { + "minimatch": "0.2.14" + } }, "redis": { "version": "0.10.1", - "from": "redis@0.10.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-0.10.1.tgz" + "resolved": "https://registry.npmjs.org/redis/-/redis-0.10.1.tgz", + "integrity": "sha1-TwkliTHZYTdyOf29SV4dmaJjqOw=" }, "redis-commands": { "version": "1.3.1", - "from": "redis-commands@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", + "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=" }, "redis-parser": { "version": "2.6.0", - "from": "redis-parser@>=2.6.0 <3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz" + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" }, "redis-sentinel": { "version": "0.1.1", - "from": "redis-sentinel@0.1.1", "resolved": "https://registry.npmjs.org/redis-sentinel/-/redis-sentinel-0.1.1.tgz", + "integrity": "sha1-Vj3TQduZMgMfSX+v3Td+hkj/s+U=", + "requires": { + "q": "0.9.2", + "redis": "0.11.0" + }, "dependencies": { "q": { "version": "0.9.2", - "from": "q@0.9.2", - "resolved": "https://registry.npmjs.org/q/-/q-0.9.2.tgz" + "resolved": "https://registry.npmjs.org/q/-/q-0.9.2.tgz", + "integrity": "sha1-I8BsRsgTKGFqrhaNPuI6Vr1D2vY=" }, "redis": { "version": "0.11.0", - "from": "redis@>=0.11.0 <0.12.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-0.11.0.tgz" + "resolved": "https://registry.npmjs.org/redis/-/redis-0.11.0.tgz", + "integrity": "sha1-/cAdSrTL5LO7LLKByP5WnDhX9XE=" } } }, "redis-sharelatex": { - "version": "1.0.2", - "from": "git+https://github.com/sharelatex/redis-sharelatex.git#v1.0.2", - "resolved": "git+https://github.com/sharelatex/redis-sharelatex.git#143b7eb192675f36d835080e534a4ac4899f918a", + "version": "git+https://github.com/sharelatex/redis-sharelatex.git#143b7eb192675f36d835080e534a4ac4899f918a", + "requires": { + "async": "2.5.0", + "chai": "1.9.1", + "coffee-script": "1.8.0", + "grunt": "0.4.5", + "grunt-contrib-coffee": "0.11.1", + "grunt-mocha-test": "0.12.0", + "ioredis": "2.5.0", + "mocha": "1.21.4", + "redis": "0.12.1", + "redis-sentinel": "0.1.1", + "sandboxed-module": "1.0.1", + "sinon": "1.10.3", + "underscore": "1.7.0" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@^0.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" }, "ansi-styles": { "version": "1.1.0", - "from": "ansi-styles@^1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" }, "assertion-error": { "version": "1.0.0", - "from": "assertion-error@1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=" }, "async": { "version": "2.5.0", - "from": "async@>=2.4.0 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", + "requires": { + "lodash": "4.17.4" + } }, "chai": { "version": "1.9.1", - "from": "chai@1.9.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-1.9.1.tgz" + "resolved": "https://registry.npmjs.org/chai/-/chai-1.9.1.tgz", + "integrity": "sha1-NxG7ZwbhVo80wLNgmL+PGUVcga4=", + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + } }, "chalk": { "version": "0.5.1", - "from": "chalk@~0.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz" + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } }, "coffee-script": { "version": "1.8.0", - "from": "coffee-script@1.8.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz", + "integrity": "sha1-nJ8dK0pSoADe0Vtll5FwNkgmPB0=", + "requires": { + "mkdirp": "0.3.5" + } }, "commander": { "version": "2.0.0", - "from": "commander@2.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=" }, "deep-eql": { "version": "0.1.3", - "from": "deep-eql@0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "requires": { + "type-detect": "0.1.1" + } }, "formatio": { "version": "1.0.2", - "from": "formatio@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.0.2.tgz", + "integrity": "sha1-55kcoUT/fYz/B7uayGqbeca6R+8=", + "requires": { + "samsam": "1.1.3" + } }, "fs-extra": { "version": "0.11.1", - "from": "fs-extra@>=0.11.1 <0.12.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.11.1.tgz", + "integrity": "sha1-3xBPlMyEHu+Pr+KkRsiPXTW7Lnk=", + "requires": { + "jsonfile": "2.4.0", + "mkdirp": "0.5.1", + "ncp": "0.6.0", + "rimraf": "2.6.2" + }, "dependencies": { "mkdirp": { "version": "0.5.1", - "from": "mkdirp@^0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } } } }, "glob": { "version": "7.1.2", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "growl": { "version": "1.8.1", - "from": "growl@>=1.8.0 <1.9.0", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz" + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=" }, "grunt-contrib-coffee": { "version": "0.11.1", - "from": "grunt-contrib-coffee@0.11.1", "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.11.1.tgz", + "integrity": "sha1-+v48nuikQryNF9WlwZ/I5i2fP0U=", + "requires": { + "chalk": "0.5.1", + "coffee-script": "1.7.1", + "lodash": "2.4.2" + }, "dependencies": { "coffee-script": { "version": "1.7.1", - "from": "coffee-script@~1.7.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "requires": { + "mkdirp": "0.3.5" + } }, "lodash": { "version": "2.4.2", - "from": "lodash@~2.4.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" } } }, "grunt-mocha-test": { "version": "0.12.0", - "from": "grunt-mocha-test@0.12.0", - "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.12.0.tgz" + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.12.0.tgz", + "integrity": "sha1-nQu5enkEQIr9x64qAj3X1rJg5uM=", + "requires": { + "fs-extra": "0.11.1", + "hooker": "0.2.3" + } }, "has-ansi": { "version": "0.1.0", - "from": "has-ansi@^0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "requires": { + "ansi-regex": "0.2.1" + } }, "jade": { "version": "0.26.3", - "from": "jade@0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, "dependencies": { "commander": { "version": "0.6.1", - "from": "commander@0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" }, "mkdirp": { "version": "0.3.0", - "from": "mkdirp@0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" } } }, "jsonfile": { "version": "2.4.0", - "from": "jsonfile@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "mkdirp": { "version": "0.3.5", - "from": "mkdirp@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" }, "mocha": { "version": "1.21.4", - "from": "mocha@1.21.4", "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.4.tgz", + "integrity": "sha1-531pw3c7o+K0/mtijCi13UOICtw=", + "requires": { + "commander": "2.0.0", + "debug": "1.0.5", + "diff": "1.0.7", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.3.5" + }, "dependencies": { "glob": { "version": "3.2.3", - "from": "glob@3.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } }, "graceful-fs": { "version": "2.0.3", - "from": "graceful-fs@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=" }, "minimatch": { "version": "0.2.14", - "from": "minimatch@~0.2.11", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } } } }, "ncp": { "version": "0.6.0", - "from": "ncp@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.6.0.tgz" + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.6.0.tgz", + "integrity": "sha1-34zgIeJiviG1L+s9Plz6qxJJHw0=" }, "redis": { "version": "0.12.1", - "from": "redis@0.12.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz", + "integrity": "sha1-ZN92rQ/IrOuuvSoGReikj6xJGF4=" }, "rimraf": { "version": "2.6.2", - "from": "rimraf@>=2.2.8 <3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "requires": { + "glob": "7.1.2" + } }, "samsam": { "version": "1.1.3", - "from": "samsam@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz" + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz", + "integrity": "sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=" }, "sandboxed-module": { "version": "1.0.1", - "from": "sandboxed-module@1.0.1", - "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-1.0.1.tgz", + "integrity": "sha1-/XVEsYgexul8kd8r0CE8Nbj8P0s=", + "requires": { + "require-like": "0.1.2", + "stack-trace": "0.0.9" + } }, "sinon": { "version": "1.10.3", - "from": "sinon@1.10.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.10.3.tgz" + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.10.3.tgz", + "integrity": "sha1-wGPg6Z2DJ9wZkROqtS64Oi6ePCw=", + "requires": { + "formatio": "1.0.2", + "util": "0.10.3" + } }, "strip-ansi": { "version": "0.3.0", - "from": "strip-ansi@^0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "requires": { + "ansi-regex": "0.2.1" + } }, "supports-color": { "version": "0.2.0", - "from": "supports-color@^0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" }, "type-detect": { "version": "0.1.1", - "from": "type-detect@0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=" }, "underscore": { "version": "1.7.0", - "from": "underscore@1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" } } }, "referrer-policy": { "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz", + "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" }, "regexp-clone": { "version": "0.0.1", - "from": "regexp-clone@0.0.1", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", + "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" }, "regexp-quote": { "version": "0.0.0", - "from": "regexp-quote@0.0.0", "resolved": "https://registry.npmjs.org/regexp-quote/-/regexp-quote-0.0.0.tgz", + "integrity": "sha1-Hg9GUMhi3L/tVP1CsUjpuxch/PI=", "dev": true }, "repeat-string": { "version": "1.6.1", - "from": "repeat-string@>=1.5.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "replace": { "version": "0.2.10", - "from": "replace@>=0.2.4 <0.3.0", "resolved": "https://registry.npmjs.org/replace/-/replace-0.2.10.tgz", + "integrity": "sha1-ESM5fplbO/75mF/GPN3PeaAU/WQ=", "dev": true, + "requires": { + "colors": "0.5.1", + "minimatch": "0.2.14", + "nomnom": "1.6.2" + }, "dependencies": { "colors": { "version": "0.5.1", - "from": "colors@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", "dev": true } } }, "request": { "version": "2.81.0", - "from": "request@>=2.69.0 <3.0.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz" + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "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.2", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } }, "requests": { "version": "0.1.7", - "from": "requests@>=0.1.7 <0.2.0", "resolved": "https://registry.npmjs.org/requests/-/requests-0.1.7.tgz", + "integrity": "sha1-e0lPH15ZYBa0OTgyzt00ZZ/RxiM=", + "requires": { + "axo": "0.0.2", + "eventemitter3": "1.1.1", + "extendible": "0.1.1", + "hang": "1.0.0", + "loads": "0.0.4", + "xhr-send": "1.0.0" + }, "dependencies": { "eventemitter3": { "version": "1.1.1", - "from": "eventemitter3@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" } } }, - "require_optional": { - "version": "1.0.1", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz" - }, "require-like": { "version": "0.1.2", - "from": "require-like@0.1.2", - "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha1-TPNaQkf2TKPfjC7yCMxJSxyo/C4=", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.3.0" + } }, "requirejs": { "version": "2.1.22", - "from": "requirejs@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.22.tgz", + "integrity": "sha1-3Xj9LTQYDA1ixyS1uK68BmTgNm8=", "dev": true }, "requires-port": { "version": "1.0.0", - "from": "requires-port@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { "version": "1.4.0", - "from": "resolve@>=1.1.6 <2.0.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha1-p1vgHFPaJdk0qY69DkxKcxL5KoY=", + "requires": { + "path-parse": "1.0.5" + } }, "resolve-from": { "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, "resumer": { "version": "0.0.0", - "from": "resumer@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz" + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } }, "retry-as-promised": { "version": "2.3.0", - "from": "retry-as-promised@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.0.tgz", + "integrity": "sha1-J79czZmZMrMWZWloJc82MMJ8Vi0=", + "requires": { + "bluebird": "3.5.0", + "debug": "2.6.8" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } } } }, "revalidator": { "version": "0.1.8", - "from": "revalidator@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", "dev": true }, "right-align": { "version": "0.1.3", - "from": "right-align@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } }, "rimraf": { "version": "2.2.6", - "from": "rimraf@2.2.6", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=" }, "rndm": { "version": "1.2.0", - "from": "rndm@1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" }, "rolling-rate-limiter": { - "version": "0.1.4", - "from": "git+https://github.com/ShaneKilkelly/rolling-rate-limiter.git#master", - "resolved": "git+https://github.com/ShaneKilkelly/rolling-rate-limiter.git#8a1a2cd8aaf9cd1a75cc81317b7f261157be2149" + "version": "git+https://github.com/ShaneKilkelly/rolling-rate-limiter.git#8a1a2cd8aaf9cd1a75cc81317b7f261157be2149", + "requires": { + "microtime-nodejs": "1.0.0" + } }, "safe-buffer": { "version": "5.1.1", - "from": "safe-buffer@>=5.1.1 <5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" }, "safe-json-stringify": { "version": "1.0.4", - "from": "safe-json-stringify@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz", + "integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=", "optional": true }, "samsam": { "version": "1.1.2", - "from": "samsam@1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=" }, "sandboxed-module": { "version": "0.2.0", - "from": "sandboxed-module@0.2.0", "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-0.2.0.tgz", + "integrity": "sha1-xZRDVA93A0t/z8o3B6Urskw2FkU=", "dev": true, + "requires": { + "require-like": "0.1.2", + "stack-trace": "0.0.6" + }, "dependencies": { "stack-trace": { "version": "0.0.6", - "from": "stack-trace@0.0.6", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.6.tgz", + "integrity": "sha1-HnGb1qJin/CcGJ4Xqe+QKpT8XbA=", "dev": true } } }, "sanitize-html": { "version": "1.14.1", - "from": "sanitize-html@>=1.14.1 <2.0.0", "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.14.1.tgz", - "dev": true + "integrity": "sha1-cw/6Ikm98YMz7/5FsoYXPJxa0Lg=", + "dev": true, + "requires": { + "htmlparser2": "3.9.2", + "regexp-quote": "0.0.0", + "xtend": "4.0.1" + } }, "sanitizer": { "version": "0.1.1", - "from": "sanitizer@0.1.1", - "resolved": "https://registry.npmjs.org/sanitizer/-/sanitizer-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/sanitizer/-/sanitizer-0.1.1.tgz", + "integrity": "sha1-VIv706Xzoafg32seaydkhwN9fEw=" }, "sax": { "version": "1.2.1", - "from": "sax@1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "semver": { "version": "5.3.0", - "from": "semver@>=5.3.0 <5.4.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "send": { "version": "0.13.0", - "from": "send@0.13.0", "resolved": "https://registry.npmjs.org/send/-/send-0.13.0.tgz", + "integrity": "sha1-UY+SGusFYK7H3KspkLFM9vPM5d4=", + "requires": { + "debug": "2.2.0", + "depd": "1.0.1", + "destroy": "1.0.3", + "escape-html": "1.0.2", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + }, "dependencies": { "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "depd": { "version": "1.0.1", - "from": "depd@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", + "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" }, "http-errors": { "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "requires": { + "inherits": "2.0.3", + "statuses": "1.2.1" + } }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" }, "statuses": { "version": "1.2.1", - "from": "statuses@>=1.2.1 <1.3.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" } } }, "sendgrid": { "version": "1.9.2", - "from": "sendgrid@>=1.8.0 <2.0.0", "resolved": "https://registry.npmjs.org/sendgrid/-/sendgrid-1.9.2.tgz", + "integrity": "sha1-1AfmogawoqaWQkbdnAZBwQvwLxk=", + "requires": { + "lodash": "3.10.1", + "mime": "1.3.4", + "request": "2.81.0", + "smtpapi": "1.3.1" + }, "dependencies": { "lodash": { "version": "3.10.1", - "from": "lodash@>=3.0.1 <4.0.0||>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" } } }, "sequelize": { "version": "3.30.4", - "from": "sequelize@>=3.2.0 <4.0.0", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-3.30.4.tgz", + "integrity": "sha1-vaLfHjGFSwmeQUmhEen8Clyh0aQ=", + "requires": { + "bluebird": "3.5.0", + "depd": "1.1.1", + "dottie": "1.1.1", + "generic-pool": "2.4.2", + "inflection": "1.12.0", + "lodash": "4.12.0", + "moment": "2.18.1", + "moment-timezone": "0.5.13", + "retry-as-promised": "2.3.0", + "semver": "5.3.0", + "shimmer": "1.1.0", + "terraformer-wkt-parser": "1.1.2", + "toposort-class": "1.0.1", + "uuid": "3.1.0", + "validator": "5.7.0", + "wkx": "0.2.0" + }, "dependencies": { "lodash": { "version": "4.12.0", - "from": "lodash@4.12.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz", + "integrity": "sha1-K9bcRqBA9Z5obJcu0h2T3FkFMlg=" } } }, "serve-static": { "version": "1.10.3", - "from": "serve-static@>=1.10.0 <1.11.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "requires": { + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.13.2" + }, "dependencies": { "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "destroy": { "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "escape-html": { "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "http-errors": { "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "requires": { + "inherits": "2.0.3", + "statuses": "1.2.1" + } }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" }, "send": { "version": "0.13.2", - "from": "send@0.13.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz" + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "requires": { + "debug": "2.2.0", + "depd": "1.1.1", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + } }, "statuses": { "version": "1.2.1", - "from": "statuses@>=1.2.1 <1.3.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" } } }, "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" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { "version": "1.0.3", - "from": "setprototypeof@1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" }, "settings-sharelatex": { - "version": "1.0.0", - "from": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", - "resolved": "git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559", + "version": "git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559", + "requires": { + "coffee-script": "1.6.0" + }, "dependencies": { "coffee-script": { "version": "1.6.0", - "from": "coffee-script@1.6.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz", + "integrity": "sha1-gIs5bhEPU9AhoZpO8fZb4OjjX6M=" } } }, "shimmer": { "version": "1.1.0", - "from": "shimmer@1.1.0", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.1.0.tgz", + "integrity": "sha1-l9c3cTf/u6tCVSLkKf4KqJpIizU=" }, "sigmund": { "version": "1.0.1", - "from": "sigmund@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" }, "signal-exit": { "version": "3.0.2", - "from": "signal-exit@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { "version": "1.17.7", - "from": "sinon@>=1.17.0 <2.0.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "dev": true + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.10.3" + } }, "sixpack-client": { "version": "1.0.0", - "from": "sixpack-client@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/sixpack-client/-/sixpack-client-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/sixpack-client/-/sixpack-client-1.0.0.tgz", + "integrity": "sha1-BwEiFjjhZ3Om7xbk5FySzpzSa2Y=" }, "sliced": { "version": "1.0.1", - "from": "sliced@1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, "smtp-connection": { "version": "2.0.1", - "from": "smtp-connection@2.0.1", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.0.1.tgz", + "integrity": "sha1-5pKP44ZrQ2p8YHtZHa6Z2aB0WYE=", + "requires": { + "nodemailer-shared": "1.0.3" + } }, "smtpapi": { "version": "1.3.1", - "from": "smtpapi@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/smtpapi/-/smtpapi-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/smtpapi/-/smtpapi-1.3.1.tgz", + "integrity": "sha1-GHQp607SffSjz/0j8OAkXN/mh9Q=" }, "sntp": { "version": "1.0.9", - "from": "sntp@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } }, "source-map": { "version": "0.1.34", - "from": "source-map@0.1.34", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "requires": { + "amdefine": "1.0.1" + } }, "sshpk": { "version": "1.13.1", - "from": "sshpk@>=1.7.0 <2.0.0", "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" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "stack-trace": { "version": "0.0.9", - "from": "stack-trace@0.0.9", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" }, "statsd-parser": { "version": "0.0.4", - "from": "statsd-parser@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/statsd-parser/-/statsd-parser-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/statsd-parser/-/statsd-parser-0.0.4.tgz", + "integrity": "sha1-y9JDlTzELv/VSLXSI4jtaJ7GOb0=" }, "statuses": { "version": "1.3.1", - "from": "statuses@>=1.3.1 <2.0.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" }, "stream-consume": { "version": "0.1.0", - "from": "stream-consume@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=" }, "streamsearch": { "version": "0.1.2", - "from": "streamsearch@0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, "string-width": { "version": "1.0.2", - "from": "string-width@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + "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.prototype.trim": { "version": "1.1.2", - "from": "string.prototype.trim@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.8.2", + "function-bind": "1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "stringstream": { "version": "0.0.5", - "from": "stringstream@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.1 <4.0.0", - "resolved": "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", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } }, "strip-json-comments": { "version": "2.0.1", - "from": "strip-json-comments@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "3.2.3", - "from": "supports-color@>=3.2.3 <4.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "dev": true + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } }, "tape": { "version": "4.8.0", - "from": "tape@>=4.6.3 <5.0.0", "resolved": "https://registry.npmjs.org/tape/-/tape-4.8.0.tgz", + "integrity": "sha1-9qn+xBzFCh3lD6M2A6tYCZH2Bo4=", + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.2", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.3.0", + "resolve": "1.4.0", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + }, "dependencies": { "glob": { "version": "7.1.2", - "from": "glob@>=7.1.2 <7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "minimist": { "version": "1.2.0", - "from": "minimist@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, "tar": { "version": "2.2.1", - "from": "tar@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz" + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } }, "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", + "integrity": "sha1-vIz5oi9YMnOfEvORDaweuXtJcIw=", + "requires": { + "debug": "2.2.0", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.3.3", + "readable-stream": "2.1.5", + "rimraf": "2.5.4", + "tar": "2.2.1", + "uid-number": "0.0.6" + }, "dependencies": { "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "glob": { "version": "7.1.2", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" }, "readable-stream": { "version": "2.1.5", - "from": "readable-stream@>=2.1.4 <2.2.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } }, "rimraf": { "version": "2.5.4", - "from": "rimraf@>=2.5.1 <2.6.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "requires": { + "glob": "7.1.2" + } } } }, "tar-stream": { "version": "0.3.3", - "from": "tar-stream@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.3.3.tgz" + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.3.3.tgz", + "integrity": "sha1-I8pTvXOLhwInKoDibMk4vEuEuHs=", + "requires": { + "bl": "0.6.0", + "end-of-stream": "0.1.5", + "readable-stream": "1.0.34" + } }, "temp": { "version": "0.8.3", - "from": "temp@>=0.8.3 <0.9.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz" + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.6" + } }, "terraformer": { "version": "1.0.8", - "from": "terraformer@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.8.tgz" + "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.8.tgz", + "integrity": "sha1-UeCtiXRvzyFh3G9lqnDkI3fItZM=", + "requires": { + "@types/geojson": "1.0.3" + } }, "terraformer-wkt-parser": { "version": "1.1.2", - "from": "terraformer-wkt-parser@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz", + "integrity": "sha1-M2oMj8gglKWv+DKI9prt7NNpvww=", + "requires": { + "terraformer": "1.0.8" + } }, "text-encoding": { "version": "0.6.4", - "from": "text-encoding@0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz" + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" }, "through": { "version": "2.3.8", - "from": "through@>=2.3.8 <2.4.0", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "thunky": { "version": "0.1.0", - "from": "thunky@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", + "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=" }, "timekeeper": { "version": "2.0.0", - "from": "timekeeper@latest", - "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.0.0.tgz", + "integrity": "sha512-DVH+iEKcVwU3JkZK0Z86qFx8osIG05U1H/F6lAE+iPfvElioM9HPVd2ZKmoI4zS0AWsDogOXl/BuKWXNadI/fw==" }, "timespan": { "version": "2.3.0", - "from": "timespan@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", "dev": true }, "tiny-lr": { "version": "0.2.1", - "from": "tiny-lr@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", "dev": true, + "requires": { + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.2.2", + "parseurl": "1.3.2", + "qs": "5.1.0" + }, "dependencies": { "body-parser": { "version": "1.14.2", - "from": "body-parser@>=1.14.0 <1.15.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.1.1", + "http-errors": "1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "2.3.0", + "qs": "5.2.0", + "raw-body": "2.1.7", + "type-is": "1.6.15" + }, "dependencies": { "qs": { "version": "5.2.0", - "from": "qs@5.2.0", "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", "dev": true } } }, "bytes": { "version": "2.2.0", - "from": "bytes@2.2.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", "dev": true }, "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "dev": true + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } }, "http-errors": { "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "dev": true + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.3.1" + } }, "iconv-lite": { "version": "0.4.13", - "from": "iconv-lite@0.4.13", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true }, "qs": { "version": "5.1.0", - "from": "qs@>=5.1.0 <5.2.0", "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", "dev": true }, "raw-body": { "version": "2.1.7", - "from": "raw-body@>=2.1.5 <2.2.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, "dependencies": { "bytes": { "version": "2.4.0", - "from": "bytes@2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", "dev": true } } @@ -4694,481 +6723,687 @@ }, "to-mongodb-core": { "version": "2.0.0", - "from": "to-mongodb-core@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz", + "integrity": "sha1-NZbsdhOsmtO5ioncua77pWnNJ+s=" }, "token-stream": { "version": "0.0.1", - "from": "token-stream@0.0.1", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" }, "toposort-class": { "version": "1.0.1", - "from": "toposort-class@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, "tough-cookie": { "version": "2.3.2", - "from": "tough-cookie@>=2.3.0 <2.4.0", - "resolved": "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", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "requires": { + "punycode": "1.4.1" + } }, "transformers": { "version": "2.1.0", - "from": "transformers@2.1.0", "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz", + "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=", + "requires": { + "css": "1.0.8", + "promise": "2.0.0", + "uglify-js": "2.2.5" + }, "dependencies": { "optimist": { "version": "0.3.7", - "from": "optimist@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz" + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.2" + } }, "uglify-js": { "version": "2.2.5", - "from": "uglify-js@>=2.2.5 <2.3.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz" + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "requires": { + "optimist": "0.3.7", + "source-map": "0.1.34" + } } } }, "translations-sharelatex": { - "version": "0.1.4", - "from": "git+https://github.com/sharelatex/translations-sharelatex.git#master", - "resolved": "git+https://github.com/sharelatex/translations-sharelatex.git#12d5cefc591bcc0b4e54b5ce9acfbd980208b9e1", + "version": "git+https://github.com/sharelatex/translations-sharelatex.git#12d5cefc591bcc0b4e54b5ce9acfbd980208b9e1", "dev": true, + "requires": { + "async": "2.5.0", + "coffee-script": "1.12.4", + "i18next": "1.7.10", + "onesky": "0.1.6", + "sanitize-html": "1.14.1", + "underscore": "1.6.0" + }, "dependencies": { "async": { "version": "2.5.0", - "from": "async@>=2.1.4 <3.0.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "dev": true + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } } } }, "tsscmp": { "version": "1.0.5", - "from": "tsscmp@1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" }, "tunnel-agent": { "version": "0.6.0", - "from": "tunnel-agent@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + "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", - "from": "tweetnacl@>=0.14.0 <0.15.0", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, "type-detect": { "version": "1.0.0", - "from": "type-detect@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, "type-is": { "version": "1.6.15", - "from": "type-is@>=1.6.15 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" + "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" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { "version": "2.4.24", - "from": "uglify-js@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "requires": { + "async": "0.2.10", + "source-map": "0.1.34", + "uglify-to-browserify": "1.0.2", + "yargs": "3.5.4" + }, "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.6 <0.3.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" } } }, "uglify-to-browserify": { "version": "1.0.2", - "from": "uglify-to-browserify@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" }, "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" + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" }, "uid-safe": { "version": "2.1.4", - "from": "uid-safe@2.1.4", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "requires": { + "random-bytes": "1.0.0" + } }, "uid2": { "version": "0.0.3", - "from": "uid2@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz" + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" }, "underscore": { "version": "1.6.0", - "from": "underscore@1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "underscore.string": { "version": "2.2.1", - "from": "underscore.string@>=2.2.1 <2.3.0", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz" + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=" + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, "unpipe": { "version": "1.0.0", - "from": "unpipe@1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "url": { "version": "0.10.3", - "from": "url@0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", - "from": "punycode@1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" } } }, "util": { "version": "0.10.3", - "from": "util@>=0.10.3 <1.0.0", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + }, "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" } } }, "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" + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utile": { "version": "0.2.1", - "from": "utile@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "integrity": "sha1-kwyI6ZCY1iIINMNWy9mncFItkNc=", "dev": true, + "requires": { + "async": "0.2.10", + "deep-equal": "1.0.1", + "i": "0.3.5", + "mkdirp": "0.5.1", + "ncp": "0.4.2", + "rimraf": "2.2.6" + }, "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, "ncp": { "version": "0.4.2", - "from": "ncp@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", "dev": true } } }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" }, "uuid": { "version": "3.1.0", - "from": "uuid@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" }, "v8-profiler": { "version": "5.7.0", - "from": "v8-profiler@>=5.2.3 <6.0.0", "resolved": "https://registry.npmjs.org/v8-profiler/-/v8-profiler-5.7.0.tgz", + "integrity": "sha1-6DgcvrtbX9DKjSsJ9qAYGhWNs00=", + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.37" + }, "dependencies": { "debug": { "version": "2.6.8", - "from": "debug@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } }, "glob": { "version": "7.1.2", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "isarray": { "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "minimatch": { "version": "3.0.4", - "from": "minimatch@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.8" + } }, "nan": { "version": "2.7.0", - "from": "nan@>=2.5.1 <3.0.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz" + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" }, "node-pre-gyp": { "version": "0.6.37", - "from": "node-pre-gyp@>=0.6.34 <0.7.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.37.tgz" + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.37.tgz", + "integrity": "sha1-PIcrI2suJm5BQFeP4e6I9pMyOgU=", + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.1.7", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tape": "4.8.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } }, "nopt": { "version": "4.0.1", - "from": "nopt@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } }, "readable-stream": { "version": "2.3.3", - "from": "readable-stream@>=2.1.4 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "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" + } }, "rimraf": { "version": "2.6.2", - "from": "rimraf@>=2.6.1 <3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "requires": { + "glob": "7.1.2" + } }, "string_decoder": { "version": "1.0.3", - "from": "string_decoder@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } }, "tar-pack": { "version": "3.4.0", - "from": "tar-pack@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz" + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.3.3", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } } } }, "validator": { "version": "5.7.0", - "from": "validator@>=5.2.0 <6.0.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-5.7.0.tgz" + "resolved": "https://registry.npmjs.org/validator/-/validator-5.7.0.tgz", + "integrity": "sha1-eoelgUa2laxIYHEUHAxJ1n2gXlw=" }, "vary": { "version": "1.0.1", - "from": "vary@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" }, "vasync": { "version": "1.4.0", - "from": "vasync@1.4.0", "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.4.0.tgz", + "integrity": "sha1-bqWmNYI1iGjYdDy91v+tyQg7kQ8=", + "requires": { + "jsprim": "0.3.0", + "verror": "1.1.0" + }, "dependencies": { "extsprintf": { "version": "1.0.0", - "from": "extsprintf@1.0.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.0.tgz", + "integrity": "sha1-TVi4Fazlvr/E6/A8+YsKdgSpm4Y=" }, "json-schema": { "version": "0.2.2", - "from": "json-schema@0.2.2", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz", + "integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY=" }, "jsprim": { "version": "0.3.0", - "from": "jsprim@0.3.0", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-0.3.0.tgz", + "integrity": "sha1-zRNGbqJIDb2DlqVw1H0x3aR2+LE=", + "requires": { + "extsprintf": "1.0.0", + "json-schema": "0.2.2", + "verror": "1.3.3" + }, "dependencies": { "verror": { "version": "1.3.3", - "from": "verror@1.3.3", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.3.tgz" + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.3.tgz", + "integrity": "sha1-impKw6jHdLb2h/7OSb3/14VS4s0=", + "requires": { + "extsprintf": "1.0.0" + } } } }, "verror": { "version": "1.1.0", - "from": "verror@1.1.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/verror/-/verror-1.1.0.tgz", + "integrity": "sha1-KktOsUogcFHnWm+U7lExW/FzobA=", + "requires": { + "extsprintf": "1.0.0" + } } } }, "verror": { "version": "1.10.0", - "from": "verror@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" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "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", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "void-elements": { "version": "2.0.1", - "from": "void-elements@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, "watch": { "version": "0.13.0", - "from": "watch@>=0.13.0 <0.14.0", "resolved": "https://registry.npmjs.org/watch/-/watch-0.13.0.tgz", + "integrity": "sha1-/MbSs/DoxzSC61Qjmhn9W8+adTw=", "dev": true, + "requires": { + "minimist": "1.2.0" + }, "dependencies": { "minimist": { "version": "1.2.0", - "from": "minimist@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "websocket-driver": { "version": "0.7.0", - "from": "websocket-driver@>=0.5.1", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "dev": true + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.8", + "websocket-extensions": "0.1.2" + } }, "websocket-extensions": { "version": "0.1.2", - "from": "websocket-extensions@>=0.1.1", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.2.tgz", + "integrity": "sha1-Dhh4HeYpoYMIzhSBZQ9n/6JpOl0=", "dev": true }, "which": { "version": "1.0.9", - "from": "which@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=" }, "wide-align": { "version": "1.1.2", - "from": "wide-align@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", + "requires": { + "string-width": "1.0.2" + } }, "window-size": { "version": "0.1.0", - "from": "window-size@0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, "winston": { "version": "0.8.3", - "from": "winston@>=0.8.1 <0.9.0", "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", + "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", "dev": true, + "requires": { + "async": "0.2.10", + "colors": "0.6.2", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "pkginfo": "0.3.1", + "stack-trace": "0.0.9" + }, "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true } } }, "with": { "version": "3.0.1", - "from": "with@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/with/-/with-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/with/-/with-3.0.1.tgz", + "integrity": "sha1-CDVNpBAkPPYXP7FCuwTmxm+W+FQ=", + "requires": { + "uglify-js": "2.4.24" + } }, "wkx": { "version": "0.2.0", - "from": "wkx@0.2.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.2.0.tgz", + "integrity": "sha1-dsJPFqzQzY+TzTSqMx4PeWElboQ=" }, "wordwrap": { "version": "0.0.2", - "from": "wordwrap@0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" }, "wrappy": { "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "x-xss-protection": { "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz", + "integrity": "sha1-iYr7k4abJGYc+cUvnujbjtB2Tdk=" }, "xhr-response": { "version": "1.0.1", - "from": "xhr-response@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/xhr-response/-/xhr-response-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/xhr-response/-/xhr-response-1.0.1.tgz", + "integrity": "sha1-r/46CFRLpyGG5NxSzQImZx2Gc/4=" }, "xhr-send": { "version": "1.0.0", - "from": "xhr-send@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/xhr-send/-/xhr-send-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/xhr-send/-/xhr-send-1.0.0.tgz", + "integrity": "sha1-GkDHPl2yAo7gj+kPXD1tx/eWqFQ=" }, "xhr-status": { "version": "1.0.0", - "from": "xhr-status@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/xhr-status/-/xhr-status-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/xhr-status/-/xhr-status-1.0.0.tgz", + "integrity": "sha1-mo0ew670hvdnKcHq1921RWLY8I8=" }, "xml-crypto": { "version": "0.8.5", - "from": "xml-crypto@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-0.8.5.tgz", + "integrity": "sha1-K7z7PrM/OoKiGLgiv2craxwg5Tg=", + "requires": { + "xmldom": "0.1.19", + "xpath.js": "1.0.7" + }, "dependencies": { "xmldom": { "version": "0.1.19", - "from": "xmldom@0.1.19", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz" + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz", + "integrity": "sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw=" } } }, "xml-encryption": { "version": "0.7.4", - "from": "xml-encryption@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-0.7.4.tgz", + "integrity": "sha1-Qnkexk1VbSRV3LnaClQSNmWsZcc=", + "requires": { + "async": "0.2.10", + "ejs": "0.8.8", + "node-forge": "0.2.24", + "xmldom": "0.1.27", + "xpath": "0.0.5" + }, "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.7 <0.3.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" } } }, "xml2js": { "version": "0.2.0", - "from": "xml2js@0.2.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.0.tgz", + "integrity": "sha1-99pSJ33rtkeYMFOtti2XLe5loaw=", + "requires": { + "sax": "1.2.1" + } }, "xmlbuilder": { "version": "4.2.1", - "from": "xmlbuilder@4.2.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz" + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "4.17.4" + } }, "xmldom": { "version": "0.1.27", - "from": "xmldom@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz" + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" }, "xpath": { "version": "0.0.5", - "from": "xpath@0.0.5", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.5.tgz", + "integrity": "sha1-RUA29u8PPfWvXUukoRn7dWdLPmw=" }, "xpath.js": { "version": "1.0.7", - "from": "xpath.js@>=0.0.3", - "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.0.7.tgz" + "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.0.7.tgz", + "integrity": "sha1-fpRif1QSdsvGprArXTXpQYVls+Q=" }, "xtend": { "version": "4.0.1", - "from": "xtend@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "yargs": { "version": "3.5.4", - "from": "yargs@>=3.5.4 <3.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz" + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "requires": { + "camelcase": "1.2.1", + "decamelize": "1.2.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + } + }, + "yauzl": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", + "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } }, "zip-stream": { "version": "0.3.7", - "from": "zip-stream@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.3.7.tgz", + "integrity": "sha1-yE0FfrC8wBOXR708bJcoC89fK7I=", + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "0.2.0", + "debug": "1.0.5", + "deflate-crc32-stream": "0.1.2", + "lodash": "2.4.2", + "readable-stream": "1.0.34" + }, "dependencies": { "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" } } }, "zlib-browserify": { "version": "0.0.1", - "from": "zlib-browserify@0.0.1", "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz", + "integrity": "sha1-T6akXQDbwV8xikr6HZr8Aljhdsw=", "dev": true } } diff --git a/services/web/package.json b/services/web/package.json index a35688bfe7..80cba81a5f 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -25,6 +25,7 @@ "dateformat": "1.0.4-1.2.3", "express": "4.13.0", "express-session": "^1.14.2", + "fs-extra": "^4.0.2", "heapdump": "^0.3.7", "helmet": "^3.8.1", "http-proxy": "^1.8.1", @@ -69,7 +70,8 @@ "underscore": "1.6.0", "uuid": "^3.0.1", "v8-profiler": "^5.2.3", - "xml2js": "0.2.0" + "xml2js": "0.2.0", + "yauzl": "^2.8.0" }, "devDependencies": { "autoprefixer": "^6.6.1", From 96d08e41a7c30b30cdbb9799546be72abb9a285c Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 16 Oct 2017 11:13:53 +0100 Subject: [PATCH 77/99] update tests --- .../Features/Uploads/ArchiveManager.coffee | 13 +- .../coffee/Uploads/ArchiveManagerTests.coffee | 180 ++++++++++++++---- 2 files changed, 156 insertions(+), 37 deletions(-) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index b71b5cd2bc..b52ff72afa 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -15,7 +15,7 @@ module.exports = ArchiveManager = _isZipTooLarge: (source, callback = (err, isTooLarge)->)-> callback = _.once callback - totalSizeInBytes = 0 + totalSizeInBytes = null yauzl.open source, {lazyEntries: true}, (err, zipfile) -> return callback(err) if err? @@ -61,11 +61,15 @@ module.exports = ArchiveManager = readStream.on "error", callback readStream.on "end", callback + errorHandler = (err) -> # clean up before calling callback + readStream.unpipe() + readStream.destroy() + callback(err) + fse.ensureDir Path.dirname(destFile), (err) -> - return callback(err) if err? + return errorHandler(err) if err? writeStream = fs.createWriteStream destFile - writeStream.on 'error', (err) -> - return callback(err) + writeStream.on 'error', errorHandler readStream.pipe(writeStream) _extractZipFiles: (source, destination, callback = (err) ->) -> @@ -110,6 +114,7 @@ module.exports = ArchiveManager = logger.log source: source, destination: destination, "unzipping file" ArchiveManager._extractZipFiles source, destination, (err) -> + timer.done() if err? logger.error {err, source, destination}, "unzip failed" callback(err) diff --git a/services/web/test/UnitTests/coffee/Uploads/ArchiveManagerTests.coffee b/services/web/test/UnitTests/coffee/Uploads/ArchiveManagerTests.coffee index fd6153efae..61efbccce7 100644 --- a/services/web/test/UnitTests/coffee/Uploads/ArchiveManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Uploads/ArchiveManagerTests.coffee @@ -10,24 +10,22 @@ describe "ArchiveManager", -> beforeEach -> @logger = error: sinon.stub() + warn: sinon.stub() err:-> log: sinon.stub() - @process = new events.EventEmitter - @process.stdout = new events.EventEmitter - @process.stderr = new events.EventEmitter - - @child = - spawn: sinon.stub().returns(@process) - - @metrics = Timer: class Timer done: sinon.stub() + @zipfile = new events.EventEmitter + @zipfile.readEntry = sinon.stub() + @zipfile.close = sinon.stub() + @ArchiveManager = SandboxedModule.require modulePath, requires: - "child_process": @child + "yauzl": @yauzl = {open: sinon.stub().callsArgWith(2, null, @zipfile)} "logger-sharelatex": @logger "metrics-sharelatex": @metrics "fs": @fs = {} + "fs-extra": @fse = {} describe "extractZipArchive", -> beforeEach -> @@ -39,10 +37,10 @@ describe "ArchiveManager", -> describe "successfully", -> beforeEach (done) -> @ArchiveManager.extractZipArchive @source, @destination, done - @process.emit "close" + @zipfile.emit "end" - it "should run unzip", -> - @child.spawn.calledWithExactly("unzip", [@source, "-d", @destination]).should.equal true + it "should run yauzl", -> + @yauzl.open.calledWith(@source).should.equal true it "should time the unzip", -> @metrics.Timer::done.called.should.equal true @@ -50,13 +48,12 @@ describe "ArchiveManager", -> it "should log the unzip", -> @logger.log.calledWith(sinon.match.any, "unzipping file").should.equal true - describe "with an error on stderr", -> + describe "with an error in the zip file header", -> beforeEach (done) -> + @yauzl.open = sinon.stub().callsArgWith(2, new Error("Something went wrong")) @ArchiveManager.extractZipArchive @source, @destination, (error) => @callback(error) done() - @process.stderr.emit "data", "Something went wrong" - @process.emit "close" it "should return the callback with an error", -> @callback.calledWithExactly(new Error("Something went wrong")).should.equal true @@ -74,60 +71,177 @@ describe "ArchiveManager", -> it "should return the callback with an error", -> @callback.calledWithExactly(new Error("zip_too_large")).should.equal true - it "should not call spawn", -> - @child.spawn.called.should.equal false + it "should not call yauzl.open", -> + @yauzl.open.called.should.equal false - describe "with an error on the process", -> + describe "with an error in the extracted files", -> beforeEach (done) -> @ArchiveManager.extractZipArchive @source, @destination, (error) => @callback(error) done() - @process.emit "error", new Error("Something went wrong") + @zipfile.emit "error", new Error("Something went wrong") it "should return the callback with an error", -> @callback.calledWithExactly(new Error("Something went wrong")).should.equal true it "should log out the error", -> @logger.error.called.should.equal true - + + describe "with a relative extracted file path", -> + beforeEach (done) -> + @zipfile.openReadStream = sinon.stub() + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "../testfile.txt"} + @zipfile.emit "end" + + it "should not write try to read the file entry", -> + @zipfile.openReadStream.called.should.equal false + + it "should log out a warning", -> + @logger.warn.called.should.equal true + + describe "with an unnormalized extracted file path", -> + beforeEach (done) -> + @zipfile.openReadStream = sinon.stub() + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "foo/./testfile.txt"} + @zipfile.emit "end" + + it "should not write try to read the file entry", -> + @zipfile.openReadStream.called.should.equal false + + it "should log out a warning", -> + @logger.warn.called.should.equal true + + describe "with a directory entry", -> + beforeEach (done) -> + @zipfile.openReadStream = sinon.stub() + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "testdir/"} + @zipfile.emit "end" + + it "should not write try to read the entry", -> + @zipfile.openReadStream.called.should.equal false + + it "should not log out a warning", -> + @logger.warn.called.should.equal false + + describe "with an error opening the file read stream", -> + beforeEach (done) -> + @zipfile.openReadStream = sinon.stub().callsArgWith(1, new Error("Something went wrong")) + @writeStream = new events.EventEmitter + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "testfile.txt"} + @zipfile.emit "end" + + it "should return the callback with an error", -> + @callback.calledWithExactly(new Error("Something went wrong")).should.equal true + + it "should log out the error", -> + @logger.error.called.should.equal true + + it "should close the zipfile", -> + @zipfile.close.called.should.equal true + + describe "with an error in the file read stream", -> + beforeEach (done) -> + @readStream = new events.EventEmitter + @readStream.pipe = sinon.stub() + @zipfile.openReadStream = sinon.stub().callsArgWith(1, null, @readStream) + @writeStream = new events.EventEmitter + @fs.createWriteStream = sinon.stub().returns @writeStream + @fse.ensureDir = sinon.stub().callsArg(1) + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "testfile.txt"} + @readStream.emit "error", new Error("Something went wrong") + @zipfile.emit "end" + + it "should return the callback with an error", -> + @callback.calledWithExactly(new Error("Something went wrong")).should.equal true + + it "should log out the error", -> + @logger.error.called.should.equal true + + it "should close the zipfile", -> + @zipfile.close.called.should.equal true + + describe "with an error in the file write stream", -> + beforeEach (done) -> + @readStream = new events.EventEmitter + @readStream.pipe = sinon.stub() + @readStream.unpipe = sinon.stub() + @readStream.destroy = sinon.stub() + @zipfile.openReadStream = sinon.stub().callsArgWith(1, null, @readStream) + @writeStream = new events.EventEmitter + @fs.createWriteStream = sinon.stub().returns @writeStream + @fse.ensureDir = sinon.stub().callsArg(1) + @ArchiveManager.extractZipArchive @source, @destination, (error) => + @callback(error) + done() + @zipfile.emit "entry", {fileName: "testfile.txt"} + @writeStream.emit "error", new Error("Something went wrong") + @zipfile.emit "end" + + it "should return the callback with an error", -> + @callback.calledWithExactly(new Error("Something went wrong")).should.equal true + + it "should log out the error", -> + @logger.error.called.should.equal true + + it "should unpipe from the readstream", -> + @readStream.unpipe.called.should.equal true + + it "should destroy the readstream", -> + @readStream.destroy.called.should.equal true + + it "should close the zipfile", -> + @zipfile.close.called.should.equal true + describe "_isZipTooLarge", -> - beforeEach -> - @output = (totalSize)->" Length Date Time Name \n-------- ---- ---- ---- \n241 03-12-16 12:20 main.tex \n108801 03-12-16 12:20 ddd/x1J5kHh.jpg \n-------- ------- \n#{totalSize} 2 files\n" it "should return false with small output", (done)-> @ArchiveManager._isZipTooLarge @source, (error, isTooLarge) => isTooLarge.should.equal false done() - @process.stdout.emit "data", @output("109042") - @process.emit "close" + @zipfile.emit "entry", {uncompressedSize: 109042} + @zipfile.emit "end" it "should return true with large bytes", (done)-> @ArchiveManager._isZipTooLarge @source, (error, isTooLarge) => isTooLarge.should.equal true done() - @process.stdout.emit "data", @output("1090000000000000042") - @process.emit "close" + @zipfile.emit "entry", {uncompressedSize: 1090000000000000042} + @zipfile.emit "end" it "should return error on no data", (done)-> @ArchiveManager._isZipTooLarge @source, (error, isTooLarge) => expect(error).to.exist done() - @process.stdout.emit "data", "" - @process.emit "close" + @zipfile.emit "entry", {} + @zipfile.emit "end" it "should return error if it didn't get a number", (done)-> @ArchiveManager._isZipTooLarge @source, (error, isTooLarge) => expect(error).to.exist done() - @process.stdout.emit "data", @output("total_size_string") - @process.emit "close" + @zipfile.emit "entry", {uncompressedSize:"random-error"} + @zipfile.emit "end" - it "should return error if the is only a bit of data", (done)-> + it "should return error if there is no data", (done)-> @ArchiveManager._isZipTooLarge @source, (error, isTooLarge) => expect(error).to.exist done() - @process.stdout.emit "data", " Length Date Time Name \n--------" - @process.emit "close" + @zipfile.emit "end" describe "findTopLevelDirectory", -> beforeEach -> From 2bb7c6d4c6d89f21b4e4f90c79de130923f6daf6 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 16 Oct 2017 14:21:28 +0100 Subject: [PATCH 78/99] remove child_process module from ArchiveManager --- services/web/app/coffee/Features/Uploads/ArchiveManager.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index b52ff72afa..db31e5f0f4 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -1,4 +1,3 @@ -child = require "child_process" logger = require "logger-sharelatex" metrics = require "metrics-sharelatex" fs = require "fs" From 4c78b5770c7c20206f1002b567fbc2b98738ec40 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 16 Oct 2017 15:17:33 +0100 Subject: [PATCH 79/99] use regex for directory check --- services/web/app/coffee/Features/Uploads/ArchiveManager.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index db31e5f0f4..9407cd9e5b 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -39,7 +39,8 @@ module.exports = ArchiveManager = _checkFilePath: (entry, destination, callback = (err, destFile) ->) -> # check if the entry is a directory - if /\/$/.test(entry.fileName) + endsWithSlash = /\/$/ + if endsWithSlash.test(entry.fileName) return callback() # don't give a destfile for directory # check that the file does not use a relative path for dir in entry.fileName.split('/') From aff5823a2d15d914e9a729304dfec36b13e02dae Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 17 Oct 2017 13:30:47 +0100 Subject: [PATCH 80/99] Revert "Complete 'usepackage' with packages" --- .../auto-complete/AutoCompleteManager.coffee | 13 +++--- .../auto-complete/CommandManager.coffee | 26 +++++------ .../auto-complete/PackageManager.coffee | 43 ------------------- 3 files changed, 18 insertions(+), 64 deletions(-) delete mode 100644 services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 60241da990..24a524b4b6 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -1,11 +1,10 @@ define [ "ide/editor/directives/aceEditor/auto-complete/CommandManager" "ide/editor/directives/aceEditor/auto-complete/EnvironmentManager" - "ide/editor/directives/aceEditor/auto-complete/PackageManager" "ide/editor/directives/aceEditor/auto-complete/Helpers" "ace/ace" "ace/ext-language_tools" -], (CommandManager, EnvironmentManager, PackageManager, Helpers) -> +], (CommandManager, EnvironmentManager, Helpers) -> Range = ace.require("ace/range").Range aceSnippetManager = ace.require('ace/snippets').snippetManager @@ -36,7 +35,6 @@ define [ }) SnippetCompleter = new EnvironmentManager() - PackageCompleter = new PackageManager() Graphics = @graphics Preamble = @preamble @@ -128,11 +126,10 @@ define [ callback null, result @editor.completers = [ - @suggestionManager - SnippetCompleter - PackageCompleter - ReferencesCompleter - LabelsCompleter + @suggestionManager, + SnippetCompleter, + ReferencesCompleter, + LabelsCompleter, GraphicsCompleter ] diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee index 88cd3a2e84..fd6cdf7e64 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/CommandManager.coffee @@ -12,7 +12,7 @@ define [], () -> 'Lambda', 'Xi', 'Pi', 'Sigma', 'Upsilon', 'Phi', 'Psi', 'Omega' ] singleArgumentCommands = [ - 'chapter', 'section', 'label', 'textbf', 'subsection', + 'chapter', 'usepackage', 'section', 'label', 'textbf', 'subsection', 'vspace', 'cite', 'textit', 'documentclass', 'includegraphics', 'input', 'emph','caption', 'ref', 'title', 'author', 'texttt', 'include', 'hspace', 'bibitem', 'url', 'large', 'subsubsection', 'textsc', 'date', @@ -63,19 +63,19 @@ define [], () -> meta: "cmd" } special = for cmd in special - { - caption: "\\#{cmd}{}" - snippet: "\\#{cmd}{}" - meta: "cmd" - } + { + caption: "\\#{cmd}{}" + snippet: "\\#{cmd}{}" + meta: "cmd" + } staticCommands = [].concat( - noArgumentCommands, - singleArgumentCommands, - doubleArgumentCommands, - tripleArgumentCommands, - special - ) + noArgumentCommands, + singleArgumentCommands, + doubleArgumentCommands, + tripleArgumentCommands, + special + ) class Parser constructor: (@doc, @prefix) -> @@ -172,7 +172,7 @@ define [], () -> commands = parser.parse() completions = [] for command in commands - if command[0] not in rawCommands and command[0] != "usepackage" + if command[0] not in rawCommands caption = "\\#{command[0]}" score = if caption == prefix then 99 else 50 snippet = caption diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee deleted file mode 100644 index c0e1cf5e8f..0000000000 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/PackageManager.coffee +++ /dev/null @@ -1,43 +0,0 @@ -define () -> - packages = [ - 'inputenc', 'graphicx', 'amsmath', 'geometry', 'amssymb', 'hyperref', - 'babel', 'color', 'xcolor', 'url', 'natbib', 'fontenc', 'fancyhdr', - 'amsfonts', 'booktabs', 'amsthm', 'float', 'tikz', 'caption', - 'setspace', 'multirow', 'array', 'multicol', 'titlesec', 'enumitem', - 'ifthen', 'listings', 'blindtext', 'subcaption', 'times', 'bm', - 'subfigure', 'algorithm', 'fontspec', 'biblatex', 'tabularx', - 'microtype', 'etoolbox', 'parskip', 'calc', 'verbatim', 'mathtools', - 'epsfig', 'wrapfig', 'lipsum', 'cite', 'textcomp', 'longtable', - 'textpos', 'algpseudocode', 'enumerate', 'subfig', 'pdfpages', - 'epstopdf', 'latexsym', 'lmodern', 'pifont', 'ragged2e', 'rotating', - 'dcolumn', 'xltxtra', 'marvosym', 'indentfirst', 'xspace', 'csquotes', - 'xparse', 'changepage', 'soul', 'xunicode', 'comment', 'mathrsfs', - 'tocbibind', 'lastpage', 'algorithm2e', 'pgfplots', 'lineno', - 'graphics', 'algorithmic', 'fullpage', 'mathptmx', 'todonotes', - 'ulem', 'tweaklist', 'moderncvstyleclassic', 'collection', - 'moderncvcompatibility', 'gensymb', 'helvet', 'siunitx', 'adjustbox', - 'placeins', 'colortbl', 'appendix', 'makeidx', 'supertabular', 'ifpdf', - 'framed', 'aliascnt', 'layaureo', 'authblk' - ] - - packageSnippets = for pkg in packages - { - caption: "\\usepackage{#{pkg}}" - snippet: "\\usepackage{#{pkg}}" - meta: "pkg" - } - - packageSnippets.push { - caption: "\\usepackage{}" - snippet: "\\usepackage{}" - meta: "pkg" - score: 55 - } - - class PackageManager - getCompletions: (editor, session, pos, prefix, callback) -> - docText = session.getValue() - loaded = parseLoadedPackages docText - callback null, packageSnippets - - return PackageManager From 6ff3a2de9ff984bea6998a4f8d292b6c245d756a Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 17 Oct 2017 15:04:27 +0100 Subject: [PATCH 81/99] Rollout autocompile to 1% of users and improve readability --- .../web/app/coffee/Features/Project/ProjectController.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 68d2c49bca..d9a3664165 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -257,8 +257,8 @@ module.exports = ProjectController = timestamp = parseInt(user_id.toString().substring(0, 8), 16) counter = parseInt(user_id.toString().substring(18, 24), 16) - rolloutProportion = 0 - if counter % 1000 >= rolloutProportion + rolloutPercentage = 1 # Percentage of users to roll out to + if counter % 1000 > rolloutPercentage # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) From b0dc84748abb9ada18b89320905ac922ef559df0 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Tue, 17 Oct 2017 15:44:15 +0100 Subject: [PATCH 82/99] Fix to actual percentage --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index d9a3664165..d210d5d40a 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -258,7 +258,7 @@ module.exports = ProjectController = counter = parseInt(user_id.toString().substring(18, 24), 16) rolloutPercentage = 1 # Percentage of users to roll out to - if counter % 1000 > rolloutPercentage + if counter % 100 > rolloutPercentage # Don't show if user is not part of roll out return cb(null, false) userSignupDate = new Date(timestamp * 1000) From f70ab03bd8fbd0ad68ae2b7bdb6fa3d542e59b15 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 15:47:50 +0100 Subject: [PATCH 83/99] show an error if the main file cannot be found also improve logic for detecting the main file, if there's only one file it must be the main file. --- .../Features/Compile/ClsiManager.coffee | 22 ++++++++++++++++--- services/web/app/views/project/editor/pdf.pug | 3 +++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index cff2b931b6..0a939505e5 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -29,7 +29,11 @@ module.exports = ClsiManager = sendRequestOnce: (project_id, user_id, options = {}, callback = (error, status, outputFiles, clsiServerId, validationProblems) ->) -> ClsiManager._buildRequest project_id, options, (error, req) -> - return callback(error) if error? + if error? + if error.message is "no main file specified" + return callback(null, "validation-problems", null, null, {mainFile:error.message}) + else + return callback(error) logger.log project_id: project_id, "sending compile to CLSI" ClsiFormatChecker.checkRecoursesForProblems req.compile?.resources, (err, validationProblems)-> if err? @@ -206,9 +210,12 @@ module.exports = ClsiManager = resources = [] rootResourcePath = null rootResourcePathOverride = null + hasMainFile = false + numberOfDocsInProject = 0 for path, doc of docs path = path.replace(/^\//, "") # Remove leading / + numberOfDocsInProject++ if doc.lines? # add doc to resources unless it is just a stub entry resources.push path: path @@ -217,11 +224,20 @@ module.exports = ClsiManager = rootResourcePath = path if options.rootDoc_id? and doc._id.toString() == options.rootDoc_id.toString() rootResourcePathOverride = path + if path is "main.tex" + hasMainFile = true rootResourcePath = rootResourcePathOverride if rootResourcePathOverride? if !rootResourcePath? - logger.warn {project_id}, "no root document found, setting to main.tex" - rootResourcePath = "main.tex" + if hasMainFile + logger.warn {project_id}, "no root document found, setting to main.tex" + rootResourcePath = "main.tex" + else if numberOfDocsInProject is 1 # only one file, must be the main document + for path, doc of docs + rootResourcePath = path.replace(/^\//, "") # Remove leading / + logger.warn {project_id, rootResourcePath: rootResourcePath}, "no root document found, single document in project" + else + return callback new Error("no main file specified") for path, file of files path = path.replace(/^\//, "") # Remove leading / diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 58b0aa6521..429fa41c6f 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -317,6 +317,9 @@ div.full-size.pdf(ng-controller="PdfController") div li(ng-repeat="entry in pdf.validation.conflictedPaths") {{ '/'+entry['path'] }} + .alert.alert-danger(ng-show="pdf.validation.mainFile") + strong #{translate("main_file_not_found")} + span #{translate("please_set_main_file")} .pdf-errors(ng-switch-when="errors") From 56cb901b4125c85e75a154d46958003d251012e8 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 15:49:02 +0100 Subject: [PATCH 84/99] filter missing doc_ids from root doc_ids list --- services/web/app/coffee/Features/Compile/ClsiManager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 0a939505e5..c27bc2fe90 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -184,7 +184,7 @@ module.exports = ClsiManager = # present in the docupdater. This allows finaliseRequest to # identify the root doc. possibleRootDocIds = [options.rootDoc_id, project.rootDoc_id] - for rootDoc_id in possibleRootDocIds when rootDoc_id? + for rootDoc_id in possibleRootDocIds when rootDoc_id? and rootDoc_id of docPath path = docPath[rootDoc_id] docs[path] ?= {_id: rootDoc_id, path: path} ClsiManager._finaliseRequest project_id, options, project, docs, [], callback From bcabec1c5de28342df9a20d9034ba570a03a9722 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 15:50:29 +0100 Subject: [PATCH 85/99] added tests --- .../coffee/Compile/ClsiManagerTests.coffee | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee index 6786c3a1a8..bd02af2f28 100644 --- a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee @@ -346,7 +346,49 @@ describe "ClsiManager", -> it "should set to main.tex", -> @request.compile.rootResourcePath.should.equal "main.tex" - + + describe "when there is no valid root document and no main.tex document", -> + beforeEach () -> + @project.rootDoc_id = "not-valid" + @docs = { + "/other.tex": @doc_1 = { + name: "other.tex" + _id: "mock-doc-id-1" + lines: ["Hello", "world"] + }, + "/chapters/chapter1.tex": @doc_2 = { + name: "chapter1.tex" + _id: "mock-doc-id-2" + lines: [ + "Chapter 1" + ] + } + } + @ProjectEntityHandler.getAllDocs = sinon.stub().callsArgWith(1, null, @docs) + @ClsiManager._buildRequest @project, null, @callback + + it "should report an error", -> + @callback.calledWith(new Error("no main file specified")).should.equal true + + + describe "when there is no valid root document and a single document which is not main.tex", -> + beforeEach (done) -> + @project.rootDoc_id = "not-valid" + @docs = { + "/other.tex": @doc_1 = { + name: "other.tex" + _id: "mock-doc-id-1" + lines: ["Hello", "world"] + } + } + @ProjectEntityHandler.getAllDocs = sinon.stub().callsArgWith(1, null, @docs) + @ClsiManager._buildRequest @project, null, (@error, @request) => + done() + + it "should set io to the only file", -> + @request.compile.rootResourcePath.should.equal "other.tex" + + describe "with the draft option", -> it "should add the draft option into the request", (done) -> @ClsiManager._buildRequest @project_id, {timeout:100, draft: true}, (error, request) => From 82b84fd5f434fce11bc80658eed32520e9ce9e04 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 15:50:38 +0100 Subject: [PATCH 86/99] hide logs when there are validation errors --- .../web/public/coffee/ide/pdf/controllers/PdfController.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 640c224e7b..4846837856 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -231,6 +231,7 @@ define [ else if response.status == "validation-problems" $scope.pdf.view = "validation-problems" $scope.pdf.validation = response.validationProblems + $scope.shouldShowLogs = false else if response.status == "compile-in-progress" $scope.pdf.view = 'errors' $scope.pdf.compileInProgress = true From 76d73951f249b3daaaf8187aa6c7d466c561b5a5 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 16:31:35 +0100 Subject: [PATCH 87/99] fix bug when unzipping directory --- services/web/app/coffee/Features/Uploads/ArchiveManager.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index 9407cd9e5b..a0e3863a19 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -94,6 +94,8 @@ module.exports = ArchiveManager = return callback(err) else zipfile.readEntry() # continue to the next file + else # if it's a directory, continue + zipfile.readEntry() # no more entries to read zipfile.on "end", callback From 6001f142619ed11aae04ce146a94e0509d533c3b Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 16:31:56 +0100 Subject: [PATCH 88/99] log each file unzipped --- services/web/app/coffee/Features/Uploads/ArchiveManager.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index a0e3863a19..3db074b13f 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -81,6 +81,7 @@ module.exports = ArchiveManager = # read all the entries zipfile.readEntry() zipfile.on "entry", (entry) -> + logger.log {source:source, fileName: entry.fileName}, "processing zip file entry" ArchiveManager._checkFilePath entry, destination, (err, destFile) -> if err? logger.warn err:err, source:source, destination:destination, "skipping bad file path" From 277b9c5d500c0168a4cffc96f708ed33649a2c18 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 16:32:26 +0100 Subject: [PATCH 89/99] ignore .git directories in uploads --- services/web/app/coffee/Features/Uploads/FileTypeManager.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee index 2e22ed5665..40c6e126de 100644 --- a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee @@ -18,6 +18,7 @@ module.exports = FileTypeManager = IGNORE_FILENAMES : [ "__MACOSX" + ".git" ] MAX_TEXT_FILE_SIZE: 1 * 1024 * 1024 # 1 MB From 290361dc723fbc088c5b1c1a2f8db0001f770a18 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 17 Oct 2017 16:49:51 +0100 Subject: [PATCH 90/99] ignore .gitignore files in uploads too --- services/web/app/coffee/Features/Uploads/FileTypeManager.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee index 40c6e126de..918f66df7b 100644 --- a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee @@ -19,6 +19,7 @@ module.exports = FileTypeManager = IGNORE_FILENAMES : [ "__MACOSX" ".git" + ".gitignore" ] MAX_TEXT_FILE_SIZE: 1 * 1024 * 1024 # 1 MB From bf4404b60a52298882158722a8b61b6d2f571a5a Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Wed, 18 Oct 2017 14:14:59 +0100 Subject: [PATCH 91/99] handle null values when saving rootDoc_id --- .../ide/settings/controllers/SettingsController.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee b/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee index 26520d76e0..df65a2f721 100644 --- a/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee +++ b/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee @@ -55,7 +55,11 @@ define [ $scope.$watch "project.rootDoc_id", (rootDoc_id, oldRootDoc_id) => return if @ignoreUpdates - if oldRootDoc_id? and rootDoc_id != oldRootDoc_id + # don't save on initialisation, Angular passes oldRootDoc_id as + # undefined in this case. + return if typeof oldRootDoc_id is "undefined" + # otherwise only save changes, null values are allowed + if (rootDoc_id != oldRootDoc_id) settings.saveProjectSettings({rootDocId: rootDoc_id}) From 4cc517240c34d33f8914e38b190890f693dc5139 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 19 Oct 2017 10:54:21 +0100 Subject: [PATCH 92/99] Increase rollout to 3% --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index d210d5d40a..80c74754e0 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -257,7 +257,7 @@ module.exports = ProjectController = timestamp = parseInt(user_id.toString().substring(0, 8), 16) counter = parseInt(user_id.toString().substring(18, 24), 16) - rolloutPercentage = 1 # Percentage of users to roll out to + rolloutPercentage = 3 # Percentage of users to roll out to if counter % 100 > rolloutPercentage # Don't show if user is not part of roll out return cb(null, false) From 4d4dba96777e2c103e9c2e4d316991f8ec783e24 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 19 Oct 2017 15:31:19 +0100 Subject: [PATCH 93/99] Adds some onboarding logging to investigate potential bug --- .../web/app/coffee/Features/Project/ProjectController.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 80c74754e0..4cebc197a7 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -273,6 +273,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else + logger.log user_id, event, "autocompile onboarding not shown yet to this user" return cb(null, true) }, (err, results)-> if err? From 6fd1d493e3ddf28801c0ba415036760d914fe918 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 19 Oct 2017 15:47:12 +0100 Subject: [PATCH 94/99] Also add logging for track changes --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 4cebc197a7..6e3b84f383 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -229,6 +229,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else + logger.log user_id, event, "track changes onboarding not shown yet to this user" return cb(null, true) showPerUserTCNotice: (cb) -> cb = underscore.once(cb) @@ -247,6 +248,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else + logger.log user_id, event, "per user track changes notice not shown yet to this user" return cb(null, true) showAutoCompileOnboarding: (cb) -> cb = underscore.once(cb) From ebaa640c516dd2b6646c3c209339c91d7c72ed51 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Thu, 19 Oct 2017 16:02:40 +0100 Subject: [PATCH 95/99] Fix log call signature --- .../app/coffee/Features/Project/ProjectController.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 6e3b84f383..424fe7e248 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -229,7 +229,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else - logger.log user_id, event, "track changes onboarding not shown yet to this user" + logger.log { user_id, event }, "track changes onboarding not shown yet to this user" return cb(null, true) showPerUserTCNotice: (cb) -> cb = underscore.once(cb) @@ -248,7 +248,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else - logger.log user_id, event, "per user track changes notice not shown yet to this user" + logger.log { user_id, event }, "per user track changes notice not shown yet to this user" return cb(null, true) showAutoCompileOnboarding: (cb) -> cb = underscore.once(cb) @@ -275,7 +275,7 @@ module.exports = ProjectController = else if event? return cb(null, false) else - logger.log user_id, event, "autocompile onboarding not shown yet to this user" + logger.log { user_id, event }, "autocompile onboarding not shown yet to this user" return cb(null, true) }, (err, results)-> if err? From edb2a6c88b803cf9051fbbf63bd4842aec37e66d Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Fri, 20 Oct 2017 10:23:52 +0100 Subject: [PATCH 96/99] Increase rollout to 5% --- .../web/app/coffee/Features/Project/ProjectController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 80c74754e0..8091cf9864 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -257,7 +257,7 @@ module.exports = ProjectController = timestamp = parseInt(user_id.toString().substring(0, 8), 16) counter = parseInt(user_id.toString().substring(18, 24), 16) - rolloutPercentage = 3 # Percentage of users to roll out to + rolloutPercentage = 5 # Percentage of users to roll out to if counter % 100 > rolloutPercentage # Don't show if user is not part of roll out return cb(null, false) From 624dd26f390092c9f94fc5888418989d10c84ce1 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 20 Oct 2017 16:20:38 +0100 Subject: [PATCH 97/99] Avoid loading onboarding images on page load. --- .../web/app/views/project/editor/feature-onboarding.pug | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/web/app/views/project/editor/feature-onboarding.pug b/services/web/app/views/project/editor/feature-onboarding.pug index 833eac5a80..f0047ce45c 100644 --- a/services/web/app/views/project/editor/feature-onboarding.pug +++ b/services/web/app/views/project/editor/feature-onboarding.pug @@ -33,7 +33,7 @@ loop ) source(ng-src="{{ '/img/onboarding/review-panel/open-review.mp4' }}", type="video/mp4") - img(src="/img/onboarding/review-panel/open-review.gif") + img(ng-src="{{ '/img/onboarding/review-panel/open-review.gif' }}", alt="Open review panel demo") div(ng-show="onboarding.innerStep === 2;") video.feat-onboard-video( video-play-state="onboarding.innerStep === 2;" @@ -41,7 +41,7 @@ loop ) source(ng-src="{{ '/img/onboarding/review-panel/commenting.mp4' }}", type="video/mp4") - img(src="/img/onboarding/review-panel/commenting.gif") + img(ng-src="{{ '/img/onboarding/review-panel/commenting.gif' }}", alt="Commenting demo") div(ng-show="onboarding.innerStep === 3;") video.feat-onboard-video( video-play-state="onboarding.innerStep === 3;" @@ -49,7 +49,7 @@ loop ) source(ng-src="{{ '/img/onboarding/review-panel/add-changes.mp4' }}", type="video/mp4") - img(src="/img/onboarding/review-panel/add-changes.gif") + img(ng-src="{{ '/img/onboarding/review-panel/add-changes.gif' }}", alt="Add changes demo") div(ng-show="onboarding.innerStep === 4;") video.feat-onboard-video( video-play-state="onboarding.innerStep === 4;" @@ -57,7 +57,7 @@ loop ) source(ng-src="{{ '/img/onboarding/review-panel/accept-changes.mp4' }}", type="video/mp4") - img(src="/img/onboarding/review-panel/accept-changes.gif") + img(ng-src="{{ '/img/onboarding/review-panel/accept-changes.gif' }}", alt="Accept changes demo") button.btn.btn-primary.feat-onboard-nav-btn( ng-click="gotoNextStep();" ng-disabled="onboarding.innerStep === onboarding.nSteps;") From 299112f6e06297449fb855eb944ac870e00c92e8 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 11 Oct 2017 11:18:34 +0100 Subject: [PATCH 98/99] toggle project history using setting --- .../Features/History/HistoryController.coffee | 9 ++- services/web/config/settings.defaults.coffee | 3 + .../History/HistoryControllerTests.coffee | 59 +++++++++++++------ 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/services/web/app/coffee/Features/History/HistoryController.coffee b/services/web/app/coffee/Features/History/HistoryController.coffee index d4f42b38b1..6ab7f917eb 100644 --- a/services/web/app/coffee/Features/History/HistoryController.coffee +++ b/services/web/app/coffee/Features/History/HistoryController.coffee @@ -6,7 +6,8 @@ AuthenticationController = require "../Authentication/AuthenticationController" module.exports = HistoryController = proxyToHistoryApi: (req, res, next = (error) ->) -> user_id = AuthenticationController.getLoggedInUserId req - url = settings.apis.trackchanges.url + req.url + url = HistoryController.buildHistoryServiceUrl() + req.url + logger.log url: url, "proxying to track-changes api" getReq = request( url: url @@ -18,3 +19,9 @@ module.exports = HistoryController = getReq.on "error", (error) -> logger.error err: error, "track-changes API error" next(error) + + buildHistoryServiceUrl: () -> + if settings.apis.project_history.enabled + return settings.apis.project_history.url + else + return settings.apis.trackchanges.url diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 2456590709..a013f5c1ec 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -104,6 +104,9 @@ module.exports = settings = url : "http://localhost:3005" trackchanges: url : "http://localhost:3015" + project_history: + enabled: false + url : "http://localhost:3054" docstore: url : "http://localhost:3016" pubUrl: "http://localhost:3016" diff --git a/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee b/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee index 577aae6a9d..db5fade45a 100644 --- a/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee @@ -22,37 +22,60 @@ describe "HistoryController", -> @next = sinon.stub() @settings.apis = trackchanges: + enabled: false url: "http://trackchanges.example.com" + project_history: + url: "http://project_history.example.com" @proxy = events: {} pipe: sinon.stub() on: (event, handler) -> @events[event] = handler @request.returns @proxy - @HistoryController.proxyToHistoryApi @req, @res, @next describe "successfully", -> - it "should get the user id", -> - @AuthenticationController.getLoggedInUserId - .calledWith(@req) - .should.equal true + describe "with project history enabled", -> + beforeEach -> + @settings.apis.project_history.enabled = true + @HistoryController.proxyToHistoryApi @req, @res, @next - it "should call the track changes api", -> - @request - .calledWith({ - url: "#{@settings.apis.trackchanges.url}#{@req.url}" - method: @req.method - headers: - "X-User-Id": @user_id - }) - .should.equal true + it "should get the user id", -> + @AuthenticationController.getLoggedInUserId + .calledWith(@req) + .should.equal true - it "should pipe the response to the client", -> - @proxy.pipe - .calledWith(@res) - .should.equal true + it "should call the project history api", -> + @request + .calledWith({ + url: "#{@settings.apis.project_history.url}#{@req.url}" + method: @req.method + headers: + "X-User-Id": @user_id + }) + .should.equal true + + it "should pipe the response to the client", -> + @proxy.pipe + .calledWith(@res) + .should.equal true + + describe "with project history disabled", -> + beforeEach -> + @settings.apis.project_history.enabled = false + @HistoryController.proxyToHistoryApi @req, @res, @next + + it "should call the track changes api", -> + @request + .calledWith({ + url: "#{@settings.apis.trackchanges.url}#{@req.url}" + method: @req.method + headers: + "X-User-Id": @user_id + }) + .should.equal true describe "with an error", -> beforeEach -> + @HistoryController.proxyToHistoryApi @req, @res, @next @proxy.events["error"].call(@proxy, @error = new Error("oops")) it "should pass the error up the call chain", -> From c437eb37d5188841a4e8a8e5d7d15d2da45455ea Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Tue, 24 Oct 2017 09:47:14 +0100 Subject: [PATCH 99/99] handle missing settings.apis.project_history --- .../web/app/coffee/Features/History/HistoryController.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/History/HistoryController.coffee b/services/web/app/coffee/Features/History/HistoryController.coffee index 6ab7f917eb..5fe9cc37b0 100644 --- a/services/web/app/coffee/Features/History/HistoryController.coffee +++ b/services/web/app/coffee/Features/History/HistoryController.coffee @@ -21,7 +21,7 @@ module.exports = HistoryController = next(error) buildHistoryServiceUrl: () -> - if settings.apis.project_history.enabled + if settings.apis.project_history?.enabled return settings.apis.project_history.url else return settings.apis.trackchanges.url