diff --git a/services/web/.gitignore b/services/web/.gitignore index 9c2a272a7a..b416345461 100644 --- a/services/web/.gitignore +++ b/services/web/.gitignore @@ -61,6 +61,7 @@ public/js/utils/ public/stylesheets/style.css public/stylesheets/ol-style.css +public/stylesheets/*.map public/brand/plans.css public/minjs/ diff --git a/services/web/Gruntfile.coffee b/services/web/Gruntfile.coffee index 0845b435c2..d4a4929964 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' @@ -28,9 +30,15 @@ module.exports = (grunt) -> exec: run: command:"node app.js | ./node_modules/logger-sharelatex/node_modules/bunyan/bin/bunyan --color" - cssmin: - command:"node_modules/clean-css/bin/cleancss --s0 -o public/stylesheets/style.css public/stylesheets/style.css" + cssmin_sl: + command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/style.css public/stylesheets/style.css" + cssmin_ol: + command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/ol-style.css public/stylesheets/ol-style.css" + forever: + app: + options: + index: "app.js" watch: coffee: @@ -137,20 +145,31 @@ module.exports = (grunt) -> less: app: + options: + sourceMap: true + sourceMapFilename: "public/stylesheets/style.css.map" + sourceMapBasepath: "public/stylesheets" files: "public/stylesheets/style.css": "public/stylesheets/style.less" ol: + options: + sourceMap: true + sourceMapFilename: "public/stylesheets/ol-style.css.map" + sourceMapBasepath: "public/stylesheets" files: "public/stylesheets/ol-style.css": "public/stylesheets/ol-style.less" postcss: options: - map: true, + map: + prev: "public/stylesheets/" + inline: false + sourcesContent: true processors: [ require('autoprefixer')({browsers: [ 'last 2 versions', 'ie >= 10' ]}) ] dist: - src: 'public/stylesheets/style.css' + src: [ "public/stylesheets/style.css", "public/stylesheets/ol-style.css" ] env: run: @@ -244,8 +263,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: @@ -381,7 +403,7 @@ module.exports = (grunt) -> grunt.registerTask 'compile:server', 'Compile the server side coffee script', ['clean:app', 'coffee:app', 'coffee:app_dir', 'compile:modules:server'] grunt.registerTask 'compile:client', 'Compile the client side coffee script', ['coffee:client', 'coffee:sharejs', 'wrap_sharejs', "compile:modules:client", 'compile:modules:inject_clientside_includes'] grunt.registerTask 'compile:css', 'Compile the less files to css', ['less', 'postcss:dist'] - grunt.registerTask 'compile:minify', 'Concat and minify the client side js', ['requirejs', "file_append", "exec:cssmin",] + grunt.registerTask 'compile:minify', 'Concat and minify the client side js and css', ['requirejs', "file_append", "exec:cssmin_sl", "exec:cssmin_ol"] grunt.registerTask 'compile:unit_tests', 'Compile the unit tests', ['clean:unit_tests', 'coffee:unit_tests'] grunt.registerTask 'compile:acceptance_tests', 'Compile the acceptance tests', ['clean:acceptance_tests', 'coffee:acceptance_tests'] grunt.registerTask 'compile:smoke_tests', 'Compile the smoke tests', ['coffee:smoke_tests'] @@ -396,6 +418,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 8a844ca0a0..50ced29d60 100644 --- a/services/web/Jenkinsfile +++ b/services/web/Jenkinsfile @@ -1,11 +1,6 @@ pipeline { - agent { - docker { - image 'node:6.9.5' - args "-v /var/lib/jenkins/.npm:/tmp/.npm" - } - } + agent any environment { HOME = "/tmp" @@ -18,6 +13,12 @@ pipeline { stages { stage('Set up') { + agent { + docker { + image 'node:6.9.5' + reuseNode true + } + } steps { // we need to disable logallrefupdates, else git clones during the npm install will require git to lookup the user id // which does not exist in the container's /etc/passwd file, causing the clone to fail. @@ -40,15 +41,28 @@ pipeline { checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'modules/learn-wiki'], [$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[credentialsId: 'GIT_DEPLOY_KEY', url: 'git@bitbucket.org:sharelatex/learn-wiki-web-module.git']]]) 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']]]) } } stage('Install') { + agent { + docker { + image 'node:6.9.5' + args "-v /var/lib/jenkins/.npm:/tmp/.npm" + reuseNode true + } + } steps { + sh 'git config --global core.logallrefupdates false' sh 'mv app/views/external/robots.txt public/robots.txt' sh 'mv app/views/external/googlebdb0f8f7f4a17241.html public/googlebdb0f8f7f4a17241.html' sh 'npm install' sh 'npm rebuild' + // 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' sh 'npm install --quiet grunt-cli' sh 'ls -l node_modules/.bin' @@ -56,29 +70,62 @@ pipeline { } stage('Compile') { + agent { + docker { + image 'node:6.9.5' + reuseNode true + } + } steps { sh 'node_modules/.bin/grunt compile --verbose' + // replace the build number placeholder for sentry + sh 'node_modules/.bin/grunt version' } } stage('Smoke Test') { + agent { + docker { + image 'node:6.9.5' + reuseNode true + } + } steps { sh 'node_modules/.bin/grunt compile:smoke_tests' } } stage('Minify') { + agent { + docker { + image 'node:6.9.5' + reuseNode true + } + } steps { sh 'node_modules/.bin/grunt compile:minify' } } stage('Unit Test') { + agent { + docker { + image 'node:6.9.5' + reuseNode true + } + } steps { sh 'env NODE_ENV=development ./node_modules/.bin/grunt test:unit --reporter=tap' } } + stage('Acceptance Tests') { + steps { + sh 'docker pull sharelatex/acceptance-test-runner' + sh 'docker run --rm -v $(pwd):/app --env SHARELATEX_ALLOW_PUBLIC_ACCESS=true sharelatex/acceptance-test-runner' + } + } + stage('Package') { steps { sh 'rm -rf ./node_modules/grunt*' @@ -87,6 +134,7 @@ pipeline { sh 'tar -czf build.tar.gz --exclude=build.tar.gz --exclude-vcs .' } } + stage('Publish') { steps { withAWS(credentials:'S3_CI_BUILDS_AWS_KEYS', region:"${S3_REGION_BUILD_ARTEFACTS}") { @@ -96,6 +144,18 @@ pipeline { } } } + + + stage('Sync OSS') { + when { + branch 'master' + } + steps { + sshagent (credentials: ['GIT_DEPLOY_KEY']) { + sh 'git push git@github.com:sharelatex/web-sharelatex.git HEAD:master' + } + } + } } post { diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee index 0f7f40a6b4..fd8a7577de 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee @@ -249,3 +249,55 @@ module.exports = CollaboratorsHandler = if err? return callback(err) callback(null, project?) + + transferProjects: (from_user_id, to_user_id, callback=(err, projects) ->) -> + MEMBER_KEYS = ['collaberator_refs', 'readOnly_refs'] + + # 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/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 68b13a8f68..c27bc2fe90 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? @@ -38,17 +42,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") @@ -107,6 +111,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" @@ -144,13 +150,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 @@ -183,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 @@ -209,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 @@ -220,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/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index 61fe7038a6..f18dc56c7b 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,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, 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 + 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) ->) -> @@ -72,18 +76,30 @@ module.exports = CompileManager = else return callback null, true - _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, callback = (err, canCompile)->)-> + _checkCompileGroupAutoCompileLimit: (isAutoCompile, compileGroup, callback = (err, canCompile)->)-> if !isAutoCompile return callback(null, true) - opts = + if compileGroup is "standard" + # apply extra limits to the standard compile group + 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-#{compileGroup}" + opts = endpointName:"auto_compile" timeInterval:20 - subjectName:"everyone" - throttle: 25 + 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-#{compileGroup}-limited" callback err, canCompile _ensureRootDocumentIsSet: (project_id, callback = (error) ->) -> 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" 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/History/HistoryController.coffee b/services/web/app/coffee/Features/History/HistoryController.coffee index d4f42b38b1..c7c869d674 100644 --- a/services/web/app/coffee/Features/History/HistoryController.coffee +++ b/services/web/app/coffee/Features/History/HistoryController.coffee @@ -4,9 +4,33 @@ settings = require "settings-sharelatex" AuthenticationController = require "../Authentication/AuthenticationController" module.exports = HistoryController = + initializeProject: (callback = (error, history_id) ->) -> + return callback() if !settings.apis.project_history?.enabled + request.post { + url: "#{settings.apis.project_history.url}/project" + }, (error, res, body)-> + return callback(error) if error? + + if res.statusCode >= 200 and res.statusCode < 300 + try + project = JSON.parse(body) + catch error + return callback(error) + + overleaf_id = project?.project?.id + if !overleaf_id + error = new Error("project-history did not provide an id", project) + return callback(error) + + callback null, { overleaf_id } + else + error = new Error("project-history returned a non-success status code: #{res.statusCode}") + callback error + 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 +42,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/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/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 8b164fc05b..edf85bbf9d 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,12 +248,40 @@ 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) isTokenMember: (cb) -> cb = underscore.once(cb) if !user_id? return cb() CollaboratorsHandler.userIsTokenMember user_id, project_id, cb + showAutoCompileOnboarding: (cb) -> + cb = underscore.once(cb) + if !user_id? + return cb() + + # Extract data from user's ObjectId + timestamp = parseInt(user_id.toString().substring(0, 8), 16) + counter = parseInt(user_id.toString().substring(18, 24), 16) + + rolloutPercentage = 40 # 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, { enabled: false, showOnboarding: false }) + userSignupDate = new Date(timestamp * 1000) + if userSignupDate > new Date("2017-10-16") + # Don't show for users who registered after it was released + return cb(null, { enabled: true, showOnboarding: false }) + timeout = setTimeout cb, 500 + AnalyticsManager.getLastOccurance user_id, "shown-autocompile-onboarding", (error, event) -> + clearTimeout timeout + if error? + return cb(null, { enabled: true, showOnboarding: false }) + else if event? + return cb(null, { enabled: true, showOnboarding: false }) + else + logger.log { user_id, event }, "autocompile onboarding not shown yet to this user" + return cb(null, { enabled: true, showOnboarding: true }) }, (err, results)-> if err? logger.err err:err, "error getting details for project page" @@ -260,9 +289,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" token = TokenAccessHandler.getRequestToken(req, project_id) @@ -307,6 +336,8 @@ module.exports = ProjectController = trackChangesState: project.track_changes showTrackChangesOnboarding: !!showTrackChangesOnboarding showPerUserTCNotice: !!showPerUserTCNotice + autoCompileEnabled: !!showAutoCompileOnboarding?.enabled + showAutoCompileOnboarding: !!showAutoCompileOnboarding?.showOnboarding privilegeLevel: privilegeLevel chatUrl: Settings.apis.chat.url anonymous: anonymous diff --git a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee index 41b40c11b9..a38b214a9e 100644 --- a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee @@ -2,11 +2,12 @@ logger = require('logger-sharelatex') async = require("async") metrics = require('metrics-sharelatex') Settings = require('settings-sharelatex') -ObjectId = require('mongoose').Types.ObjectId +ObjectId = require('mongoose').Types.ObjectId Project = require('../../models/Project').Project Folder = require('../../models/Folder').Folder ProjectEntityHandler = require('./ProjectEntityHandler') ProjectDetailsHandler = require('./ProjectDetailsHandler') +HistoryController = require('../History/HistoryController') User = require('../../models/User').User fs = require('fs') Path = require "path" @@ -14,23 +15,36 @@ _ = require "underscore" module.exports = ProjectCreationHandler = - createBlankProject : (owner_id, projectName, callback = (error, project) ->)-> + createBlankProject : (owner_id, projectName, projectHistoryId, callback = (error, project) ->)-> metrics.inc("project-creation") + if arguments.length == 3 + callback = projectHistoryId + projectHistoryId = null + ProjectDetailsHandler.validateProjectName projectName, (error) -> return callback(error) if error? logger.log owner_id:owner_id, projectName:projectName, "creating blank project" - rootFolder = new Folder {'name':'rootFolder'} - project = new Project - owner_ref : new ObjectId(owner_id) - name : projectName - if Settings.currentImageName? - project.imageName = Settings.currentImageName - project.rootFolder[0] = rootFolder - User.findById owner_id, "ace.spellCheckLanguage", (err, user)-> - project.spellCheckLanguage = user.ace.spellCheckLanguage - project.save (err)-> - return callback(err) if err? - callback err, project + if projectHistoryId? + ProjectCreationHandler._createBlankProject owner_id, projectName, projectHistoryId, callback + else + HistoryController.initializeProject (error, history) -> + return callback(error) if error? + ProjectCreationHandler._createBlankProject owner_id, projectName, history?.overleaf_id, callback + + _createBlankProject : (owner_id, projectName, projectHistoryId, callback = (error, project) ->)-> + rootFolder = new Folder {'name':'rootFolder'} + project = new Project + owner_ref : new ObjectId(owner_id) + name : projectName + project.overleaf.history.id = projectHistoryId + if Settings.currentImageName? + project.imageName = Settings.currentImageName + project.rootFolder[0] = rootFolder + User.findById owner_id, "ace.spellCheckLanguage", (err, user)-> + project.spellCheckLanguage = user.ace.spellCheckLanguage + project.save (err)-> + return callback(err) if err? + callback err, project createBasicProject : (owner_id, projectName, callback = (error, project) ->)-> self = @ diff --git a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee index 658983d0a9..ff4a1ea0a9 100644 --- a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee @@ -10,7 +10,7 @@ ProjectTokenGenerator = require('./ProjectTokenGenerator') 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) @@ -22,7 +22,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)-> @@ -54,7 +58,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")) @@ -97,4 +101,3 @@ module.exports = ProjectDetailsHandler = Project.update {_id: project_id}, {$set: {tokens: tokens}}, (err) -> return callback(err) if err? callback(null, tokens) - 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/app/coffee/Features/StaticPages/StaticPagesRouter.coffee b/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee index 07923d48d0..e33cae555a 100644 --- a/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee +++ b/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee @@ -14,6 +14,7 @@ module.exports = webRouter.get '/privacy_policy', HomeController.externalPage("privacy", "Privacy Policy") webRouter.get '/planned_maintenance', HomeController.externalPage("planned_maintenance", "Planned Maintenance") webRouter.get '/style', HomeController.externalPage("style_guide", "Style Guide") + webRouter.get '/ol-style', HomeController.externalPage("ol_style_guide", "Overleaf Style Guide") webRouter.get '/jobs', HomeController.externalPage("jobs", "Jobs") webRouter.get '/track-changes-and-comments-in-latex', HomeController.externalPage("review-features-page", "Review features") diff --git a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee index a7f0ccdbeb..3db074b13f 100644 --- a/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee +++ b/services/web/app/coffee/Features/Uploads/ArchiveManager.coffee @@ -1,56 +1,105 @@ -child = require "child_process" 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 = null + 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 + 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('/') + 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) + errorHandler = (err) -> # clean up before calling callback + readStream.unpipe() + readStream.destroy() + callback(err) - callback(error, isTooLarge) + fse.ensureDir Path.dirname(destFile), (err) -> + return errorHandler(err) if err? + writeStream = fs.createWriteStream destFile + writeStream.on 'error', errorHandler + readStream.pipe(writeStream) + _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) -> + 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" + 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 + else # if it's a directory, continue + zipfile.readEntry() + # no more entries to read + zipfile.on "end", callback - extractZipArchive: (source, destination, _callback = (err) ->) -> callback = (args...) -> _callback(args...) @@ -62,36 +111,19 @@ 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]) - - # 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", () -> + ArchiveManager._extractZipFiles source, destination, (err) -> timer.done() - if error? - error = new Error(error) - logger.error err:error, source: source, destination: destination, "error unzipping file" - callback(error) - + if err? + logger.error {err, source, destination}, "unzip failed" + callback(err) + else + callback() + findTopLevelDirectory: (directory, callback = (error, topLevelDir) ->) -> fs.readdir directory, (error, files) -> return callback(error) if error? diff --git a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee index 2e22ed5665..918f66df7b 100644 --- a/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileTypeManager.coffee @@ -18,6 +18,8 @@ module.exports = FileTypeManager = IGNORE_FILENAMES : [ "__MACOSX" + ".git" + ".gitignore" ] MAX_TEXT_FILE_SIZE: 1 * 1024 * 1024 # 1 MB 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/app/coffee/models/Project.coffee b/services/web/app/coffee/models/Project.coffee index b2acce75e0..77f17f542e 100644 --- a/services/web/app/coffee/models/Project.coffee +++ b/services/web/app/coffee/models/Project.coffee @@ -42,6 +42,8 @@ ProjectSchema = new Schema imported_at_ver_id : { type: Number } token : { type: String } read_token : { type: String } + history : + id : { type: Number } ProjectSchema.statics.getProject = (project_or_id, fields, callback)-> if project_or_id._id? diff --git a/services/web/app/views/layout/footer.pug b/services/web/app/views/layout/footer.pug index 62a98ecfaa..7bf47b24f7 100644 --- a/services/web/app/views/layout/footer.pug +++ b/services/web/app/views/layout/footer.pug @@ -1,7 +1,7 @@ footer.site-footer - .container + .site-footer-content .row ul.col-md-9 @@ -38,6 +38,6 @@ footer.site-footer each item in nav.right_footer li if item.url - a(href=item.url, class=item.class) !{item.text} + a(href=item.url, class=item.class, aria-label=item.label) !{item.text} else | !{item.text} diff --git a/services/web/app/views/layout/navbar.pug b/services/web/app/views/layout/navbar.pug index 54509d6565..9e242e1f25 100644 --- a/services/web/app/views/layout/navbar.pug +++ b/services/web/app/views/layout/navbar.pug @@ -4,11 +4,11 @@ nav.navbar.navbar-default button.navbar-toggle(ng-init="navCollapsed = true", ng-click="navCollapsed = !navCollapsed", ng-class="{active: !navCollapsed}") i.fa.fa-bars if settings.nav.custom_logo - a(href='/', style='background-image:url("'+settings.nav.custom_logo+'")').navbar-brand + a(href='/', aria-label=settings.appName, style='background-image:url("'+settings.nav.custom_logo+'")').navbar-brand else if (nav.title) - a(href='/').navbar-title #{nav.title} + a(href='/', aria-label=settings.appName).navbar-title #{nav.title} else - a(href='/').navbar-brand + a(href='/', aria-label=settings.appName).navbar-brand .navbar-collapse.collapse(collapse="navCollapsed") diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index 7700d0dc6f..5bb7f98354 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -124,6 +124,8 @@ block requirejs window.trackChangesState = data.trackChangesState; window.showTrackChangesOnboarding = #{!!showTrackChangesOnboarding}; window.showPerUserTCNotice = #{!!showPerUserTCNotice}; + window.autoCompileEnabled = #{!!autoCompileEnabled}; + window.showAutoCompileOnboarding = #{!!showAutoCompileOnboarding} window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)}; window.enableTokenAccessUI = #{enableTokenAccessUI} window.requirejs = { diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 6007f2e0be..86cc63a5e5 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -94,4 +94,17 @@ div.full-size( ng-show="ui.view == 'pdf'" ) include ./pdf - + +#onboarding-autocompile.onboarding-autocompile.popover( + ng-controller="AutoCompileOnboardingController" + ng-if="onboarding.autoCompile == 'show'" + ng-class="placement" +) + .popover-inner + 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%") + p #{translate("auto_compile_onboarding_description")} + button.btn.btn-default.btn-block(ng-click="dismiss()") + | #{translate("got_it")} 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;") diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 960d4bf2c9..eb2b4bfefd 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" @@ -26,6 +26,17 @@ div.full-size.pdf(ng-controller="PdfController") ) span.caret ul.dropdown-menu.dropdown-menu-left + // Only show if on beta program or part of rollout + if user.betaProgram || autoCompileEnabled + li.dropdown-header #{translate("auto_compile")} + li + a(href, ng-click="autocompile_enabled = true") + i.fa.fa-fw(ng-class="{'fa-check': autocompile_enabled}") + |  #{translate('on')} + li + a(href, ng-click="autocompile_enabled = false") + i.fa.fa-fw(ng-class="{'fa-check': !autocompile_enabled}") + |  #{translate('off')} li.dropdown-header #{translate("compile_mode")} li a(href, ng-click="draft = false") @@ -306,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") @@ -333,6 +347,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")}. @@ -376,6 +394,12 @@ div.full-size.pdf(ng-controller="PdfController") ng-click="startFreeTrial('compile-timeout')" ) #{translate("start_free_trial")} + + .alert.alert-danger(ng-show="pdf.autoCompileDisabled") + 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/app/views/project/list.pug b/services/web/app/views/project/list.pug index ddf80a0b5f..c2fcb53a31 100644 --- a/services/web/app/views/project/list.pug +++ b/services/web/app/views/project/list.pug @@ -15,58 +15,58 @@ block content } }; + .announcements( + ng-controller="AnnouncementsController" + ng-class="{ 'announcements-open': ui.isOpen }" + ng-cloak + ) + .announcements-backdrop( + ng-if="ui.isOpen" + ng-click="toggleAnnouncementsUI();" + ) + a.announcements-btn( + href + ng-if="announcements.length" + ng-click="toggleAnnouncementsUI();" + ng-class="{ 'announcements-btn-open': ui.isOpen, 'announcements-btn-has-new': ui.newItems }" + ) + span.announcements-badge(ng-if="ui.newItems") {{ ui.newItems }} + .announcements-body( + ng-if="ui.isOpen" + ) + .announcements-scroller + .announcement( + ng-repeat="announcement in announcements | filter:(ui.newItems ? { read: false } : '') track by announcement.id" + ) + h2.announcement-header {{ announcement.title }} + p.announcement-description(ng-bind-html="announcement.excerpt") + .announcement-meta + p.announcement-date {{ announcement.date | date:"longDate" }} + a.announcement-link( + ng-href="{{ announcement.url }}" + ng-click="logAnnouncementClick()", + target="_blank" + ) Read more + div.text-center( + ng-if="ui.newItems > 0 && ui.newItems < announcements.length" + ) + a.btn.btn-default.btn-sm( + href + ng-click="showAll();" + ) Show all .content.content-alt.project-list-page(ng-controller="ProjectPageController") - .container - .announcements( - ng-controller="AnnouncementsController" - ng-class="{ 'announcements-open': ui.isOpen }" - ng-cloak - ) - .announcements-backdrop( - ng-if="ui.isOpen" - ng-click="toggleAnnouncementsUI();" - ) - a.announcements-btn( - href - ng-if="announcements.length" - ng-click="toggleAnnouncementsUI();" - ng-class="{ 'announcements-btn-open': ui.isOpen, 'announcements-btn-has-new': ui.newItems }" - ) - span.announcements-badge(ng-if="ui.newItems") {{ ui.newItems }} - .announcements-body( - ng-if="ui.isOpen" - ) - .announcements-scroller - .announcement( - ng-repeat="announcement in announcements | filter:(ui.newItems ? { read: false } : '') track by announcement.id" - ) - h2.announcement-header {{ announcement.title }} - p.announcement-description(ng-bind-html="announcement.excerpt") - .announcement-meta - p.announcement-date {{ announcement.date | date:"longDate" }} - a.announcement-link( - ng-href="{{ announcement.url }}" - ng-click="logAnnouncementClick()", - target="_blank" - ) Read more - div.text-center( - ng-if="ui.newItems > 0 && ui.newItems < announcements.length" - ) - a.btn.btn-default.btn-sm( - href - ng-click="showAll();" - ) Show all + .project-list-content - .row(ng-cloak) - span(ng-if="projects.length > 0") - aside.col-md-2.col-xs-3 + .row.project-list-row(ng-cloak) + .project-list-container(ng-if="projects.length > 0") + aside.project-list-sidebar.col-md-2.col-xs-3 include ./list/side-bar - .col-md-10.col-xs-9 + .project-list-main.col-md-10.col-xs-9 include ./list/notifications include ./list/project-list - span(ng-if="projects.length === 0") + .project-list-empty(ng-if="projects.length === 0") .col-md-offset-2.col-md-8.col-md-offset-2.col-xs-8 include ./list/empty-project-list diff --git a/services/web/app/views/project/list/project-list.pug b/services/web/app/views/project/list/project-list.pug index 5d1866fab7..e65e2e98d3 100644 --- a/services/web/app/views/project/list/project-list.pug +++ b/services/web/app/views/project/list/project-list.pug @@ -7,6 +7,7 @@ .form-group.has-feedback.has-feedback-left.col-md-7.col-xs-12 input.form-control.col-md-7.col-xs-12( placeholder=translate('search_projects')+"…", + aria-label=translate('search_projects')+"…", autofocus='autofocus', ng-model="searchText.value", focus-on='search:clear', @@ -127,6 +128,7 @@ input.select-all( select-all, type="checkbox" + aria-label=translate('select_all_projects') ) span.header.clickable(ng-click="changePredicate('name')") #{translate("title")} i.tablesort.fa(ng-class="getSortIconClass('name')") @@ -147,6 +149,7 @@ type="checkbox", ng-model="project.selected" stop-propagation="click" + aria-label=translate('select_project') + " '{{ project.name }}'" ) span a.projectName( diff --git a/services/web/app/views/project/list/side-bar.pug b/services/web/app/views/project/list/side-bar.pug index 5429045afb..fe053f0019 100644 --- a/services/web/app/views/project/list/side-bar.pug +++ b/services/web/app/views/project/list/side-bar.pug @@ -1,5 +1,5 @@ .dropdown(dropdown) - a.btn.btn-primary.dropdown-toggle( + a.btn.btn-primary.sidebar-new-proj-btn.dropdown-toggle( href="#", data-toggle="dropdown", dropdown-toggle @@ -45,7 +45,7 @@ a(href) #{translate("shared_with_you")} li(ng-class="{active: (filter == 'archived')}", ng-click="filterProjects('archived')") a(href) #{translate("deleted_projects")} - li + li.separator h2 #{translate("folders")} li.tag( ng-repeat="tag in tags | orderBy:'name'", diff --git a/services/web/cleanup.js b/services/web/cleanup.js deleted file mode 100644 index 9d6d88285c..0000000000 --- a/services/web/cleanup.js +++ /dev/null @@ -1,11 +0,0 @@ -var keys = require('./app/js/infrastructure/Keys'); -var settings = require('settings-sharelatex'); -var queueName = process.argv[2]; -var projectQueueName = process.argv[3]; -var queue = require('fairy').connect(settings.redis.web).queue(queueName); -console.log("cleaning up queue "+ queueName + " " + projectQueueName); -queue._requeue_group(projectQueueName); - -//fairy should kill the process but just in case -thirtySeconds = 30 * 1000 -setTimeout(process.exit, thirtySeconds) diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index edd06eb574..69bf0a3b7c 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -109,6 +109,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" @@ -442,3 +445,8 @@ module.exports = settings = # name : "all projects", # url: "/templates/all" #}] + + rateLimits: + autoCompile: + everyone: 100 + standard: 25 diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json index bfb59b91cc..6ece76837e 100644 --- a/services/web/npm-shrinkwrap.json +++ b/services/web/npm-shrinkwrap.json @@ -1,1686 +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", + "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", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "cliff": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.9.tgz", + "integrity": "sha1-ohHgnGo947oa8n0EnTASUNGIErw=", + "dev": true, + "requires": { + "colors": "0.6.2", + "eyes": "0.1.8", + "winston": "0.8.0" + } + }, + "winston": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", + "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", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true, + "optional": true + }, + "cycle": { + "version": "1.0.3", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "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", - "from": "dtrace-provider@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", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.2.8.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/forever/-/forever-0.14.2.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "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", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "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", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "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-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-contrib-clean": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz", + "integrity": "sha1-9T397ghJsce0Dp67umn0jExgecU=", + "dev": true, + "requires": { + "rimraf": "2.2.6" + } }, - "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", + "grunt-contrib-coffee": { + "version": "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", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "dev": true, + "requires": { + "mkdirp": "0.3.5" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "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", + "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", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/grunt-contrib-requirejs/-/grunt-contrib-requirejs-0.4.1.tgz", + "integrity": "sha1-hiuhZxQbio82r1RE/qsycruM9L0=", + "dev": true, + "requires": { + "requirejs": "2.1.22" + } + }, + "grunt-contrib-watch": { + "version": "1.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", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "grunt-env": { + "version": "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 <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=", + "dev": true + } + } + }, + "grunt-exec": { + "version": "0.4.7", + "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", + "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz", + "integrity": "sha1-TpRf5XlZzA3neZCDtrQq7ZYWNQo=" + }, + "grunt-file-append": { + "version": "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", + "resolved": "https://registry.npmjs.org/grunt-forever/-/grunt-forever-0.4.7.tgz", + "integrity": "sha1-dHDb4a2hFFAhZKTCoAOHXfj+EzA=", + "dev": true, + "requires": { + "forever": "0.14.2" + } + }, + "grunt-git-rev-parse": { + "version": "0.1.5", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz", + "integrity": "sha1-P1att9oG6BR5XuJBWw6+X7iQPrs=", + "dev": true, + "requires": { + "zlib-browserify": "0.0.1" + } + }, + "grunt-mocha-test": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.9.0.tgz", + "integrity": "sha1-BNFfMl8OKJcrLMZB9OMEwGxFwQs=", + "dev": true, + "requires": { + "hooker": "0.2.3", + "mocha": "1.17.1" + } + }, + "grunt-newer": { + "version": "1.3.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", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "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", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "grunt-parallel": { + "version": "0.5.1", + "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", + "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "integrity": "sha1-kWKpHhGBnEvNp9oVz1/vqtB3iCM=", + "dev": true + } + } + }, + "grunt-postcss": { + "version": "0.8.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", + "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=", + "dev": true + } + } + }, + "grunt-sed": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-sed/-/grunt-sed-0.1.1.tgz", + "integrity": "sha1-JhPUhpCTGbP49L112vtGpkLsP4I=", + "dev": true, + "requires": { + "replace": "0.2.10" + } + }, + "grunt-shell": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-2.1.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "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", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.5.tgz", + "integrity": "sha1-HSuFQVjsgWkRPGy39raAHpniEdU=", + "dev": true + }, + "i18next": { + "version": "1.7.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-1.7.10.tgz", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.1" + } }, "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", + "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", + "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" + } } } } @@ -1688,2284 +3246,4142 @@ }, "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", + "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", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.0.8.tgz", + "integrity": "sha1-6TfN/cxXgaAIF67EB56Fs+wVeiA=", + "dev": true, + "optional": true, + "requires": { + "commander": "2.0.0" + } + }, + "commander": { + "version": "2.0.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", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true, + "optional": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true, + "optional": true } } }, "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", + "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", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz", + "integrity": "sha1-32MGD789Myhqdqr21Vophtn/hhk=", + "dev": true + }, + "optimist": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", + "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", + "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", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "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", + "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", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "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", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.5.3.tgz", + "integrity": "sha1-iDyi7GBfXtZKTVGQsmJUAZKPj40=", + "dev": true, + "requires": { + "eventemitter2": "0.4.14", + "lazy": "1.0.11" + } + }, + "num2fraction": { + "version": "1.2.2", + "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", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "dev": true, + "requires": { + "hoek": "0.9.1" + } + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "dev": true, + "optional": true, + "requires": { + "boom": "0.4.2" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true, + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "dev": true, + "optional": true, + "requires": { + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime": "1.2.11" + } + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "dev": 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", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true, + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "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", + "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", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "integrity": "sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g=", + "dev": true + }, + "request": { + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "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", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "dev": true, + "optional": true, + "requires": { + "hoek": "0.9.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true, + "optional": true + } + } }, "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", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", + "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", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-0.0.3.tgz", + "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", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.14.1.tgz", + "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", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "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", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "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", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true + }, + "tiny-lr": { + "version": "0.2.1", + "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", + "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", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "bytes": { + "version": "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", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.3.1" + } + }, + "iconv-lite": { + "version": "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", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "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", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + } + } + } + } }, "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" + } } } }, "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", + "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", + "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", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "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", + "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", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "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", + "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", + "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", + "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", + "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 335e99b85d..e831d929e1 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -25,11 +25,12 @@ "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", - "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", @@ -54,8 +55,7 @@ "passport-oauth2-refresh": "^1.0.0", "passport-saml": "^0.15.0", "pug": "^2.0.0-beta6", - "redis": "0.10.1", - "redis-sharelatex": "git+https://github.com/sharelatex/redis-sharelatex.git#v1.0.2", + "redis-sharelatex": "git+https://github.com/sharelatex/redis-sharelatex.git#v1.0.4", "request": "^2.69.0", "requests": "^0.1.7", "rimraf": "2.2.6", @@ -68,16 +68,17 @@ "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", "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 +90,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/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index a298f3732b..d2cafb7cef 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" @@ -71,12 +72,17 @@ define [ view: "editor" chatOpen: false pdfLayout: 'sideBySide' - reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}") - miniReviewPanelVisible: false + pdfHidden: false, + pdfWidth: 0, + reviewPanelOpen: localStorage("ui.reviewPanelOpen.#{window.project_id}"), + miniReviewPanelVisible: false, + } + $scope.onboarding = { + autoCompile: if window.showAutoCompileOnboarding then 'unseen' else 'dismissed' } $scope.user = window.user $scope.__enableTokenAccessUI = window.enableTokenAccessUI == true - + $scope.$watch "project.features.trackChangesVisible", (visible) -> return if !visible? $scope.ui.showCollabFeaturesOnboarding = window.showTrackChangesOnboarding and visible @@ -101,6 +107,10 @@ define [ if value? localStorage "ui.reviewPanelOpen.#{window.project_id}", value + $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) -> if newView? and newView != "editor" and newView != "pdf" @@ -183,6 +193,20 @@ 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) + ) + 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] diff --git a/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee new file mode 100644 index 0000000000..a57575fb94 --- /dev/null +++ b/services/web/public/coffee/ide/AutoCompileOnboardingController.coffee @@ -0,0 +1,26 @@ +define [ + "base" +], (App) -> + App.controller "AutoCompileOnboardingController", ($scope, event_tracking) -> + recompileBtn = angular.element('#recompile') + 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({ + top: top, + left: left - popover.width() + }) + else + $scope.placement = 'right' + popover.offset({ + top: top, + left: left + recompileBtn.width() + }) + + $scope.dismiss = () -> + $scope.onboarding.autoCompile = 'dismissed' + event_tracking.sendMB "shown-autocompile-onboarding" diff --git a/services/web/public/coffee/ide/editor/Document.coffee b/services/web/public/coffee/ide/editor/Document.coffee index d1aa883734..459f033ac6 100644 --- a/services/web/public/coffee/ide/editor/Document.coffee +++ b/services/web/public/coffee/ide/editor/Document.coffee @@ -252,21 +252,34 @@ define [ _joinDoc: (callback = (error) ->) -> if @doc? - @ide.socket.emit 'joinDoc', @doc_id, @doc.getVersion(), (error, docLines, version, updates, ranges) => + @ide.socket.emit 'joinDoc', @doc_id, @doc.getVersion(), { encodeRanges: true }, (error, docLines, version, updates, ranges) => return callback(error) if error? @joined = true @doc.catchUp( updates ) - @_catchUpRanges( ranges?.changes, ranges?.comments ) + @_decodeRanges(ranges) + @_catchUpRanges(ranges?.changes, ranges?.comments) callback() else - @ide.socket.emit 'joinDoc', @doc_id, (error, docLines, version, updates, ranges) => + @ide.socket.emit 'joinDoc', @doc_id, { encodeRanges: true }, (error, docLines, version, updates, ranges) => return callback(error) if error? @joined = true @doc = new ShareJsDoc @doc_id, docLines, version, @ide.socket + @_decodeRanges(ranges) @ranges = new RangesTracker(ranges?.changes, ranges?.comments) @_bindToShareJsDocEvents() callback() + _decodeRanges: (ranges) -> + decodeFromWebsockets = (text) -> decodeURIComponent(escape(text)) + try + for change in ranges.changes or [] + change.op.i = decodeFromWebsockets(change.op.i) if change.op.i? + change.op.d = decodeFromWebsockets(change.op.d) if change.op.d? + for comment in ranges.comments or [] + comment.op.c = decodeFromWebsockets(comment.op.c) if comment.op.c? + catch err + console.log(err) + _leaveDoc: (callback = (error) ->) -> sl_console.log '[_leaveDoc] Sending leaveDoc request' @ide.socket.emit 'leaveDoc', @doc_id, (error) => @@ -309,6 +322,9 @@ define [ @ide.pushEvent "op:acknowledged", doc_id: @doc_id op: op + @ide.$scope.$emit "ide:opAcknowledged", + doc_id: @doc_id + op: op @trigger "op:acknowledged" @doc.on "op:timeout", (op) => @ide.pushEvent "op:timeout", diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index aa1ba9dc5b..577a3a0e75 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -374,6 +374,21 @@ define [ if scope.eventsBridge? session.on "changeScrollTop", onScroll + $rootScope.hasLintingError = false + session.on('changeAnnotation', () -> + # Both linter errors and compile logs are set as error annotations, + # however when the user types something, the compile logs are + # replaced with linter errors. When we check for lint errors before + # autocompile we are guaranteed to get linter errors + hasErrors = session + .getAnnotations() + .filter((annotation) -> annotation.type != 'info') + .length > 0 + + if ($rootScope.hasLintingError != hasErrors) + $rootScope.hasLintingError = hasErrors + ) + setTimeout () -> # Let any listeners init themselves onScroll(editor.renderer.getScrollTop()) 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 55104341e8..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,21 +1,13 @@ define [ "ide/editor/directives/aceEditor/auto-complete/CommandManager" "ide/editor/directives/aceEditor/auto-complete/EnvironmentManager" + "ide/editor/directives/aceEditor/auto-complete/Helpers" "ace/ace" "ace/ext-language_tools" -], (CommandManager, EnvironmentManager) -> +], (CommandManager, EnvironmentManager, Helpers) -> Range = ace.require("ace/range").Range aceSnippetManager = ace.require('ace/snippets').snippetManager - getLastCommandFragment = (lineUpToCursor) -> - if m = lineUpToCursor.match(/(\\[^\\]+)$/) - return m[1] - else - return null - - getCommandNameFromFragment = (commandFragment) -> - commandFragment?.match(/\\(\w+)\{/)?[1] - class AutoCompleteManager constructor: (@$scope, @editor, @element, @labelsManager, @graphics, @preamble) -> @suggestionManager = new CommandManager() @@ -48,15 +40,11 @@ define [ Preamble = @preamble GraphicsCompleter = getCompletions: (editor, session, pos, prefix, callback) -> - upToCursorRange = new Range(pos.row, 0, pos.row, pos.column) - lineUpToCursor = editor.getSession().getTextRange(upToCursorRange) - commandFragment = getLastCommandFragment(lineUpToCursor) + context = Helpers.getContext(editor, pos) + {lineUpToCursor, commandFragment, lineBeyondCursor, needsClosingBrace} = context if commandFragment match = commandFragment.match(/^~?\\(includegraphics(?:\[.*])?){([^}]*, *)?(\w*)/) if match - beyondCursorRange = new Range(pos.row, pos.column, pos.row, 99999) - lineBeyondCursor = editor.getSession().getTextRange(beyondCursorRange) - needsClosingBrace = !lineBeyondCursor.match(/^[^{]*}/) commandName = match[1] currentArg = match[3] graphicsPaths = Preamble.getGraphicsPaths() @@ -78,15 +66,11 @@ define [ labelsManager = @labelsManager LabelsCompleter = getCompletions: (editor, session, pos, prefix, callback) -> - upToCursorRange = new Range(pos.row, 0, pos.row, pos.column) - lineUpToCursor = editor.getSession().getTextRange(upToCursorRange) - commandFragment = getLastCommandFragment(lineUpToCursor) + context = Helpers.getContext(editor, pos) + {lineUpToCursor, commandFragment, lineBeyondCursor, needsClosingBrace} = context if commandFragment refMatch = commandFragment.match(/^~?\\([a-z]*ref){([^}]*, *)?(\w*)/) if refMatch - beyondCursorRange = new Range(pos.row, pos.column, pos.row, 99999) - lineBeyondCursor = editor.getSession().getTextRange(beyondCursorRange) - needsClosingBrace = !lineBeyondCursor.match(/^[^{]*}/) commandName = refMatch[1] currentArg = refMatch[2] result = [] @@ -108,15 +92,13 @@ define [ references = @$scope.$root._references ReferencesCompleter = getCompletions: (editor, session, pos, prefix, callback) -> - upToCursorRange = new Range(pos.row, 0, pos.row, pos.column) - lineUpToCursor = editor.getSession().getTextRange(upToCursorRange) - commandFragment = getLastCommandFragment(lineUpToCursor) + context = Helpers.getContext(editor, pos) + {lineUpToCursor, commandFragment, lineBeyondCursor, needsClosingBrace} = context if commandFragment - citeMatch = commandFragment.match(/^~?\\([a-z]*cite[a-z]*(?:\[.*])?){([^}]*, *)?(\w*)/) + citeMatch = commandFragment.match( + /^~?\\([a-z]*cite[a-z]*(?:\[.*])?){([^}]*, *)?(\w*)/ + ) if citeMatch - beyondCursorRange = new Range(pos.row, pos.column, pos.row, 99999) - lineBeyondCursor = editor.getSession().getTextRange(beyondCursorRange) - needsClosingBrace = !lineBeyondCursor.match(/^[^{]*}/) commandName = citeMatch[1] previousArgs = citeMatch[2] currentArg = citeMatch[3] @@ -160,8 +142,8 @@ define [ onChange: (change) -> cursorPosition = @editor.getCursorPosition() end = change.end - range = new Range(end.row, 0, end.row, end.column) - lineUpToCursor = @editor.getSession().getTextRange(range) + context = Helpers.getContext(@editor, end) + {lineUpToCursor, commandFragment, commandName, lineBeyondCursor, needsClosingBrace} = context if lineUpToCursor.match(/.*%.*/) return lastCharIsBackslash = lineUpToCursor.slice(-1) == "\\" @@ -170,8 +152,6 @@ define [ if lastTwoChars.match(/^\\[^a-z]$/) @editor?.completer?.detach?() return - commandFragment = getLastCommandFragment(lineUpToCursor) - commandName = getCommandNameFromFragment(commandFragment) if commandName in ['begin', 'end'] return # Check that this change was made by us, not a collaborator @@ -233,10 +213,10 @@ define [ range.start.column, ) ) - # Delete back to last backslash, as appropriate - lastBackslashIndex = lineUpToCursor.lastIndexOf('\\') - if lastBackslashIndex != -1 - leftRange.start.column = lastBackslashIndex + # Delete back to command start, as appropriate + commandStartIndex = Helpers.getLastCommandFragmentIndex(lineUpToCursor) + if commandStartIndex != -1 + leftRange.start.column = commandStartIndex else leftRange.start.column -= completions.filterText.length editor.session.remove(leftRange) @@ -310,5 +290,5 @@ define [ currentLineOffset = i + 1 break currentLine = text.slice(currentLineOffset, pos) - fragment = getLastCommandFragment(currentLine) or "" + fragment = Helpers.getLastCommandFragment(currentLine) or "" return fragment 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 0a202a7793..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 @@ -1,10 +1,15 @@ define [], () -> noArgumentCommands = [ 'item', 'hline', 'lipsum', 'centering', 'noindent', 'textwidth', 'draw', - 'maketitle', 'newpage', 'verb', 'bibliography', 'fi', 'hfill', 'par', - 'in', 'sum', 'cdot', 'alpha', 'ldots', 'else', 'linewidth', 'left', - 'right', 'today', 'clearpage', 'newline', 'endinput', 'mu', - 'tableofcontents', 'vfill', 'bigskip', 'fill', 'cleardoublepage' + 'maketitle', 'newpage', 'verb', 'bibliography', 'hfill', 'par', + 'in', 'sum', 'cdot', 'ldots', 'linewidth', 'left', 'right', 'today', + 'clearpage', 'newline', 'endinput', 'tableofcontents', 'vfill', + 'bigskip', 'fill', 'cleardoublepage', 'infty', 'leq', 'geq', 'times', + 'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'varepsilon', 'zeta', + 'eta', 'theta', 'vartheta', 'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi', + 'pi', 'varpi', 'rho', 'varrho', 'sigma', 'varsigma', 'tau', 'upsilon', + 'phi', 'varphi', 'chi', 'psi', 'omega', 'Gamma', 'Delta', 'Theta', + 'Lambda', 'Xi', 'Pi', 'Sigma', 'Upsilon', 'Phi', 'Psi', 'Omega' ] singleArgumentCommands = [ 'chapter', 'usepackage', 'section', 'label', 'textbf', 'subsection', @@ -13,11 +18,12 @@ define [], () -> 'hspace', 'bibitem', 'url', 'large', 'subsubsection', 'textsc', 'date', 'footnote', 'small', 'thanks', 'underline', 'graphicspath', 'pageref', 'section*', 'subsection*', 'subsubsection*', 'sqrt', 'text', - 'normalsize', 'Large', 'paragraph', 'pagestyle', 'thispagestyle', - 'bibliographystyle' + 'normalsize', 'footnotesize', 'Large', 'paragraph', 'pagestyle', + 'thispagestyle', 'bibliographystyle', 'hat' ] doubleArgumentCommands = [ - 'newcommand', 'frac', 'renewcommand', 'setlength', 'href', 'newtheorem' + 'newcommand', 'frac', 'dfrac', 'renewcommand', 'setlength', 'href', + 'newtheorem' ] tripleArgumentCommands = [ 'addcontentsline', 'newacronym', 'multicolumn' @@ -25,12 +31,12 @@ define [], () -> special = ['LaTeX', 'TeX'] rawCommands = [].concat( - noArgumentCommands, - singleArgumentCommands, - doubleArgumentCommands, - tripleArgumentCommands, - special - ) + noArgumentCommands, + singleArgumentCommands, + doubleArgumentCommands, + tripleArgumentCommands, + special + ) noArgumentCommands = for cmd in noArgumentCommands { @@ -79,7 +85,7 @@ define [], () -> # hacky solution: limit iterations limit = null if window?._ide?.browserIsSafari - limit = 100 + limit = 5000 # fully formed commands realCommands = [] diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee new file mode 100644 index 0000000000..7beb41debd --- /dev/null +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/Helpers.coffee @@ -0,0 +1,45 @@ +define [ + "ace/ace" + "ace/ext-language_tools" +], () -> + Range = ace.require("ace/range").Range + + Helpers = + getLastCommandFragment: (lineUpToCursor) -> + if (index = Helpers.getLastCommandFragmentIndex(lineUpToCursor)) > -1 + return lineUpToCursor.slice(index) + else + return null + + getLastCommandFragmentIndex: (lineUpToCursor) -> + # This is hack to let us skip over commands in arguments, and + # go to the command on the same 'level' as us. E.g. + # \includegraphics[width=\textwidth]{.. + # should not match the \textwidth. + blankArguments = lineUpToCursor.replace /\[([^\]]*)\]/g, (args) -> + Array(args.length+1).join('.') + if m = blankArguments.match(/(\\[^\\]+)$/) + return m.index + else + return -1 + + getCommandNameFromFragment: (commandFragment) -> + commandFragment?.match(/\\(\w+)\{/)?[1] + + getContext: (editor, pos) -> + upToCursorRange = new Range(pos.row, 0, pos.row, pos.column) + lineUpToCursor = editor.getSession().getTextRange(upToCursorRange) + commandFragment = Helpers.getLastCommandFragment(lineUpToCursor) + commandName = Helpers.getCommandNameFromFragment(commandFragment) + beyondCursorRange = new Range(pos.row, pos.column, pos.row, 99999) + lineBeyondCursor = editor.getSession().getTextRange(beyondCursorRange) + needsClosingBrace = !lineBeyondCursor.match(/^[^{]*}/) + return { + lineUpToCursor, + commandFragment, + commandName, + lineBeyondCursor, + needsClosingBrace + } + + return Helpers 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 diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index d06d5822a4..4846837856 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -5,8 +5,10 @@ define [ "libs/bib-log-parser" "services/log-hints-feedback" ], (App, Ace, HumanReadableLogs, BibLogParser) -> - App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) -> + AUTO_COMPILE_TIMEOUT = 5000 + OP_ACKNOWLEDGEMENT_TIMEOUT = 1100 + App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) -> # enable per-user containers by default perUserCompile = true autoCompile = true @@ -66,13 +68,50 @@ 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", () -> $scope.pdf.view = 'errors' $scope.pdf.renderingError = true + autoCompileTimeout = null + triggerAutoCompile = () -> + 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 + # changed and continue with recompile + isTimeNonMonotonic = timeSinceLastCompile < 0 + + if isTimeNonMonotonic || timeSinceLastCompile >= AUTO_COMPILE_TIMEOUT + if (!ide.$scope.hasLintingError) + $scope.recompile(isAutoCompileOnChange: true) + else + # Extend remainder of timeout + autoCompileTimeout = setTimeout () -> + autoCompileTimeout = null + triggerAutoCompile() + , AUTO_COMPILE_TIMEOUT - timeSinceLastCompile + + autoCompileListener = null + toggleAutoCompile = (enabling) -> + if enabling + autoCompileListener = ide.$scope.$on "ide:opAcknowledged", _.debounce(triggerAutoCompile, OP_ACKNOWLEDGEMENT_TIMEOUT) + else + autoCompileListener() if autoCompileListener + autoCompileListener = null + + $scope.autocompile_enabled = localStorage("autocompile_enabled:#{$scope.project_id}") or false + $scope.$watch "autocompile_enabled", (newValue, oldValue) -> + if newValue? and oldValue != newValue + localStorage("autocompile_enabled:#{$scope.project_id}", newValue) + toggleAutoCompile(newValue) + event_tracking.sendMB "autocompile-setting-changed", { value: newValue } + + if (window.user?.betaProgram or window.showAutoCompileOnboarding) and $scope.autocompile_enabled + toggleAutoCompile(true) + # abort compile if syntax checks fail $scope.stop_on_validation_error = localStorage("stop_on_validation_error:#{$scope.project_id}") $scope.stop_on_validation_error ?= true # turn on for all users by default @@ -88,7 +127,7 @@ define [ sendCompileRequest = (options = {}) -> url = "/project/#{$scope.project_id}/compile" params = {} - if options.isAutoCompile + 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 @@ -105,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} @@ -128,6 +167,8 @@ define [ $scope.pdf.compileTerminated = false $scope.pdf.compileExited = false $scope.pdf.failedCheck = false + $scope.pdf.compileInProgress = false + $scope.pdf.autoCompileDisabled = false # make a cache to look up files by name fileByPath = {} @@ -166,7 +207,13 @@ define [ $scope.shouldShowLogs = true fetchLogs(fileByPath) else if response.status == "autocompile-backoff" - $scope.pdf.view = 'uncompiled' + if $scope.pdf.isAutoCompileOnLoad # initial autocompile + $scope.pdf.view = 'uncompiled' + else # background autocompile from typing + $scope.pdf.view = 'errors' + $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" $scope.pdf.view = 'errors' $scope.pdf.projectTooLarge = true @@ -184,6 +231,10 @@ 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 else if response.status == "success" $scope.pdf.view = 'pdf' $scope.shouldShowLogs = false @@ -369,9 +420,13 @@ define [ $scope.recompile = (options = {}) -> return if $scope.pdf.compiling + if !options.isAutoCompileOnLoad and $scope.onboarding.autoCompile == 'unseen' + $scope.onboarding.autoCompile = 'show' + event_tracking.sendMBSampled "editor-recompile-sampled", options $scope.pdf.compiling = true + $scope.pdf.isAutoCompileOnLoad = options?.isAutoCompileOnLoad # initial autocompile if options?.force # for forced compile, turn off validation check and ignore errors @@ -401,6 +456,8 @@ define [ $scope.pdf.renderingError = false $scope.pdf.error = true $scope.pdf.view = 'errors' + .finally () -> + $scope.recompiledAt = Date.now() # This needs to be public. ide.$scope.recompile = $scope.recompile 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}) diff --git a/services/web/public/coffee/main/project-list/project-list.coffee b/services/web/public/coffee/main/project-list/project-list.coffee index f994151a3c..8c39df060f 100644 --- a/services/web/public/coffee/main/project-list/project-list.coffee +++ b/services/web/public/coffee/main/project-list/project-list.coffee @@ -26,22 +26,12 @@ define [ storedUIOpts = JSON.parse(localStorage("project_list")) recalculateProjectListHeight = () -> - topOffset = $(".project-list-card")?.offset()?.top - bottomOffset = $("footer").outerHeight() + 25 - sideBarHeight = $("aside").height() - 56 - # When footer is visible and page doesn't need to scroll we just make it - # span between header and footer - height = $window.innerHeight - topOffset - bottomOffset - - # When page is small enough that this pushes the project list smaller than - # the side bar, then the window going to have to scroll to take into account the - # footer. So we now start to track to the bottom of the window, with a 25px padding - # since the footer is hidden below the fold. Don't ever get bigger than the sidebar - # though since that's what triggered this happening in the first place. - if height < sideBarHeight - height = Math.min(sideBarHeight, $window.innerHeight - topOffset - 25) + $projListCard = $(".project-list-card") + topOffset = $projListCard.offset()?.top + cardPadding = $projListCard.outerHeight() - $projListCard.height() + bottomOffset = $("footer").outerHeight() + height = $window.innerHeight - topOffset - bottomOffset - cardPadding $scope.projectListHeight = height - angular.element($window).bind "resize", () -> recalculateProjectListHeight() diff --git a/services/web/public/img/ol-brand/overleaf-white.svg b/services/web/public/img/ol-brand/overleaf-white.svg new file mode 100644 index 0000000000..2ced81aa46 --- /dev/null +++ b/services/web/public/img/ol-brand/overleaf-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/web/public/img/ol-brand/overleaf.svg b/services/web/public/img/ol-brand/overleaf.svg new file mode 100644 index 0000000000..73d2a9b4e0 --- /dev/null +++ b/services/web/public/img/ol-brand/overleaf.svg @@ -0,0 +1 @@ + \ No newline at end of file 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 0000000000..b0b8523dc7 Binary files /dev/null and b/services/web/public/img/ol_plus_sl.png differ 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 0000000000..cc0da8f7a5 Binary files /dev/null and b/services/web/public/img/onboarding/autocompile/setting-dropdown.png differ diff --git a/services/web/public/stylesheets/app/editor/feature-onboarding.less b/services/web/public/stylesheets/app/editor/feature-onboarding.less index 7289ed4fb7..475658f885 100644 --- a/services/web/public/stylesheets/app/editor/feature-onboarding.less +++ b/services/web/public/stylesheets/app/editor/feature-onboarding.less @@ -98,4 +98,48 @@ a.feat-onboard-dismiss { color: #FFF; opacity: 1; } -} \ No newline at end of file +} + +.onboarding-autocompile { + display: block; + top: 10px; + + img { + margin-bottom: 10px; + border: 1px solid @gray-lighter; + } + + &::before, &::after { + content: ''; + border-width: 11px; + border-style: solid; + border-color: transparent; + top: 7px; + display: block; + position: absolute; + } + + &.right::before { + border-left-width: 0; + border-right-color: rgba(0, 0, 0, .3); + left: -11px; + } + + &.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; + } +} diff --git a/services/web/public/stylesheets/app/editor/review-panel.less b/services/web/public/stylesheets/app/editor/review-panel.less index 4e53fa2b97..15ed39f6a7 100644 --- a/services/web/public/stylesheets/app/editor/review-panel.less +++ b/services/web/public/stylesheets/app/editor/review-panel.less @@ -947,6 +947,7 @@ justify-content: center; border-radius: 3px; box-shadow: 0 0 20px 10px rgba(0, 0, 0, .3); + z-index: 1; &::before { content: ''; diff --git a/services/web/public/stylesheets/app/ol-style-guide.less b/services/web/public/stylesheets/app/ol-style-guide.less new file mode 100644 index 0000000000..30e4e5045f --- /dev/null +++ b/services/web/public/stylesheets/app/ol-style-guide.less @@ -0,0 +1,66 @@ +.renderColorSwatchClasses(@colorName) { + @colorVal: @@colorName; + @colorValRed: red(@colorVal); + @colorValGreen: green(@colorVal); + @colorValBlue: blue(@colorVal); + @colorValAsRGB: 'rgb(@{colorValRed}, @{colorValGreen}, @{colorValBlue})'; + + &.@{colorName} { + .color-swatch { + background-color: @colorVal; + } + .color-less-var::before { + content: '@@{colorName}'; + } + .color-hex-val::before { + content: '@{colorVal}'; + } + .color-rgb-val::before { + font-size: 10px; + content: '@{colorValAsRGB}'; + } + } +} + +.color-row { + display: flex; + justify-content: space-between; +} + +.color-box { + background: white; + margin: 10px 4px; + border-radius: 4px; + width: 16.666%; + .renderColorSwatchClasses(ol-blue-gray-1); + .renderColorSwatchClasses(ol-blue-gray-2); + .renderColorSwatchClasses(ol-blue-gray-3); + .renderColorSwatchClasses(ol-blue-gray-4); + .renderColorSwatchClasses(ol-blue-gray-5); + .renderColorSwatchClasses(ol-blue-gray-6); + .renderColorSwatchClasses(ol-green); + .renderColorSwatchClasses(ol-dark-green); + .renderColorSwatchClasses(ol-blue); + .renderColorSwatchClasses(ol-dark-blue); + .renderColorSwatchClasses(ol-red); + .renderColorSwatchClasses(ol-dark-red); +} + +.color-swatch { + height: 100px; + width: 100px; + margin: 10px auto; + border-radius: 4px; +} + +.color-label { + display: flex; + flex-direction: column; + margin: 0 3px 10px; +} + +.color-label pre { + font-size: 12px; + line-height: 1.8em; + margin: 0 auto; +} \ No newline at end of file diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index 13ca60e181..5e7442e1ce 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -18,9 +18,56 @@ } .project-list-page { - position: relative; + position: absolute; + top: @header-height; + bottom: @footer-height; + padding-top: 0; + padding-bottom: 0; + width: 100%; + overflow-x: hidden; + overflow-y: auto; } +.project-list-content when (@is-overleaf) { + .container-fluid; + margin: 0; + height: 100%; +} + +.project-list-content when (@is-overleaf = false) { + .container; +} + +.sidebar-new-proj-btn when (@is-overleaf) { + .btn-block; +} + + .project-list-row when (@is-overleaf) { + height: 100%; + } + .project-list-container when (@is-overleaf) { + height: 100%; + } + .project-list-sidebar { + background-color: @sidebar-bg; + padding-top: @content-margin-vertical; + padding-bottom: @content-margin-vertical; + } + + .project-list-sidebar when (@is-overleaf) { + height: 100%; + overflow-x: hidden; + overflow-y: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + + .project-list-main { + padding-top: @content-margin-vertical; + padding-bottom: @content-margin-vertical; + height: 100%; + overflow: hidden; + } + .project-header { .btn-group > .btn { padding-left: @line-height-base / 2; @@ -48,6 +95,9 @@ } p { margin-bottom: @line-height-computed / 4; + &.small { + color: @sidebar-color; + } } } @@ -76,27 +126,38 @@ } ul.folders-menu { - margin: 0; + margin: @folders-menu-margin; .subdued { color: @gray-light; } > li { cursor: pointer; - line-height: 1.8; position: relative; > a { + display: block; + color: @sidebar-link-color; + padding: @folders-menu-item-v-padding @folders-menu-item-h-padding; + border-bottom: solid 1px transparent; + &:hover { + background-color: @sidebar-hover-bg; + text-decoration: @sidebar-hover-text-decoration; + } + &:focus { + text-decoration: none; + } + } + > a when (@is-overleaf = false) { font-size: 0.9rem; - color: #333; - padding: (@line-height-computed / 4); - display: inline-block; - line-height: 1.2; + } + &.separator { + padding: @folders-menu-item-v-padding @folders-menu-item-h-padding; + cursor: auto; } } > li.active { - //border-right: 4px solid @red; - background-color: @link-color; - border-radius: @border-radius-small; + border-radius: @sidebar-active-border-radius; > a { + background-color: @sidebar-active-bg; font-weight: 700; color: white; .subdued { @@ -108,10 +169,13 @@ ul.folders-menu { color: @gray; } h2 { - margin-top: @line-height-computed / 2; - margin-bottom: @line-height-computed / 4; - font-size: @font-size-base; - font-weight: 500; + margin-top: @folders-title-margin-top; + margin-bottom: @folders-title-margin-bottom; + font-size: @folders-title-font-size; + color: @folders-title-color; + text-transform: @folders-title-text-transform; + padding: @folders-title-padding; + font-weight: @folders-title-font-weight; font-family: @font-family-sans-serif; } > li.tag { @@ -120,7 +184,7 @@ ul.folders-menu { color: white; border-color: white; &:hover { - background-color: darken(@brand-primary, 10%); + background-color: @folders-tag-menu-active-hover; } } } @@ -128,7 +192,7 @@ ul.folders-menu { font-style: italic; margin-bottom: @line-height-computed / 4; a { - line-height: 1.7; + line-height: @folders-untagged-line-height; &:hover, &:focus { text-decoration: none; @@ -140,7 +204,7 @@ ul.folders-menu { } &:hover { &:not(.active) { - background-color: darken(@gray-lightest, 2%); + background-color: @folders-tag-hover; } .tag-menu { display: block @@ -148,30 +212,23 @@ ul.folders-menu { } &:not(.active) { .tag-menu > a:hover { - background-color: @gray-light; + background-color: @folders-tag-menu-hover; } } a.tag-name { - padding: 2px (@line-height-computed / 4); - margin-right: 18px; - display: inline-block; + padding: @folders-tag-padding; + display: @folders-tag-display; position: relative; - i { - position: absolute; - top: 5px; - left: 6px; - } span.name { - display: inline-block; - padding-left: 22px; - line-height: 1.4; + padding-left: 0.5em; + line-height: @folders-tag-line-height; } } .tag-menu { > a { - border: 1px solid @gray; + border: 1px solid @folders-tag-border-color; border-radius: @border-radius-small; - color: @text-color; + color: @folders-tag-menu-color; display: block; width: 16px; height: 16px; @@ -184,7 +241,8 @@ ul.folders-menu { } display: none; position: absolute; - top: 6px; + top: 50%; + margin-top: -8px; // Half the element height. right: 4px; &.open { display: block; @@ -204,32 +262,34 @@ ul.structured-list { margin: 0; overflow: hidden; overflow-y: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; li { - border-bottom: 1px solid @gray-lightest; + border-bottom: 1px solid @structured-list-border-color; padding: (@line-height-computed / 4) 0; - &:first-child { - .header { - font-size: 1rem; - } - } + &:last-child { border-bottom: 0 none; } &:hover { - background-color: @gray-lightest; + background-color: @structured-list-hover-color; } - &:first-child:hover { - background-color: white; + &:first-child { + border-bottom-color: @structured-header-border-color; + &:hover { + background-color: transparent; + } } a { - color: darken(@blue, 10%); + color: @structured-list-link-color; } - .header { + .header when (@is-overleaf = true) { + font-weight: 600; + } + + .header when (@is-overleaf = false) { text-transform: uppercase; } - .select-item, .select-all { - display: inline-block; - } + .select-item, .select-all { position: absolute; left: @line-height-computed; @@ -245,17 +305,25 @@ ul.structured-list { } } +.project-list-card when (@is-overleaf) { + padding: 0 (@line-height-computed / 4); +} + ul.project-list { li { - .last-modified, .owner { + .last-modified when (@is-overleaf = false) { font-size: .8rem; } - .owner { + .owner when (@is-overleaf = false) { + font-size: .8rem; + } + .owner when (@is-overleaf = false) { margin-right: 0; } .projectName { margin-right: @line-height-computed / 4; } + .tag-label { margin-left: @line-height-computed / 4; position: relative; @@ -267,6 +335,12 @@ ul.project-list { display: inline-block; padding-top: 0.3em; color: #FFF; + border-radius: @tag-border-radius; + background-color: @tag-bg-color; + &:hover, + &:focus { + background-color: @tag-bg-hover-color; + } } .tag-label-name { padding-right: 0.3em; @@ -347,7 +421,7 @@ ul.project-list { .announcements { position: absolute; - bottom: 0; + bottom: @footer-height; right: 0; height: 150px; width: 100%; @@ -429,7 +503,7 @@ ul.project-list { margin-right: 95px; bottom: 30px; width: 700px; - max-height: 52%; + max-height: 40%; min-height: 100px; background: #FFF; z-index: 1; diff --git a/services/web/public/stylesheets/components/buttons.less b/services/web/public/stylesheets/components/buttons.less index 6e77fd2b7f..57a29c5353 100755 --- a/services/web/public/stylesheets/components/buttons.less +++ b/services/web/public/stylesheets/components/buttons.less @@ -14,10 +14,10 @@ vertical-align: middle; cursor: pointer; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - border-bottom: 2px solid transparent; + border: @btn-border-width solid transparent; + border-bottom: @btn-border-bottom-width solid transparent; white-space: nowrap; - .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); + .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base); .user-select(none); &, @@ -124,14 +124,14 @@ .btn-lg { // line-height: ensure even-numbered height of button next to large input - .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); + .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large); } .btn-sm { // line-height: ensure proper height of button next to small input - .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); + .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); } .btn-xs { - .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); + .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); } diff --git a/services/web/public/stylesheets/components/card.less b/services/web/public/stylesheets/components/card.less index 2619686b0a..1e06fbe3b4 100644 --- a/services/web/public/stylesheets/components/card.less +++ b/services/web/public/stylesheets/components/card.less @@ -1,8 +1,8 @@ .card { background-color: white; border-radius: @border-radius-base; - -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.1); - box-shadow: 0 2px 4px rgba(0,0,0,0.15); + -webkit-box-shadow: @card-box-shadow; + box-shadow: @card-box-shadow; padding: @line-height-computed; .page-header { margin: 0 0 1.5625rem; diff --git a/services/web/public/stylesheets/components/footer.less b/services/web/public/stylesheets/components/footer.less index e4e4f82da1..5b68fd7dde 100644 --- a/services/web/public/stylesheets/components/footer.less +++ b/services/web/public/stylesheets/components/footer.less @@ -1,7 +1,13 @@ footer.site-footer { + background-color: @footer-bg-color; border-top: 1px solid @gray-lighter; - padding: 2em; font-size: 0.9rem; + position: absolute; + bottom: 0; + width: 100%; + height: @footer-height; + line-height: @footer-height - 1; // Hack — in Chrome, using the full @footer-height would generate vertical scrolling + ul { list-style: none; margin: 0px; @@ -22,6 +28,21 @@ footer.site-footer { vertical-align: text-bottom; } } + + a { + color: @footer-link-color; + &:hover, + &:focus { + color: @footer-link-hover-color; + } + } +} + +.site-footer-content when (@is-overleaf = true) { + .container-fluid; +} +.site-footer-content when (@is-overleaf = false) { + .container; } .sprite-icon-lang { diff --git a/services/web/public/stylesheets/components/navbar.less b/services/web/public/stylesheets/components/navbar.less index 52a4a10029..47d76cc1f2 100755 --- a/services/web/public/stylesheets/components/navbar.less +++ b/services/web/public/stylesheets/components/navbar.less @@ -174,9 +174,9 @@ font-size: 20px; display: inline-block; margin-top: 2px; - color: #666; + color: @navbar-title-color; &:hover, &:active, &:focus { - color: #333; + color: @navbar-title-color-hover; text-decoration: none; } } @@ -378,13 +378,17 @@ .navbar-default { background-color: @navbar-default-bg; border-color: @navbar-default-border; - padding: 1rem 2rem; - + padding: @navbar-default-padding; + position: absolute; + top: 0; + width: 100%; + height: @header-height; + .navbar-brand { position: absolute; top: 5px; bottom: 5px; - width: 180px; + width: @navbar-brand-width; padding: 0; background-image: @navbar-brand-image-url; background-size: contain; @@ -400,11 +404,11 @@ > li > a { color: @navbar-default-link-color; border: 2px solid transparent; - border-radius: @border-radius-base; - font-size: @font-size-base * .8; - font-weight: 700; - line-height: 1; - padding: 10px 10px 11px; + border-radius: @navbar-btn-border-radius; + font-size: @navbar-btn-font-size; + font-weight: @navbar-btn-font-weight; + line-height: @navbar-btn-line-height; + padding: @navbar-btn-padding; &:hover, &:focus { @@ -432,15 +436,15 @@ > li.subdued > a { border: 0; - color: @gray; - padding: 12px 12px 13px; + color: @navbar-subdued-color; + padding: @navbar-subdued-padding; margin-left: 0; &:hover { - color: @gray-dark; - background-color: @gray-lightest; + color: @navbar-subdued-hover-color; + background-color: @navbar-subdued-hover-bg; } &:focus { - color: @gray; + color: @navbar-subdued-color; background-color: transparent; } } @@ -485,8 +489,8 @@ &, &:hover, &:focus { - color: @gray-dark; - background-color: @gray-lightest; + color: @navbar-subdued-hover-color; + background-color: @navbar-subdued-hover-bg; } } diff --git a/services/web/public/stylesheets/components/progress-bars.less b/services/web/public/stylesheets/components/progress-bars.less index 062ec48df2..df841437c3 100755 --- a/services/web/public/stylesheets/components/progress-bars.less +++ b/services/web/public/stylesheets/components/progress-bars.less @@ -29,8 +29,8 @@ height: @line-height-computed; margin-bottom: @line-height-computed; background-color: @progress-bg; - border-radius: @border-radius-base; - border: 1px solid @progress-border-color; + border-radius: @progress-border-radius; + border: @progress-border-width solid @progress-border-color; .box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); } @@ -44,7 +44,7 @@ color: @progress-bar-color; text-align: center; background-color: @progress-bar-bg; - .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); + .box-shadow(@progress-bar-shadow); .transition(width .6s ease); } diff --git a/services/web/public/stylesheets/core/_common-variables.less b/services/web/public/stylesheets/core/_common-variables.less index 6274b265f9..3d3cc383a8 100644 --- a/services/web/public/stylesheets/core/_common-variables.less +++ b/services/web/public/stylesheets/core/_common-variables.less @@ -85,7 +85,6 @@ @border-radius-base: 3px; @border-radius-large: 5px; @border-radius-small: 2px; - //** Global color for active items (e.g., navs or dropdowns). @component-active-color: #fff; //** Global background color for active items (e.g., navs or dropdowns). @@ -789,10 +788,7 @@ //** Horizontal offset for forms and lists. @component-offset-horizontal: 180px; -@content-margin-top: @line-height-computed; -@content-margin-top: @line-height-computed; - -// Custom +@content-margin-vertical: @line-height-computed; @left-menu-width: 260px; @left-menu-animation-duration: 0.35s; @@ -803,3 +799,94 @@ @editor-dark-background-color: #333; @editor-dark-toolbar-border-color: #222; @editor-dark-highlight-color: #FFA03A; + + +// Custom +@is-overleaf : false; +@header-height : 68px; +@footer-height : 50px; + +// Backgrounds +@content-alt-bg-color: lighten(@gray-lightest, 2.5%); + +// Typography +@text-small-color: @gray; + +// Navbar +@navbar-title-color : #666; +@navbar-title-color-hover : #333; +@navbar-default-padding : 1rem 2rem; +@navbar-brand-width : 180px; +@navbar-btn-font-size : @font-size-base * 0.8; +@navbar-btn-border-radius : @border-radius-base; +@navbar-btn-font-weight : 700; +@navbar-btn-padding : 10px 10px 11px; +@navbar-btn-line-height : 1; +@navbar-subdued-padding : 12px 12px 13px; +@navbar-subdued-color : @gray; +@navbar-subdued-hover-bg : @gray-lightest; +@navbar-subdued-hover-color : @gray-dark; + +// Button colors and sizing +@btn-border-radius-large : @border-radius-large; +@btn-border-radius-base : @border-radius-base; +@btn-border-radius-small : @border-radius-small; +@btn-border-width : 1px; +@btn-border-bottom-width : 2px; + +// Cards +@card-box-shadow: 0 2px 4px rgba(0,0,0,0.15); + +// Project table +@structured-list-link-color : darken(@blue, 10%); +@structured-header-border-color : @gray-lightest; +@structured-list-border-color : @gray-lightest; +@structured-list-hover-color : @gray-lightest; +@structured-list-line-height : @line-height-base; + +// Sidebar +@sidebar-bg : transparent; +@sidebar-color : @gray; +@sidebar-link-color : #333; +@sidebar-active-border-radius : @border-radius-small; +@sidebar-active-bg : @link-color; +@sidebar-hover-bg : transparent; +@sidebar-hover-text-decoration : underline; + +@folders-menu-margin : 0; +@folders-menu-line-height : 1.2; +@folders-menu-item-v-padding : (@line-height-computed / 4); +@folders-menu-item-h-padding : (@line-height-computed / 4); +@folders-title-padding : 0; +@folders-title-margin-top : (@line-height-computed / 2); +@folders-title-margin-bottom : (@line-height-computed / 4); +@folders-title-font-size : @font-size-base; +@folders-title-font-weight : 500; +@folders-title-line-height : @headings-line-height; +@folders-title-color : inherit; +@folders-title-text-transform : none; +@folders-tag-padding : 2px 20px 2px @folders-menu-item-h-padding; +@folders-tag-line-height : 1.8; +@folders-tag-display : block; +@folders-tag-menu-color : @gray; +@folders-tag-hover : darken(@gray-lightest, 2%); +@folders-tag-border-color : @text-color; +@folders-tag-menu-active-hover : darken(@brand-primary, 10%); +@folders-tag-menu-hover : @gray-light; +@folders-untagged-line-height : 1.7; + +// Progress bars +@progress-border-radius : @border-radius-base; +@progress-border-width : 1px; +@progress-bar-shadow : inset 0 -1px 0 rgba(0,0,0,.15); + +// Footer +@footer-link-color : @link-color; +@footer-link-hover-color : @link-hover-color; +@footer-bg-color : transparent; +@footer-padding : 2em; + +// Tags +@tag-border-radius : 0.25em; +@tag-bg-color : @label-default-bg; +@tag-bg-hover-color : darken(@label-default-bg, 10%); \ No newline at end of file diff --git a/services/web/public/stylesheets/core/ol-variables.less b/services/web/public/stylesheets/core/ol-variables.less index 23151bd9c4..43646ec542 100644 --- a/services/web/public/stylesheets/core/ol-variables.less +++ b/services/web/public/stylesheets/core/ol-variables.less @@ -1,11 +1,164 @@ -@ol-green: #4A9F48; -@ol-dark-green: #1C5B26; +@import "./_common-variables.less"; + +@is-overleaf: true; +@header-height: 68px; +@footer-height: 50px; + +// Styleguide colors +@ol-blue-gray-1 : #E4E8EE; +@ol-blue-gray-2 : #9DA7B7; +@ol-blue-gray-3 : #5D6879; +@ol-blue-gray-4 : #485973; +@ol-blue-gray-5 : #2C3645; +@ol-blue-gray-6 : #1E2530; + +@ol-green : #4F9C45; +@ol-dark-green : #1C5B26; +@ol-blue : #4B7FD1; +@ol-dark-blue : #2857A1; +@ol-red : #C9453E; +@ol-dark-red : #A6312B; + +@ol-type-color : @ol-blue-gray-3; + +// Navbar customization +@navbar-title-color : @ol-blue-gray-1; +@navbar-title-color-hover : @ol-blue-gray-2; +@navbar-brand-width : 130px; +@navbar-default-color : #FFF; +@navbar-default-bg : @ol-blue-gray-6; +@navbar-default-border : transparent; +@navbar-brand-image-url : url(/img/ol-brand/overleaf-white.svg); + +// Backgrounds +@body-bg : #FFF; +@content-alt-bg-color : @ol-blue-gray-1; + +// Typography +@text-small-color : @ol-type-color; +@text-color : @ol-type-color; +@link-color : @ol-blue; +@link-hover-color : @ol-dark-blue; + +// Button colors and sizing +@btn-border-width : 0; +@btn-border-bottom-width : 0; + +@btn-border-radius-large : 9999px; +@btn-border-radius-base : 9999px; +@btn-border-radius-small : 9999px; + +@btn-default-color : #FFF; +@btn-default-bg : @ol-blue-gray-4; +@btn-default-border : transparent; + +@btn-primary-color : #FFF; +@btn-primary-bg : @ol-green; +@btn-primary-border : transparent; + +@btn-success-color : #FFF; +@btn-success-bg : @ol-green; +@btn-success-border : transparent; + +@btn-info-color : #FFF; +@btn-info-bg : @ol-blue; +@btn-info-border : transparent; + +// Tags +@tag-border-radius : 9999px; +@tag-bg-color : @ol-green; +@tag-bg-hover-color : @ol-dark-green; + +// Navbar +@navbar-default-padding : (@grid-gutter-width / 2) 0; +@navbar-default-link-color : #FFF; +@navbar-default-link-hover-bg : @ol-green; +@navbar-default-link-active-bg : @ol-green; +@navbar-default-link-hover-color : @ol-green; +@navbar-btn-font-size : @font-size-base; +@navbar-btn-border-radius : @btn-border-radius-base; +@navbar-btn-font-weight : 400; +@navbar-btn-padding : (@padding-base-vertical - 1) @padding-base-horizontal @padding-base-vertical; +@navbar-btn-line-height : @line-height-base; + +@navbar-subdued-color : #FFF; +@navbar-subdued-padding : (@padding-base-vertical + 1) (@padding-base-horizontal + 1) (@padding-base-vertical + 2); +@navbar-subdued-hover-bg : #FFF; +@navbar-subdued-hover-color : @ol-green; + +// Forms +@input-color : @ol-blue-gray-3; +@input-border-radius : unit(@line-height-base, em); +@input-height-base : @line-height-computed + (@padding-base-vertical * 2) - 1; +// TODO Warning color-orange? +@btn-warning-color : #FFF; +@btn-warning-bg : @ol-red; +@btn-warning-border : transparent; + +@btn-danger-color : #FFF; +@btn-danger-bg : @ol-red; +@btn-danger-border : transparent; + +// Cards +@card-box-shadow : none; + +// Sidebar +@sidebar-bg : @ol-blue-gray-5; +@sidebar-color : @ol-blue-gray-2; +@sidebar-link-color : #FFF; +@sidebar-active-border-radius : 0; +@sidebar-active-bg : @ol-blue-gray-6; +@sidebar-hover-bg : @ol-blue-gray-4; +@sidebar-hover-text-decoration : none; + +@folders-menu-margin : 0 -(@grid-gutter-width / 2); +@folders-menu-line-height : @structured-list-line-height; +@folders-menu-item-v-padding : (@line-height-computed / 4); +@folders-menu-item-h-padding : (@grid-gutter-width / 2); +@folders-title-padding : @folders-menu-item-v-padding 0; +@folders-title-margin-top : 0; +@folders-title-margin-bottom : 0; +@folders-title-font-weight : normal; +@folders-title-font-size : @font-size-small; +@folders-title-color : @ol-blue-gray-2; +@folders-title-text-transform : uppercase; +@folders-tag-display : block; +@folders-tag-line-height : 1.4; +@folders-tag-padding : @folders-menu-item-v-padding 20px @folders-menu-item-v-padding @folders-menu-item-h-padding; +@folders-tag-menu-color : #FFF; +@folders-tag-hover : @sidebar-hover-bg; +@folders-tag-border-color : @folders-tag-menu-color; +@folders-tag-menu-hover : rgba(0, 0, 0, .1); +@folders-tag-menu-active-hover : rgba(0, 0, 0, .1); +@folders-untagged-line-height : @folders-menu-line-height; + +// Project table +@structured-list-line-height : 2.5; +@structured-list-link-color : @ol-blue; +@structured-header-border-color : shade(@ol-blue-gray-1, 5%); +@structured-list-border-color : @ol-blue-gray-1; +@structured-list-hover-color : lighten(@ol-blue-gray-1, 5%); + + +// Progress bars +@progress-border-radius : @line-height-computed; +@progress-border-width : 0; +@progress-bar-bg : @ol-blue-gray-4; +@progress-bar-success-bg : @ol-green; +@progress-bar-warning-bg : @brand-warning; +@progress-bar-danger-bg : @ol-red; +@progress-bar-info-bg : @ol-blue; +@progress-bar-shadow : none; + +// Footer +@footer-bg-color : #FFF; +@footer-link-color : @ol-green; +@footer-link-hover-color : @ol-dark-green; +@footer-padding : 2em 0; //== Colors // //## Gray and brand colors for use across Bootstrap. - - @gray-darker: #252525; @gray-dark: #505050; @gray: #7a7a7a; @@ -28,10 +181,6 @@ @brand-warning: @orange; @brand-danger: #E03A06; -@navbar-brand-image-url: url(/img/ol-brand/logo-horizontal.png); - @editor-loading-logo-padding-top: 115.44%; @editor-loading-logo-background-url: url(/img/ol-brand/overleaf-o-grey.svg); -@editor-loading-logo-foreground-url: url(/img/ol-brand/overleaf-o.svg); - -@import "./_common-variables.less"; +@editor-loading-logo-foreground-url: url(/img/ol-brand/overleaf-o.svg); \ No newline at end of file diff --git a/services/web/public/stylesheets/core/scaffolding.less b/services/web/public/stylesheets/core/scaffolding.less index b6dc68363d..22d7225b95 100755 --- a/services/web/public/stylesheets/core/scaffolding.less +++ b/services/web/public/stylesheets/core/scaffolding.less @@ -21,6 +21,7 @@ html { //font-size: 62.5%; -webkit-tap-highlight-color: rgba(0,0,0,0); + height: 100%; } body { @@ -29,6 +30,13 @@ body { line-height: @line-height-base; color: @text-color; background-color: @body-bg; + min-height: 100%; + position: relative; + padding-top: @header-height; + padding-bottom: @footer-height; + & > .content { + min-height: calc(~"100vh -" (@header-height + @footer-height)); + } } // Reset fonts for relevant elements @@ -137,12 +145,12 @@ hr { } .content { - padding-top: @content-margin-top; - padding-bottom: @content-margin-top; + padding-top: @content-margin-vertical; + padding-bottom: @content-margin-vertical; } .content-alt { - background-color: lighten(@gray-lightest, 2.5%); + background-color: @content-alt-bg-color; } .row-spaced { diff --git a/services/web/public/stylesheets/core/type.less b/services/web/public/stylesheets/core/type.less index 56c7d236ea..ac1dcf3765 100755 --- a/services/web/public/stylesheets/core/type.less +++ b/services/web/public/stylesheets/core/type.less @@ -81,7 +81,7 @@ p { // Ex: 14px base font * 85% = about 12px small, -.small { font-size: 90%; color: @gray } +.small { font-size: 90%; color: @text-small-color; } // Undo browser default styling cite { font-style: normal; } diff --git a/services/web/public/stylesheets/ol-style.less b/services/web/public/stylesheets/ol-style.less index ec53e5e8c8..1e48b7284d 100644 --- a/services/web/public/stylesheets/ol-style.less +++ b/services/web/public/stylesheets/ol-style.less @@ -1,3 +1,4 @@ // Core variables and mixins @import "core/ol-variables.less"; +@import "app/ol-style-guide.less"; @import "_style_includes.less"; \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee index 055c55074f..349712c007 100644 --- a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee @@ -431,3 +431,103 @@ describe "CollaboratorsHandler", -> expect(err).to.not.exist expect(isTokenMember).to.equal false done() + + 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 diff --git a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee index 32deed5522..bd02af2f28 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) @@ -247,12 +262,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 @@ -331,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) => 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() 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", -> 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/History/HistoryControllerTests.coffee b/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee index 577aae6a9d..ae10a34739 100644 --- a/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/History/HistoryControllerTests.coffee @@ -6,6 +6,7 @@ SandboxedModule = require('sandboxed-module') describe "HistoryController", -> beforeEach -> + @callback = sinon.stub() @user_id = "user-id-123" @AuthenticationController = getLoggedInUserId: sinon.stub().returns(@user_id) @@ -14,46 +15,134 @@ describe "HistoryController", -> "settings-sharelatex": @settings = {} "logger-sharelatex": @logger = {log: sinon.stub(), error: sinon.stub()} "../Authentication/AuthenticationController": @AuthenticationController + @settings.apis = + trackchanges: + enabled: false + url: "http://trackchanges.example.com" + project_history: + url: "http://project_history.example.com" describe "proxyToHistoryApi", -> beforeEach -> @req = { url: "/mock/url", method: "POST" } @res = "mock-res" @next = sinon.stub() - @settings.apis = - trackchanges: - url: "http://trackchanges.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", -> @next.calledWith(@error).should.equal true + + describe "initializeProject", -> + describe "with project history enabled", -> + beforeEach -> + @settings.apis.project_history.enabled = true + + describe "project history returns a successful response", -> + beforeEach -> + @overleaf_id = 1234 + @res = statusCode: 200 + @body = JSON.stringify(project: id: @overleaf_id) + @request.post = sinon.stub().callsArgWith(1, null, @res, @body) + + @HistoryController.initializeProject @callback + + it "should call the project history api", -> + @request.post.calledWith( + url: "#{@settings.apis.project_history.url}/project" + ).should.equal true + + it "should return the callback with the overleaf id", -> + @callback.calledWithExactly(null, { @overleaf_id }).should.equal true + + describe "project history returns a response without the project id", -> + beforeEach -> + @res = statusCode: 200 + @body = JSON.stringify(project: {}) + @request.post = sinon.stub().callsArgWith(1, null, @res, @body) + + @HistoryController.initializeProject @callback + + it "should return the callback with an error", -> + @callback + .calledWith(sinon.match.has("message", "project-history did not provide an id")) + .should.equal true + + describe "project history returns a unsuccessful response", -> + beforeEach -> + @res = statusCode: 404 + @request.post = sinon.stub().callsArgWith(1, null, @res) + + @HistoryController.initializeProject @callback + + it "should return the callback with an error", -> + @callback + .calledWith(sinon.match.has("message", "project-history returned a non-success status code: 404")) + .should.equal true + + describe "project history errors", -> + beforeEach -> + @error = sinon.stub() + @request.post = sinon.stub().callsArgWith(1, @error) + + @HistoryController.initializeProject @callback + + it "should return the callback with the error", -> + @callback.calledWithExactly(@error).should.equal true + + describe "with project history disabled", -> + beforeEach -> + @settings.apis.project_history.enabled = false + @HistoryController.initializeProject @callback + + it "should return the callback", -> + @callback.calledWithExactly().should.equal true 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 diff --git a/services/web/test/UnitTests/coffee/Project/ProjectCreationHandlerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectCreationHandlerTests.coffee index 8aa750b80a..5c32db63d3 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectCreationHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectCreationHandlerTests.coffee @@ -22,6 +22,8 @@ describe 'ProjectCreationHandler', -> @._id = project_id @owner_ref = options.owner_ref @name = options.name + @overleaf = + history: {} save: sinon.stub().callsArg(0) rootFolder:[{ _id: rootFolderId @@ -36,11 +38,13 @@ describe 'ProjectCreationHandler', -> setRootDoc: sinon.stub().callsArg(2) @ProjectDetailsHandler = validateProjectName: sinon.stub().yields() + @HistoryController = + initializeProject: sinon.stub().callsArg(0) - @user = + @user = first_name:"first name here" last_name:"last name here" - ace: + ace: spellCheckLanguage:"de" @User = findById:sinon.stub().callsArgWith(2, null, @user) @@ -49,6 +53,7 @@ describe 'ProjectCreationHandler', -> '../../models/User': User:@User '../../models/Project':{Project:@ProjectModel} '../../models/Folder':{Folder:@FolderModel} + '../History/HistoryController': @HistoryController './ProjectEntityHandler':@ProjectEntityHandler "./ProjectDetailsHandler":@ProjectDetailsHandler "settings-sharelatex": @Settings = {} @@ -60,32 +65,48 @@ describe 'ProjectCreationHandler', -> describe 'Creating a Blank project', -> beforeEach -> + @overleaf_id = 1234 + @HistoryController.initializeProject = sinon.stub().callsArgWith(0, null, { @overleaf_id }) @ProjectModel::save = sinon.stub().callsArg(0) describe "successfully", -> - it "should save the project", (done)-> @handler.createBlankProject ownerId, projectName, => @ProjectModel::save.called.should.equal true done() - + it "should return the project in the callback", (done)-> @handler.createBlankProject ownerId, projectName, (err, project)-> project.name.should.equal projectName (project.owner_ref + "").should.equal ownerId done() + it "should initialize the project overleaf if history id not provided", (done)-> + @handler.createBlankProject ownerId, projectName, done + @HistoryController.initializeProject.calledWith().should.equal true + + it "should set the overleaf id if overleaf id not provided", (done)-> + @handler.createBlankProject ownerId, projectName, (err, project)=> + project.overleaf.history.id.should.equal @overleaf_id + done() + + it "should set the overleaf id if overleaf id provided", (done)-> + overleaf_id = 2345 + @handler.createBlankProject ownerId, projectName, overleaf_id, (err, project)-> + project.overleaf.history.id.should.equal overleaf_id + done() + it "should set the language from the user", (done)-> @handler.createBlankProject ownerId, projectName, (err, project)-> project.spellCheckLanguage.should.equal "de" done() - + it "should set the imageName to currentImageName if set", (done) -> @Settings.currentImageName = "mock-image-name" @handler.createBlankProject ownerId, projectName, (err, project)=> project.imageName.should.equal @Settings.currentImageName done() - + it "should not set the imageName if no currentImageName", (done) -> @Settings.currentImageName = null @handler.createBlankProject ownerId, projectName, (err, project)=> @@ -96,21 +117,21 @@ describe 'ProjectCreationHandler', -> beforeEach -> @ProjectModel::save = sinon.stub().callsArgWith(0, new Error("something went wrong")) @handler.createBlankProject ownerId, projectName, @callback - + it 'should return the error to the callback', -> should.exist @callback.args[0][0] - + describe "with an invalid name", -> beforeEach -> @ProjectDetailsHandler.validateProjectName = sinon.stub().yields(new Error("bad name")) @handler.createBlankProject ownerId, projectName, @callback - + it 'should return the error to the callback', -> should.exist @callback.args[0][0] - + it 'should not try to create the project', -> @ProjectModel::save.called.should.equal false - + describe 'Creating a basic project', -> beforeEach -> diff --git a/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectDetailsHandlerTests.coffee index 481a58c466..6a75888411 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 = @@ -43,7 +43,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 @@ -51,6 +51,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") @@ -80,7 +87,7 @@ describe 'ProjectDetailsHandler', -> @handler.getProjectDescription @project_id, (returnedErr, returnedDescription)=> err.should.equal returnedErr description.should.equal returnedDescription - done() + done() describe "setProjectDescription", -> @@ -111,7 +118,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, => @@ -120,6 +127,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 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() 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 -> 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 = diff --git a/services/web/test/acceptance/coffee/AuthorizationTests.coffee b/services/web/test/acceptance/coffee/AuthorizationTests.coffee index 7b4824a3da..0814e74b8e 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..aefcd4513a --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee @@ -0,0 +1,15 @@ +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? + .on "error", (error) -> + console.error "error starting MockDocUpdaterApi:", error.message + process.exit(1) + +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..2133d40b9f --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee @@ -0,0 +1,33 @@ +express = require("express") +bodyParser = require "body-parser" +app = express() + +module.exports = MockDocStoreApi = + 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? + .on "error", (error) -> + console.error "error starting MockDocStoreApi:", error.message + process.exit(1) + + +MockDocStoreApi.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