From 7d29ae44ba7ce0a4c0ee90bdb087a04771df979e Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Wed, 14 Nov 2018 10:40:27 +0100 Subject: [PATCH 01/79] move the update username route to v3 (#10836) --- .../auth/PUT-user_update_username.test.js | 140 +++++++++-- .../auth/PUT-user_update_username.test.js | 224 ------------------ website/server/controllers/api-v3/auth.js | 49 ++-- website/server/controllers/api-v4/auth.js | 75 ------ website/server/middlewares/appRoutes.js | 1 - 5 files changed, 157 insertions(+), 332 deletions(-) delete mode 100644 test/api/v4/user/auth/PUT-user_update_username.test.js diff --git a/test/api/v3/integration/user/auth/PUT-user_update_username.test.js b/test/api/v3/integration/user/auth/PUT-user_update_username.test.js index 7fd8df6192..987f7bd556 100644 --- a/test/api/v3/integration/user/auth/PUT-user_update_username.test.js +++ b/test/api/v3/integration/user/auth/PUT-user_update_username.test.js @@ -12,14 +12,14 @@ const ENDPOINT = '/user/auth/update-username'; describe('PUT /user/auth/update-username', async () => { let user; - let newUsername = 'new-username'; - let password = 'password'; // from habitrpg/test/helpers/api-integration/v3/object-generators.js + let password = 'password'; // from habitrpg/test/helpers/api-integration/v4/object-generators.js beforeEach(async () => { user = await generateUser(); }); - it('successfully changes username', async () => { + it('successfully changes username with password', async () => { + let newUsername = 'new-username'; let response = await user.put(ENDPOINT, { username: newUsername, password, @@ -29,6 +29,38 @@ describe('PUT /user/auth/update-username', async () => { expect(user.auth.local.username).to.eql(newUsername); }); + it('successfully changes username without password', async () => { + let newUsername = 'new-username-nopw'; + let response = await user.put(ENDPOINT, { + username: newUsername, + }); + expect(response).to.eql({ username: newUsername }); + await user.sync(); + expect(user.auth.local.username).to.eql(newUsername); + }); + + it('successfully changes username containing number and underscore', async () => { + let newUsername = 'new_username9'; + let response = await user.put(ENDPOINT, { + username: newUsername, + }); + expect(response).to.eql({ username: newUsername }); + await user.sync(); + expect(user.auth.local.username).to.eql(newUsername); + }); + + it('sets verifiedUsername when changing username', async () => { + user.flags.verifiedUsername = false; + await user.sync(); + let newUsername = 'new-username-verify'; + let response = await user.put(ENDPOINT, { + username: newUsername, + }); + expect(response).to.eql({ username: newUsername }); + await user.sync(); + expect(user.flags.verifiedUsername).to.eql(true); + }); + it('converts user with SHA1 encrypted password to bcrypt encryption', async () => { let myNewUsername = 'my-new-username'; let textPassword = 'mySecretPassword'; @@ -80,6 +112,7 @@ describe('PUT /user/auth/update-username', async () => { }); it('errors if password is wrong', async () => { + let newUsername = 'new-username'; await expect(user.put(ENDPOINT, { username: newUsername, password: 'wrong-password', @@ -90,19 +123,6 @@ describe('PUT /user/auth/update-username', async () => { }); }); - it('prevents social-only user from changing username', async () => { - let socialUser = await generateUser({ 'auth.local': { ok: true } }); - - await expect(socialUser.put(ENDPOINT, { - username: newUsername, - password, - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('userHasNoLocalRegistration'), - }); - }); - it('errors if new username is not provided', async () => { await expect(user.put(ENDPOINT, { password, @@ -112,5 +132,93 @@ describe('PUT /user/auth/update-username', async () => { message: t('invalidReqParams'), }); }); + + it('errors if new username is a slur', async () => { + await expect(user.put(ENDPOINT, { + username: 'TESTPLACEHOLDERSLURWORDHERE', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), + }); + }); + + it('errors if new username contains a slur', async () => { + await expect(user.put(ENDPOINT, { + username: 'TESTPLACEHOLDERSLURWORDHERE_otherword', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), + }); + await expect(user.put(ENDPOINT, { + username: 'something_TESTPLACEHOLDERSLURWORDHERE', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), + }); + await expect(user.put(ENDPOINT, { + username: 'somethingTESTPLACEHOLDERSLURWORDHEREotherword', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), + }); + }); + + it('errors if new username is not allowed', async () => { + await expect(user.put(ENDPOINT, { + username: 'support', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueForbidden'), + }); + }); + + it('errors if new username is not allowed regardless of casing', async () => { + await expect(user.put(ENDPOINT, { + username: 'SUppORT', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueForbidden'), + }); + }); + + it('errors if username has incorrect length', async () => { + await expect(user.put(ENDPOINT, { + username: 'thisisaverylongusernameover20characters', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueLength'), + }); + }); + + it('errors if new username contains invalid characters', async () => { + await expect(user.put(ENDPOINT, { + username: 'Eichhörnchen', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueInvalidCharacters'), + }); + await expect(user.put(ENDPOINT, { + username: 'test.name', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueInvalidCharacters'), + }); + await expect(user.put(ENDPOINT, { + username: '🤬', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('usernameIssueInvalidCharacters'), + }); + }); }); }); diff --git a/test/api/v4/user/auth/PUT-user_update_username.test.js b/test/api/v4/user/auth/PUT-user_update_username.test.js deleted file mode 100644 index 26a622cf04..0000000000 --- a/test/api/v4/user/auth/PUT-user_update_username.test.js +++ /dev/null @@ -1,224 +0,0 @@ -import { - generateUser, - translate as t, -} from '../../../../helpers/api-integration/v4'; -import { - bcryptCompare, - sha1MakeSalt, - sha1Encrypt as sha1EncryptPassword, -} from '../../../../../website/server/libs/password'; - -const ENDPOINT = '/user/auth/update-username'; - -describe('PUT /user/auth/update-username', async () => { - let user; - let password = 'password'; // from habitrpg/test/helpers/api-integration/v4/object-generators.js - - beforeEach(async () => { - user = await generateUser(); - }); - - it('successfully changes username with password', async () => { - let newUsername = 'new-username'; - let response = await user.put(ENDPOINT, { - username: newUsername, - password, - }); - expect(response).to.eql({ username: newUsername }); - await user.sync(); - expect(user.auth.local.username).to.eql(newUsername); - }); - - it('successfully changes username without password', async () => { - let newUsername = 'new-username-nopw'; - let response = await user.put(ENDPOINT, { - username: newUsername, - }); - expect(response).to.eql({ username: newUsername }); - await user.sync(); - expect(user.auth.local.username).to.eql(newUsername); - }); - - it('successfully changes username containing number and underscore', async () => { - let newUsername = 'new_username9'; - let response = await user.put(ENDPOINT, { - username: newUsername, - }); - expect(response).to.eql({ username: newUsername }); - await user.sync(); - expect(user.auth.local.username).to.eql(newUsername); - }); - - it('sets verifiedUsername when changing username', async () => { - user.flags.verifiedUsername = false; - await user.sync(); - let newUsername = 'new-username-verify'; - let response = await user.put(ENDPOINT, { - username: newUsername, - }); - expect(response).to.eql({ username: newUsername }); - await user.sync(); - expect(user.flags.verifiedUsername).to.eql(true); - }); - - it('converts user with SHA1 encrypted password to bcrypt encryption', async () => { - let myNewUsername = 'my-new-username'; - let textPassword = 'mySecretPassword'; - let salt = sha1MakeSalt(); - let sha1HashedPassword = sha1EncryptPassword(textPassword, salt); - - await user.update({ - 'auth.local.hashed_password': sha1HashedPassword, - 'auth.local.passwordHashMethod': 'sha1', - 'auth.local.salt': salt, - }); - - await user.sync(); - expect(user.auth.local.passwordHashMethod).to.equal('sha1'); - expect(user.auth.local.salt).to.equal(salt); - expect(user.auth.local.hashed_password).to.equal(sha1HashedPassword); - - // update email - let response = await user.put(ENDPOINT, { - username: myNewUsername, - password: textPassword, - }); - expect(response).to.eql({ username: myNewUsername }); - - await user.sync(); - - expect(user.auth.local.username).to.eql(myNewUsername); - expect(user.auth.local.passwordHashMethod).to.equal('bcrypt'); - expect(user.auth.local.salt).to.be.undefined; - expect(user.auth.local.hashed_password).not.to.equal(sha1HashedPassword); - - let isValidPassword = await bcryptCompare(textPassword, user.auth.local.hashed_password); - expect(isValidPassword).to.equal(true); - }); - - context('errors', async () => { - it('prevents username update if new username is already taken', async () => { - let existingUsername = 'existing-username'; - await generateUser({'auth.local.username': existingUsername, 'auth.local.lowerCaseUsername': existingUsername }); - - await expect(user.put(ENDPOINT, { - username: existingUsername, - password, - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameTaken'), - }); - }); - - it('errors if password is wrong', async () => { - let newUsername = 'new-username'; - await expect(user.put(ENDPOINT, { - username: newUsername, - password: 'wrong-password', - })).to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('wrongPassword'), - }); - }); - - it('errors if new username is not provided', async () => { - await expect(user.put(ENDPOINT, { - password, - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), - }); - }); - - it('errors if new username is a slur', async () => { - await expect(user.put(ENDPOINT, { - username: 'TESTPLACEHOLDERSLURWORDHERE', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), - }); - }); - - it('errors if new username contains a slur', async () => { - await expect(user.put(ENDPOINT, { - username: 'TESTPLACEHOLDERSLURWORDHERE_otherword', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), - }); - await expect(user.put(ENDPOINT, { - username: 'something_TESTPLACEHOLDERSLURWORDHERE', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), - }); - await expect(user.put(ENDPOINT, { - username: 'somethingTESTPLACEHOLDERSLURWORDHEREotherword', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: [t('usernameIssueLength'), t('usernameIssueSlur')].join(' '), - }); - }); - - it('errors if new username is not allowed', async () => { - await expect(user.put(ENDPOINT, { - username: 'support', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueForbidden'), - }); - }); - - it('errors if new username is not allowed regardless of casing', async () => { - await expect(user.put(ENDPOINT, { - username: 'SUppORT', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueForbidden'), - }); - }); - - it('errors if username has incorrect length', async () => { - await expect(user.put(ENDPOINT, { - username: 'thisisaverylongusernameover20characters', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueLength'), - }); - }); - - it('errors if new username contains invalid characters', async () => { - await expect(user.put(ENDPOINT, { - username: 'Eichhörnchen', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueInvalidCharacters'), - }); - await expect(user.put(ENDPOINT, { - username: 'test.name', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueInvalidCharacters'), - }); - await expect(user.put(ENDPOINT, { - username: '🤬', - })).to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('usernameIssueInvalidCharacters'), - }); - }); - }); -}); diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index a7671d3f1c..15d9fa8ecd 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -17,10 +17,10 @@ import { encrypt } from '../../libs/encryption'; import { loginRes, hasBackupAuth, - hasLocalAuth, loginSocial, registerLocal, } from '../../libs/auth'; +import {verifyUsername} from '../../libs/user/validation'; const BASE_URL = nconf.get('BASE_URL'); const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL'); @@ -144,7 +144,6 @@ api.loginSocial = { * @apiName UpdateUsername * @apiGroup User * - * @apiParam (Body) {String} password The current user password * @apiParam (Body) {String} username The new username * @apiSuccess {String} data.username The new username @@ -154,37 +153,55 @@ api.updateUsername = { middlewares: [authWithHeaders()], url: '/user/auth/update-username', async handler (req, res) { - let user = res.locals.user; + const user = res.locals.user; req.checkBody({ - password: { - notEmpty: {errorMessage: res.t('missingPassword')}, - }, username: { notEmpty: {errorMessage: res.t('missingUsername')}, }, }); - let validationErrors = req.validationErrors(); + const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; - if (!hasLocalAuth(user)) throw new BadRequest(res.t('userHasNoLocalRegistration')); + const newUsername = req.body.username; - let password = req.body.password; - let isValidPassword = await passwordUtils.compare(user, password); - if (!isValidPassword) throw new NotAuthorized(res.t('wrongPassword')); + const issues = verifyUsername(newUsername, res); + if (issues.length > 0) throw new BadRequest(issues.join(' ')); - let count = await User.count({ 'auth.local.lowerCaseUsername': req.body.username.toLowerCase() }); - if (count > 0) throw new BadRequest(res.t('usernameTaken')); + const password = req.body.password; + if (password !== undefined) { + let isValidPassword = await passwordUtils.compare(user, password); + if (!isValidPassword) throw new NotAuthorized(res.t('wrongPassword')); + } + + const existingUser = await User.findOne({ 'auth.local.lowerCaseUsername': newUsername.toLowerCase() }, {auth: 1}).exec(); + if (existingUser !== undefined && existingUser !== null && existingUser._id !== user._id) { + throw new BadRequest(res.t('usernameTaken')); + } // if password is using old sha1 encryption, change it - if (user.auth.local.passwordHashMethod === 'sha1') { + if (user.auth.local.passwordHashMethod === 'sha1' && password !== undefined) { await passwordUtils.convertToBcrypt(user, password); // user is saved a few lines below } // save username - user.auth.local.lowerCaseUsername = req.body.username.toLowerCase(); - user.auth.local.username = req.body.username; + user.auth.local.lowerCaseUsername = newUsername.toLowerCase(); + user.auth.local.username = newUsername; + if (!user.flags.verifiedUsername) { + user.flags.verifiedUsername = true; + if (user.items.pets['Bear-Veteran']) { + user.items.pets['Fox-Veteran'] = 5; + } else if (user.items.pets['Lion-Veteran']) { + user.items.pets['Bear-Veteran'] = 5; + } else if (user.items.pets['Tiger-Veteran']) { + user.items.pets['Lion-Veteran'] = 5; + } else if (user.items.pets['Wolf-Veteran']) { + user.items.pets['Tiger-Veteran'] = 5; + } else { + user.items.pets['Wolf-Veteran'] = 5; + } + } await user.save(); res.respond(200, { username: req.body.username }); diff --git a/website/server/controllers/api-v4/auth.js b/website/server/controllers/api-v4/auth.js index a4f6cfe202..05f8b6dd9b 100644 --- a/website/server/controllers/api-v4/auth.js +++ b/website/server/controllers/api-v4/auth.js @@ -2,86 +2,11 @@ import { authWithHeaders, } from '../../middlewares/auth'; import * as authLib from '../../libs/auth'; -import { - NotAuthorized, - BadRequest, -} from '../../libs/errors'; -import * as passwordUtils from '../../libs/password'; import { model as User } from '../../models/user'; import {verifyUsername} from '../../libs/user/validation'; const api = {}; -/** - * @api {put} /api/v4/user/auth/update-username Update username - * @apiDescription Update the username of a local user - * @apiName UpdateUsername - * @apiGroup User - * - * @apiParam (Body) {String} username The new username - - * @apiSuccess {String} data.username The new username - **/ -api.updateUsername = { - method: 'PUT', - middlewares: [authWithHeaders()], - url: '/user/auth/update-username', - async handler (req, res) { - const user = res.locals.user; - - req.checkBody({ - username: { - notEmpty: {errorMessage: res.t('missingUsername')}, - }, - }); - - const validationErrors = req.validationErrors(); - if (validationErrors) throw validationErrors; - - const newUsername = req.body.username; - - const issues = verifyUsername(newUsername, res); - if (issues.length > 0) throw new BadRequest(issues.join(' ')); - - const password = req.body.password; - if (password !== undefined) { - let isValidPassword = await passwordUtils.compare(user, password); - if (!isValidPassword) throw new NotAuthorized(res.t('wrongPassword')); - } - - const existingUser = await User.findOne({ 'auth.local.lowerCaseUsername': newUsername.toLowerCase() }, {auth: 1}).exec(); - if (existingUser !== undefined && existingUser !== null && existingUser._id !== user._id) { - throw new BadRequest(res.t('usernameTaken')); - } - - // if password is using old sha1 encryption, change it - if (user.auth.local.passwordHashMethod === 'sha1' && password !== undefined) { - await passwordUtils.convertToBcrypt(user, password); // user is saved a few lines below - } - - // save username - user.auth.local.lowerCaseUsername = newUsername.toLowerCase(); - user.auth.local.username = newUsername; - if (!user.flags.verifiedUsername) { - user.flags.verifiedUsername = true; - if (user.items.pets['Bear-Veteran']) { - user.items.pets['Fox-Veteran'] = 5; - } else if (user.items.pets['Lion-Veteran']) { - user.items.pets['Bear-Veteran'] = 5; - } else if (user.items.pets['Tiger-Veteran']) { - user.items.pets['Lion-Veteran'] = 5; - } else if (user.items.pets['Wolf-Veteran']) { - user.items.pets['Tiger-Veteran'] = 5; - } else { - user.items.pets['Wolf-Veteran'] = 5; - } - } - await user.save(); - - res.respond(200, { username: req.body.username }); - }, -}; - api.verifyUsername = { method: 'POST', url: '/user/auth/verify-username', diff --git a/website/server/middlewares/appRoutes.js b/website/server/middlewares/appRoutes.js index 5fe0408a8f..5819c7231d 100644 --- a/website/server/middlewares/appRoutes.js +++ b/website/server/middlewares/appRoutes.js @@ -34,7 +34,6 @@ app.use('/api/v3', v3Router); // A list of v3 routes in the format METHOD-URL to skip const v4RouterOverrides = [ // 'GET-/status', Example to override the GET /status api call - 'PUT-/user/auth/update-username', 'POST-/user/auth/local/register', 'GET-/user', 'PUT-/user', From 39761bdc0441867e4b6597890fc94071ea395ad0 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 15 Nov 2018 12:01:26 +0100 Subject: [PATCH 02/79] Add API Call to retrieve auto-complete options for usernames --- website/server/controllers/api-v4/members.js | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 website/server/controllers/api-v4/members.js diff --git a/website/server/controllers/api-v4/members.js b/website/server/controllers/api-v4/members.js new file mode 100644 index 0000000000..d46c75f650 --- /dev/null +++ b/website/server/controllers/api-v4/members.js @@ -0,0 +1,34 @@ +import {model as User} from '../../models/user'; + +let api = {}; + + +api.getUsernameAutocompletes = { + method: 'GET', + url: '/members/find/:username', + middlewares: [], + async handler (req, res) { + req.checkParams('username', res.t('invalidReqParams')).notEmpty(); + + let validationErrors = req.validationErrors(); + if (validationErrors) throw validationErrors; + + let username = req.params.username.toLowerCase(); + if (username[0] === '@') username = username.slice(1, username.length); + + if (username.length < 2) { + res.respond(200, []); + return; + } + + let members = await User + .find({'auth.local.lowerCaseUsername': {$regex: `.*${username}.*`}, 'flags.verifiedUsername': true}) + .select(['profile.name', 'contributor', 'auth.local.username']) + .limit(20) + .exec(); + + res.respond(200, members); + }, +}; + +module.exports = api; From aae2fb1cb9f05a0bf84a8b8d8c84892843eb2fdc Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 15 Nov 2018 14:27:14 +0100 Subject: [PATCH 03/79] Create links to users profile in chat messages --- package-lock.json | 420 +++++++++---------- test/api/unit/libs/highlightMentions.js | 57 +++ website/server/controllers/api-v3/chat.js | 4 +- website/server/controllers/api-v3/members.js | 3 +- website/server/libs/highlightMentions.js | 22 + 5 files changed, 294 insertions(+), 212 deletions(-) create mode 100644 test/api/unit/libs/highlightMentions.js create mode 100644 website/server/libs/highlightMentions.js diff --git a/package-lock.json b/package-lock.json index 0afe237bc9..1e9b493ec1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "dependencies": { "@babel/code-frame": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", "requires": { "@babel/highlight": "7.0.0-beta.44" @@ -14,7 +14,7 @@ }, "@babel/generator": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", "requires": { "@babel/types": "7.0.0-beta.44", @@ -38,7 +38,7 @@ }, "@babel/helper-function-name": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", "requires": { "@babel/helper-get-function-arity": "7.0.0-beta.44", @@ -48,7 +48,7 @@ }, "@babel/helper-get-function-arity": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", "requires": { "@babel/types": "7.0.0-beta.44" @@ -56,7 +56,7 @@ }, "@babel/helper-split-export-declaration": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", "requires": { "@babel/types": "7.0.0-beta.44" @@ -64,7 +64,7 @@ }, "@babel/highlight": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", "requires": { "chalk": "^2.0.0", @@ -74,7 +74,7 @@ }, "@babel/template": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", "requires": { "@babel/code-frame": "7.0.0-beta.44", @@ -85,14 +85,14 @@ "dependencies": { "babylon": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==" } } }, "@babel/traverse": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", "requires": { "@babel/code-frame": "7.0.0-beta.44", @@ -109,7 +109,7 @@ "dependencies": { "babylon": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==" }, "debug": { @@ -134,7 +134,7 @@ }, "@babel/types": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", "requires": { "esutils": "^2.0.2", @@ -306,7 +306,7 @@ }, "acorn-jsx": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { @@ -315,7 +315,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "http://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=", "dev": true } @@ -611,7 +611,7 @@ }, "ansi-colors": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "requires": { "ansi-wrap": "^0.1.0" @@ -792,7 +792,7 @@ "dependencies": { "async": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" }, "winston": { @@ -825,7 +825,7 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" } } @@ -1229,7 +1229,7 @@ "dependencies": { "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -1596,7 +1596,7 @@ }, "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-array-reduce": { @@ -1723,7 +1723,7 @@ }, "axios": { "version": "0.18.0", - "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { "follow-redirects": "^1.3.0", @@ -1747,7 +1747,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -1807,7 +1807,7 @@ "dependencies": { "babylon": { "version": "7.0.0-beta.44", - "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==" } } @@ -1955,7 +1955,7 @@ }, "babel-plugin-istanbul": { "version": "4.1.6", - "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", "dev": true, "requires": { @@ -1967,17 +1967,17 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, "babel-plugin-transform-es2015-arrow-functions": { @@ -3839,7 +3839,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "requires": { "is-buffer": "^1.0.2" @@ -3891,7 +3891,7 @@ "dependencies": { "ansi-colors": { "version": "0.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.1.0.tgz", "integrity": "sha1-M0rDbNPq1wjeXGnhmpjRhkImtD8=", "requires": { "ansi-bgblack": "^0.1.1", @@ -4165,7 +4165,7 @@ }, "basic-auth": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" }, "bcrypt": { @@ -4933,7 +4933,7 @@ }, "bl": { "version": "1.2.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "requires": { "readable-stream": "^2.3.5", @@ -4942,7 +4942,7 @@ }, "blob": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", "dev": true }, @@ -5096,7 +5096,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "requires": { "buffer-xor": "^1.0.3", @@ -5130,7 +5130,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "requires": { "bn.js": "^4.1.0", @@ -5175,7 +5175,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { "base64-js": "^1.0.2", @@ -5332,7 +5332,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "requires": { "camelcase": "^2.0.0", @@ -5460,7 +5460,7 @@ }, "chai-nightwatch": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", "dev": true, "requires": { @@ -5476,7 +5476,7 @@ }, "deep-eql": { "version": "0.1.3", - "resolved": "http://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=", "dev": true, "requires": { @@ -5552,7 +5552,7 @@ }, "cheerio": { "version": "0.19.0", - "resolved": "http://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", "integrity": "sha1-dy5wFfLuKZZQltcepBdbdas1SSU=", "requires": { "css-select": "~1.0.0", @@ -5564,7 +5564,7 @@ "dependencies": { "css-select": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", "integrity": "sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA=", "requires": { "boolbase": "~1.0.0", @@ -5575,7 +5575,7 @@ }, "css-what": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", "integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w=" }, "domhandler": { @@ -5596,7 +5596,7 @@ }, "htmlparser2": { "version": "3.8.3", - "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", "requires": { "domelementtype": "1", @@ -5617,7 +5617,7 @@ }, "entities": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" } } @@ -5629,12 +5629,12 @@ }, "lodash": { "version": "3.10.1", - "resolved": "http://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=" }, "readable-stream": { "version": "1.1.14", - "resolved": "http://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.0", @@ -5824,7 +5824,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -6007,7 +6007,7 @@ }, "color": { "version": "0.11.4", - "resolved": "http://registry.npmjs.org/color/-/color-0.11.4.tgz", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "requires": { "clone": "^1.0.2", @@ -6219,7 +6219,7 @@ }, "yargs-parser": { "version": "2.4.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "requires": { "camelcase": "^3.0.0", @@ -6625,7 +6625,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -6728,7 +6728,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -6829,7 +6829,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -6913,7 +6913,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", @@ -6925,7 +6925,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", @@ -6997,12 +6997,12 @@ }, "css-color-names": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" }, "css-loader": { "version": "0.28.11", - "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", "requires": { "babel-code-frame": "^6.26.0", @@ -7023,7 +7023,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -7142,7 +7142,7 @@ }, "cssnano": { "version": "3.10.0", - "resolved": "http://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "requires": { "autoprefixer": "^6.3.1", @@ -7203,7 +7203,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -7418,7 +7418,7 @@ }, "data-store": { "version": "0.16.1", - "resolved": "http://registry.npmjs.org/data-store/-/data-store-0.16.1.tgz", + "resolved": "https://registry.npmjs.org/data-store/-/data-store-0.16.1.tgz", "integrity": "sha1-5pwDpcrBXR/zPwJUyWeDZT5ogwQ=", "requires": { "cache-base": "^0.8.4", @@ -7640,7 +7640,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "requires": { "is-buffer": "^1.0.2" @@ -8043,7 +8043,7 @@ }, "kind-of": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" } } @@ -8093,7 +8093,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "requires": { "bn.js": "^4.1.0", @@ -8165,7 +8165,7 @@ "dependencies": { "domelementtype": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" } } @@ -8298,7 +8298,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" }, "duplexer3": { @@ -8336,7 +8336,7 @@ "dependencies": { "commander": { "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "requires": { "graceful-readlink": ">= 1.0.0" @@ -8577,7 +8577,7 @@ }, "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "requires": { "is-buffer": "^1.0.2" @@ -8908,7 +8908,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -9007,7 +9007,7 @@ }, "eslint": { "version": "4.19.1", - "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { @@ -9172,7 +9172,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -9253,7 +9253,7 @@ }, "eslint-plugin-lodash": { "version": "2.7.0", - "resolved": "http://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-2.7.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-2.7.0.tgz", "integrity": "sha512-sIEzx85Sy+Higf4W+oLCIyh7ym0OEcmJCzY8ukptlGfkcyVagzYBjhUt1JfkcpT4qZC68+7TzceJSqLu+qwYMg==", "dev": true, "optional": true, @@ -9286,7 +9286,7 @@ }, "espree": { "version": "3.5.4", - "resolved": "http://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { @@ -9362,7 +9362,7 @@ }, "events": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, "eventsource-polyfill": { @@ -9419,7 +9419,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" } } @@ -9494,7 +9494,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "set-value": { @@ -9656,7 +9656,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "set-value": { @@ -9896,7 +9896,7 @@ }, "external-editor": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "requires": { "chardet": "^0.4.0", @@ -10068,7 +10068,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-glob": { @@ -10166,7 +10166,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "requires": { "loader-utils": "^1.0.2", @@ -10311,7 +10311,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", @@ -11181,7 +11181,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://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=", "dev": true, "requires": { @@ -11373,7 +11373,7 @@ }, "gif-encoder": { "version": "0.4.3", - "resolved": "http://registry.npmjs.org/gif-encoder/-/gif-encoder-0.4.3.tgz", + "resolved": "https://registry.npmjs.org/gif-encoder/-/gif-encoder-0.4.3.tgz", "integrity": "sha1-iitP6MqJWkjjoLbLs0CgpqNXGJk=", "requires": { "readable-stream": "~1.1.9" @@ -11386,7 +11386,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://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.0", @@ -11608,7 +11608,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -12071,7 +12071,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -12361,7 +12361,7 @@ }, "html-webpack-plugin": { "version": "3.2.0", - "resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", "requires": { "html-minifier": "^3.2.3", @@ -12388,7 +12388,7 @@ }, "htmlparser2": { "version": "3.3.0", - "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", "requires": { "domelementtype": "1", @@ -12412,7 +12412,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -12435,7 +12435,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", @@ -12834,7 +12834,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -12879,7 +12879,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -13095,7 +13095,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "requires": { "builtin-modules": "^1.0.0" @@ -13308,7 +13308,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, "is-object": { @@ -13867,7 +13867,7 @@ }, "json5": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { @@ -14067,7 +14067,7 @@ "dependencies": { "chai": { "version": "3.5.0", - "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", "dev": true, "requires": { @@ -14084,7 +14084,7 @@ }, "deep-eql": { "version": "0.1.3", - "resolved": "http://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=", "dev": true, "requires": { @@ -14312,7 +14312,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -14508,7 +14508,7 @@ }, "kind-of": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" } } @@ -14687,7 +14687,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -14699,7 +14699,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -15345,7 +15345,7 @@ "dependencies": { "ansi-colors": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", "integrity": "sha1-csMd4qDZoszQysMMyYI+6y9kNLU=", "requires": { "ansi-bgblack": "^0.1.1", @@ -15897,7 +15897,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "http://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=" }, "mem": { @@ -15935,7 +15935,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "requires": { "camelcase-keys": "^2.0.0", @@ -15952,7 +15952,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -16008,7 +16008,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "requires": { "is-buffer": "^1.0.2" @@ -16165,7 +16165,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mixin-deep": { @@ -16205,7 +16205,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "http://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" @@ -16315,7 +16315,7 @@ "dependencies": { "commander": { "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { @@ -16324,7 +16324,7 @@ }, "debug": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { @@ -16359,7 +16359,7 @@ }, "ms": { "version": "0.7.1", - "resolved": "http://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=", "dev": true }, @@ -16473,7 +16473,7 @@ "dependencies": { "es6-promise": { "version": "3.2.1", - "resolved": "http://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=", "dev": true }, @@ -16716,7 +16716,7 @@ }, "yargs": { "version": "3.32.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "requires": { "camelcase": "^2.0.1", @@ -16876,7 +16876,7 @@ }, "node-fetch": { "version": "1.6.3", - "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", "requires": { "encoding": "^0.1.11", @@ -17107,7 +17107,7 @@ }, "semver": { "version": "5.3.0", - "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "tough-cookie": { @@ -17428,7 +17428,7 @@ }, "chalk": { "version": "0.4.0", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "requires": { "ansi-styles": "~1.0.0", @@ -17438,7 +17438,7 @@ }, "strip-ansi": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" } } @@ -17526,7 +17526,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "semver": { @@ -17861,7 +17861,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -17873,7 +17873,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "regenerator-runtime": { @@ -17891,7 +17891,7 @@ }, "opn": { "version": "4.0.2", - "resolved": "http://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", "requires": { "object-assign": "^4.0.1", @@ -18078,7 +18078,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { "lcid": "^1.0.0" @@ -18228,12 +18228,12 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "requires": { "create-error-class": "^3.0.0", @@ -18309,7 +18309,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -18381,7 +18381,7 @@ }, "parse-asn1": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "requires": { "asn1.js": "^4.0.0", @@ -18653,7 +18653,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -18671,7 +18671,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "requires": { "through": "~2.3" @@ -18793,7 +18793,7 @@ }, "jsonfile": { "version": "2.4.0", - "resolved": "http://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.6" @@ -18891,7 +18891,7 @@ "dependencies": { "async": { "version": "0.9.2", - "resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" }, "concat-stream": { @@ -18911,7 +18911,7 @@ }, "readable-stream": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { "core-util-is": "~1.0.0", @@ -19179,7 +19179,7 @@ }, "postcss-calc": { "version": "5.3.1", - "resolved": "http://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "requires": { "postcss": "^5.0.2", @@ -19189,7 +19189,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19249,7 +19249,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19308,7 +19308,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19358,7 +19358,7 @@ }, "postcss-discard-comments": { "version": "2.0.4", - "resolved": "http://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "requires": { "postcss": "^5.0.14" @@ -19366,7 +19366,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19424,7 +19424,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19474,7 +19474,7 @@ }, "postcss-discard-empty": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "requires": { "postcss": "^5.0.14" @@ -19482,7 +19482,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19532,7 +19532,7 @@ }, "postcss-discard-overridden": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "requires": { "postcss": "^5.0.16" @@ -19540,7 +19540,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19590,7 +19590,7 @@ }, "postcss-discard-unused": { "version": "2.2.3", - "resolved": "http://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "requires": { "postcss": "^5.0.14", @@ -19599,7 +19599,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19672,7 +19672,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19763,7 +19763,7 @@ }, "postcss-merge-idents": { "version": "2.1.7", - "resolved": "http://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "requires": { "has": "^1.0.1", @@ -19773,7 +19773,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19831,7 +19831,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19902,7 +19902,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -19957,7 +19957,7 @@ }, "postcss-minify-font-values": { "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "requires": { "object-assign": "^4.0.1", @@ -19967,7 +19967,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20017,7 +20017,7 @@ }, "postcss-minify-gradients": { "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "requires": { "postcss": "^5.0.12", @@ -20026,7 +20026,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20076,7 +20076,7 @@ }, "postcss-minify-params": { "version": "1.2.2", - "resolved": "http://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "requires": { "alphanum-sort": "^1.0.1", @@ -20087,7 +20087,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20137,7 +20137,7 @@ }, "postcss-minify-selectors": { "version": "2.1.1", - "resolved": "http://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "requires": { "alphanum-sort": "^1.0.2", @@ -20148,7 +20148,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20233,7 +20233,7 @@ }, "postcss-normalize-charset": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "requires": { "postcss": "^5.0.5" @@ -20241,7 +20241,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20291,7 +20291,7 @@ }, "postcss-normalize-url": { "version": "3.0.8", - "resolved": "http://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "requires": { "is-absolute-url": "^2.0.0", @@ -20302,7 +20302,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20361,7 +20361,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20411,7 +20411,7 @@ }, "postcss-reduce-idents": { "version": "2.4.0", - "resolved": "http://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "requires": { "postcss": "^5.0.4", @@ -20420,7 +20420,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20470,7 +20470,7 @@ }, "postcss-reduce-initial": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "requires": { "postcss": "^5.0.4" @@ -20478,7 +20478,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20528,7 +20528,7 @@ }, "postcss-reduce-transforms": { "version": "1.0.4", - "resolved": "http://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "requires": { "has": "^1.0.1", @@ -20538,7 +20538,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20598,7 +20598,7 @@ }, "postcss-svgo": { "version": "2.1.6", - "resolved": "http://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "requires": { "is-svg": "^2.0.0", @@ -20609,7 +20609,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20683,7 +20683,7 @@ }, "postcss-unique-selectors": { "version": "2.0.2", - "resolved": "http://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "requires": { "alphanum-sort": "^1.0.1", @@ -20693,7 +20693,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20748,7 +20748,7 @@ }, "postcss-zindex": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "requires": { "has": "^1.0.1", @@ -20758,7 +20758,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -20843,7 +20843,7 @@ }, "pretty-hrtime": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" }, "pretty-time": { @@ -20905,7 +20905,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -21476,7 +21476,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -21588,7 +21588,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -21603,7 +21603,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -21653,7 +21653,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -21719,7 +21719,7 @@ }, "reduce-css-calc": { "version": "1.3.0", - "resolved": "http://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "requires": { "balanced-match": "^0.4.2", @@ -21811,7 +21811,7 @@ }, "regexpp": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, @@ -21844,7 +21844,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { @@ -22061,7 +22061,7 @@ }, "request": { "version": "2.76.0", - "resolved": "http://registry.npmjs.org/request/-/request-2.76.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.76.0.tgz", "integrity": "sha1-vkRQWv73A2CgQ2lVEGvjlF2VVg4=", "requires": { "aws-sign2": "~0.6.0", @@ -22331,7 +22331,7 @@ }, "kind-of": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" }, "lazy-cache": { @@ -22402,7 +22402,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -22482,7 +22482,7 @@ }, "sax": { "version": "0.6.1", - "resolved": "http://registry.npmjs.org/sax/-/sax-0.6.1.tgz", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=" }, "schema-utils": { @@ -22539,7 +22539,7 @@ "dependencies": { "commander": { "version": "2.8.1", - "resolved": "http://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.0" @@ -22555,7 +22555,7 @@ }, "semver": { "version": "5.0.3", - "resolved": "http://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" }, "semver-diff": { @@ -22686,7 +22686,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", @@ -22754,7 +22754,7 @@ }, "simple-html-tokenizer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz", "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4=" }, "sinon": { @@ -23262,7 +23262,7 @@ }, "readable-stream": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { "core-util-is": "~1.0.0", @@ -23293,7 +23293,7 @@ "dependencies": { "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "optional": true, "requires": { @@ -23342,7 +23342,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -23468,7 +23468,7 @@ "dependencies": { "readable-stream": { "version": "1.1.14", - "resolved": "http://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.0", @@ -23491,7 +23491,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://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.0", @@ -23655,7 +23655,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://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.0.0" @@ -23707,7 +23707,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-indent": { @@ -24056,7 +24056,7 @@ "dependencies": { "kind-of": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", "requires": { "is-buffer": "^1.0.2" @@ -24306,7 +24306,7 @@ }, "text-encoding": { "version": "0.6.4", - "resolved": "http://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=", "dev": true }, @@ -24322,7 +24322,7 @@ }, "through": { "version": "2.3.8", - "resolved": "http://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=" }, "through2": { @@ -24370,7 +24370,7 @@ "dependencies": { "ansi-colors": { "version": "0.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.1.0.tgz", "integrity": "sha1-M0rDbNPq1wjeXGnhmpjRhkImtD8=", "requires": { "ansi-bgblack": "^0.1.1", @@ -24909,7 +24909,7 @@ }, "underscore.string": { "version": "3.0.3", - "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-3.0.3.tgz", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.0.3.tgz", "integrity": "sha1-Rhe4waJQz25QZPu7Nj0PqWzxRVI=" }, "undertaker": { @@ -25321,7 +25321,7 @@ }, "yargs-parser": { "version": "2.4.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "requires": { "camelcase": "^3.0.0", @@ -26066,12 +26066,12 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "requires": { "create-error-class": "^3.0.0", @@ -26200,7 +26200,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "requires": { "graceful-fs": "^4.1.2", @@ -26229,7 +26229,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "read-pkg": { @@ -26331,7 +26331,7 @@ "dependencies": { "ws": { "version": "4.1.0", - "resolved": "http://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", "dev": true, "requires": { @@ -26343,7 +26343,7 @@ }, "webpack-dev-middleware": { "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { @@ -26465,7 +26465,7 @@ "dependencies": { "async": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" } } @@ -26490,7 +26490,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "http://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=" } } @@ -26502,7 +26502,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", @@ -26594,7 +26594,7 @@ "dependencies": { "xmlbuilder": { "version": "9.0.7", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" } } diff --git a/test/api/unit/libs/highlightMentions.js b/test/api/unit/libs/highlightMentions.js new file mode 100644 index 0000000000..2b77b05728 --- /dev/null +++ b/test/api/unit/libs/highlightMentions.js @@ -0,0 +1,57 @@ +import { + highlightMentions, +} from '../../../../website/server/libs/highlightMentions'; +import mongoose from 'mongoose'; + +describe.only('highlightMentions', () => { + beforeEach(() => { + const mockFind = { + select () { + return this; + }, + lean () { + return this; + }, + exec () { + return Promise.resolve([{ + auth: { local: { username: 'user' } }, _id: '111', + }, { auth: { local: { username: 'user2' } }, _id: '222', + }, { auth: { local: { username: 'user3' } }, _id: '333', + }, + ]); + }, + }; + + sinon.stub(mongoose.Model, 'find').returns(mockFind); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('doesn\'t change text without mentions', async () => { + let text = 'some chat text'; + let highlightedText = await highlightMentions(text); + expect(highlightedText).to.equal(text); + }); + it('highlights existing users', async () => { + let text = '@user: message'; + let highlightedText = await highlightMentions(text); + expect(highlightedText).to.equal('[@user](https://habitica.com/members/111): message'); + }); + it('doesn\'t highlight nonexisting users', async () => { + let text = '@nouser message'; + let highlightedText = await highlightMentions(text); + expect(highlightedText).to.equal('@nouser message'); + }); + it('highlights multiple existing users', async () => { + let text = '@user message (@user2) @user3 @user'; + let highlightedText = await highlightMentions(text); + expect(highlightedText).to.equal('[@user](https://habitica.com/members/111) message ([@user2](https://habitica.com/members/222)) [@user3](https://habitica.com/members/333) [@user](https://habitica.com/members/111)'); + }); + it('doesn\'t highlight more than 5 users', async () => { + let text = '@user @user2 @user3 @user4 @user5 @user6'; + let highlightedText = await highlightMentions(text); + expect(highlightedText).to.equal(text); + }); +}); diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index 95f6f405f9..0c1eb316ea 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -18,6 +18,7 @@ import guildsAllowingBannedWords from '../../libs/guildsAllowingBannedWords'; import { getMatchesByWordArray } from '../../libs/stringUtils'; import bannedSlurs from '../../libs/bannedSlurs'; import apiError from '../../libs/apiError'; +import {highlightMentions} from '../../libs/highlightMentions'; const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { return { email, canSend: true }; @@ -175,7 +176,8 @@ api.postChat = { throw new NotAuthorized(res.t('messageGroupChatSpam')); } - const newChatMessage = group.sendChat(req.body.message, user); + const message = await highlightMentions(req.body.message); + const newChatMessage = group.sendChat(message, user); let toSave = [newChatMessage.save()]; if (group.type === 'party') { diff --git a/website/server/controllers/api-v3/members.js b/website/server/controllers/api-v3/members.js index 1723c925b2..daae1f2326 100644 --- a/website/server/controllers/api-v3/members.js +++ b/website/server/controllers/api-v3/members.js @@ -20,6 +20,7 @@ import { } from '../../libs/email'; import { sendNotification as sendPushNotification } from '../../libs/pushNotifications'; import { achievements } from '../../../../website/common/'; +import {highlightMentions} from '../../libs/highlightMentions'; let api = {}; @@ -632,7 +633,7 @@ api.sendPrivateMessage = { if (validationErrors) throw validationErrors; const sender = res.locals.user; - const message = req.body.message; + const message = await highlightMentions(req.body.message); const receiver = await User.findById(req.body.toUserId).exec(); if (!receiver) throw new NotFound(res.t('userNotFound')); if (!receiver.flags.verifiedUsername) delete receiver.auth.local.username; diff --git a/website/server/libs/highlightMentions.js b/website/server/libs/highlightMentions.js new file mode 100644 index 0000000000..a4229049d1 --- /dev/null +++ b/website/server/libs/highlightMentions.js @@ -0,0 +1,22 @@ +import {model as User} from '../models/user'; + +const mentionRegex = new RegExp('\\B@[-\\w]+', 'g'); + +export async function highlightMentions (text) { + const mentions = text.match(mentionRegex); + if (mentions !== null && mentions.length <= 5) { + const usernames = mentions.map((mention) => { + return mention.substr(1); + }); + let members = await User + .find({'auth.local.username': {$in: usernames}, 'flags.verifiedUsername': true}) + .select(['auth.local.username', '_id']) + .lean() + .exec(); + members.forEach((member) => { + const username = member.auth.local.username; + text = text.replace(new RegExp(`@${username}\\b`, 'g'), `[@${username}](https://habitica.com/members/${member._id})`); + }); + } + return text; +} From e9c86622c5f907f3dc9be66ee1712e2f02bb35e4 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 26 Nov 2018 15:47:22 +0100 Subject: [PATCH 04/79] Begin adding server-side autocomplete to web client --- package-lock.json | 16 +- package.json | 2 + website/client/components/chat/chatCard.vue | 15 +- website/client/components/groups/chat.vue | 154 +++++++++++++++++--- website/server/libs/highlightMentions.js | 2 +- 5 files changed, 161 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1e9b493ec1..215a7201c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1701,7 +1701,7 @@ "dependencies": { "sax": { "version": "1.2.1", - "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "uuid": { @@ -17240,7 +17240,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -21931,7 +21931,7 @@ "dependencies": { "css-select": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "requires": { "boolbase": "~1.0.0", @@ -24684,6 +24684,11 @@ "punycode": "^1.4.1" } }, + "tributejs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tributejs/-/tributejs-3.4.0.tgz", + "integrity": "sha512-BWB2YvfKpa6hZgcP9hKN5/tH3P/Guspn4r+ePgwNpftnQwMb6GVWTUgBpkMtVXkR5dwLLcP/iW87i9C1mp21zQ==" + }, "trim-leading-lines": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/trim-leading-lines/-/trim-leading-lines-0.1.1.tgz", @@ -26042,6 +26047,11 @@ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz", "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==" }, + "vue-tribute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vue-tribute/-/vue-tribute-1.0.1.tgz", + "integrity": "sha1-ThJfdoEjxUBd4izjQ4NqmaCVRz0=" + }, "vuedraggable": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.16.0.tgz", diff --git a/package.json b/package.json index 1203e1731c..9c354eca47 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "svg-url-loader": "^2.3.2", "svgo": "^1.0.5", "svgo-loader": "^2.1.0", + "tributejs": "^3.4.0", "universal-analytics": "^0.4.16", "update": "^0.7.4", "upgrade": "^1.1.0", @@ -104,6 +105,7 @@ "vue-router": "^3.0.0", "vue-style-loader": "^4.1.0", "vue-template-compiler": "^2.5.16", + "vue-tribute": "^1.0.1", "vuedraggable": "^2.15.0", "vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec", "webpack": "^3.12.0", diff --git a/website/client/components/chat/chatCard.vue b/website/client/components/chat/chatCard.vue index f992148b26..e574c44cf8 100644 --- a/website/client/components/chat/chatCard.vue +++ b/website/client/components/chat/chatCard.vue @@ -16,7 +16,7 @@ div span.mr-1(v-if="msg.username") @{{ msg.username }} span.mr-1(v-if="msg.username") • span(v-b-tooltip="", :title="msg.timestamp | date") {{ msg.timestamp | timeAgo }} - .text(v-html='atHighlight(parseMarkdown(msg.text))') + .text(v-html='atHighlight(parseMarkdown(msg.text))', ref='markdownContainer') hr .d-flex(v-if='msg.id') .action.d-flex.align-items-center(v-if='!inbox', @click='copyAsTodo(msg)') @@ -244,6 +244,16 @@ export default { return achievementsLib.getContribText(message.contributor, message.backer) || ''; }, }, + mounted () { + const links = this.$refs.markdownContainer.getElementsByTagName('a'); + for (var i = 0; i < links.length; i++) { + const link = links[i]; + links[i].onclick = (event) => { + event.preventDefault(); + this.$router.push({ path: link.getAttribute('href')}); + }; + } + }, methods: { async like () { let message = cloneDeep(this.msg); @@ -299,7 +309,8 @@ export default { }); }, parseMarkdown (text) { - return habiticaMarkdown.render(text); + const mdText = habiticaMarkdown.render(text); + return mdText; }, }, }; diff --git a/website/client/components/groups/chat.vue b/website/client/components/groups/chat.vue index 0f6b23164c..df0ccde591 100644 --- a/website/client/components/groups/chat.vue +++ b/website/client/components/groups/chat.vue @@ -4,23 +4,17 @@ h3(v-once) {{ label }} .row - textarea(:placeholder='placeholder', - v-model='newMessage', - ref='user-entry', - :class='{"user-entry": newMessage}', - @keydown='updateCarretPosition', - @keyup.ctrl.enter='sendMessageShortcut()', - @paste='disableMessageSendShortcut()', - maxlength='3000' - ) + vue-tribute(:options="autocompleteOptions") + textarea(:placeholder='placeholder', + v-model='newMessage', + ref='user-entry', + :class='{"user-entry": newMessage}', + @keydown='updateCarretPosition', + @keyup.ctrl.enter='sendMessageShortcut()', + @paste='disableMessageSendShortcut()', + maxlength='3000' + ) span {{ currentLength }} / 3000 - autocomplete( - :text='newMessage', - v-on:select="selectedAutocomplete", - :textbox='textbox', - :coords='coords', - :caretPosition = 'caretPosition', - :chat='group.chat') .row.chat-actions .col-6.chat-receive-actions @@ -42,17 +36,29 @@ From a450ac3652217e7470c2f2aa5fd3af303fd4cb70 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Tue, 27 Nov 2018 15:25:41 +0100 Subject: [PATCH 09/79] Improve chat input design --- website/client/components/groups/chat.vue | 122 ++++++++++++---------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/website/client/components/groups/chat.vue b/website/client/components/groups/chat.vue index 55a0530e63..ce121d58b2 100644 --- a/website/client/components/groups/chat.vue +++ b/website/client/components/groups/chat.vue @@ -1,27 +1,27 @@ From ed266adfc25017f012e939945075ff67b646162d Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 19 Sep 2019 16:32:17 +0200 Subject: [PATCH 72/79] remove old code --- website/client/components/groups/group.vue | 10 ---------- website/client/components/groups/tavern.vue | 1 - website/client/components/settings/site.vue | 16 ---------------- 3 files changed, 27 deletions(-) diff --git a/website/client/components/groups/group.vue b/website/client/components/groups/group.vue index b92b508f01..8ff4d05b69 100644 --- a/website/client/components/groups/group.vue +++ b/website/client/components/groups/group.vue @@ -30,7 +30,6 @@ chat( :label="$t('chat')", :group="group", - :autocompleteContext="autocompleteContext" :placeholder="!isParty ? $t('chatPlaceholder') : $t('partyChatPlaceholder')", @fetchRecentMessages="fetchRecentMessages()" ) @@ -372,15 +371,6 @@ export default { showNoNotificationsMessage () { return this.group.memberCount > this.$store.state.constants.LARGE_GROUP_COUNT_MESSAGE_CUTOFF; }, - autocompleteContext () { - if (this.isParty) { - return 'party'; - } else if (this.group.privacy === 'public') { - return 'publicGuild'; - } else { - return 'privateGuild'; - } - }, }, mounted () { if (this.isParty) this.searchId = 'party'; diff --git a/website/client/components/groups/tavern.vue b/website/client/components/groups/tavern.vue index 03d9f1700d..86776fb7d9 100644 --- a/website/client/components/groups/tavern.vue +++ b/website/client/components/groups/tavern.vue @@ -10,7 +10,6 @@ chat( :label="$t('tavernChat')", :group="group", - :autocompleteContext="'tavern'" :placeholder="$t('tavernCommunityGuidelinesPlaceholder')", @fetchRecentMessages="fetchRecentMessages()" ) diff --git a/website/client/components/settings/site.vue b/website/client/components/settings/site.vue index c95fe60045..4f6d75d1f8 100644 --- a/website/client/components/settings/site.vue +++ b/website/client/components/settings/site.vue @@ -85,18 +85,6 @@ hr - div - h5 {{ $t('mentioning') }} - h6 {{ $t('suggestMyUsername') }} - .form-horizontal - select.form-control( - v-model='user.preferences.searchableUsername', - @change='set("searchableUsername")' - ) - option(v-for='option in searchableUsernameOptions' :value='option.value') {{ option.text }} - - hr - div h5 {{ $t('customDayStart') }} .alert.alert-warning {{ $t('customDayStartInfo1') }} @@ -271,10 +259,6 @@ export default { }, displayNameIssues: [], usernameIssues: [], - searchableUsernameOptions: [ - {text: this.$t('onlyPrivateSpaces'), value: false}, - {text: this.$t('everywhere'), value: true}, - ], }; }, mounted () { From 0072a3968d13a27bf83d7408978fc2cb92a419db Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 30 Sep 2019 15:10:20 +0200 Subject: [PATCH 73/79] Send push notifications on mentions --- website/server/controllers/api-v3/chat.js | 27 +++++++++++++++++++++-- website/server/libs/highlightMentions.js | 7 +++--- website/server/libs/pushNotifications.js | 2 +- website/server/models/user/schema.js | 3 +++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index c6fe56d439..1a50a9601d 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -20,6 +20,7 @@ import { getMatchesByWordArray } from '../../libs/stringUtils'; import bannedSlurs from '../../libs/bannedSlurs'; import apiError from '../../libs/apiError'; import {highlightMentions} from '../../libs/highlightMentions'; +import {sendNotification} from '../../libs/pushNotifications'; const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { return { email, canSend: true }; @@ -183,7 +184,7 @@ api.postChat = { throw new NotAuthorized(res.t('messageGroupChatSpam')); } - const [message, mentions] = await highlightMentions(req.body.message); + const [message, mentions, mentionedMembers] = await highlightMentions(req.body.message); let client = req.headers['x-client'] || '3rd Party'; if (client) { client = client.replace('habitica-', ''); @@ -192,7 +193,6 @@ api.postChat = { let flagCount = 0; if (group.privacy === 'public' && user.flags.chatShadowMuted) { flagCount = common.constants.CHAT_FLAG_FROM_SHADOW_MUTE; - let message = req.body.message; // Email the mods let authorEmail = getUserInfo(user, ['email']).email; @@ -232,6 +232,29 @@ api.postChat = { toSave.push(user.save()); } + mentionedMembers.forEach((member) => { + if (member._id === user._id) return; + const pushNotifPrefs = member.preferences.pushNotifications; + if (group.type === 'party') { + if (pushNotifPrefs.mentionParty !== true) { + return; + } + } else if (member.guilds.contains(group._id)) { + if (pushNotifPrefs.mentionJoinedGuild !== true) { + return; + } + } else { + if (group.privacy !== 'public') { + return; + } + if (pushNotifPrefs.mentionUnjoinedGuild !== true) { + return; + } + } + sendNotification(member, {identifier: 'chatMention', title: `${user.profile.name} mentioned you in ${group.name}`, message: req.body.message}); + }); + + await Promise.all(toSave); let analyticsObject = { diff --git a/website/server/libs/highlightMentions.js b/website/server/libs/highlightMentions.js index d20735535e..48839bc38e 100644 --- a/website/server/libs/highlightMentions.js +++ b/website/server/libs/highlightMentions.js @@ -4,13 +4,14 @@ const mentionRegex = new RegExp('\\B@[-\\w]+', 'g'); export async function highlightMentions (text) { const mentions = text.match(mentionRegex); + let members = []; if (mentions !== null && mentions.length <= 5) { const usernames = mentions.map((mention) => { return mention.substr(1); }); - let members = await User + members = await User .find({'auth.local.username': {$in: usernames}, 'flags.verifiedUsername': true}) - .select(['auth.local.username', '_id']) + .select(['auth.local.username', '_id', 'preferences.pushNotifications', 'pushDevices']) .lean() .exec(); members.forEach((member) => { @@ -18,5 +19,5 @@ export async function highlightMentions (text) { text = text.replace(new RegExp(`@${username}(?![\\-\\w])`, 'g'), `[@${username}](/profile/${member._id})`); }); } - return [text, mentions]; + return [text, mentions, members]; } diff --git a/website/server/libs/pushNotifications.js b/website/server/libs/pushNotifications.js index 4cd4a1d82f..ad2a925bf0 100644 --- a/website/server/libs/pushNotifications.js +++ b/website/server/libs/pushNotifications.js @@ -56,7 +56,7 @@ function sendNotification (user, details = {}) { case 'ios': if (apnProvider) { const notification = new apn.Notification({ - alert: details.message, + alert: {title: details.title, body: details.message}, sound: 'default', category: details.category, topic: 'com.habitrpg.ios.Habitica', diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index f941f874b5..89cf5057ae 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -503,6 +503,9 @@ let schema = new Schema({ questStarted: {$type: Boolean, default: true}, invitedQuest: {$type: Boolean, default: true}, majorUpdates: {$type: Boolean, default: true}, + mentionParty: {$type: Boolean, default: true}, + mentionJoinedGuild: {$type: Boolean, default: true}, + mentionUnjoinedGuild: {$type: Boolean, default: true}, }, suppressModals: { levelUp: {$type: Boolean, default: false}, From 2d3f2500e8a9f5588c43e9006e7f0f3c2724acd3 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Tue, 1 Oct 2019 13:26:38 +0200 Subject: [PATCH 74/79] Improve handling for sending mention notifications --- website/server/controllers/api-v3/chat.js | 31 ++++++----------------- website/server/libs/chat.js | 7 +++-- website/server/models/group.js | 25 ++++++++++++++++-- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index 5f38dadee5..ba2312bae3 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -224,7 +224,14 @@ api.postChat = { }); } - const newChatMessage = group.sendChat({message: req.body.message, user, flagCount, metaData: null, client, translate: res.t}); + const newChatMessage = group.sendChat({message: req.body.message, + user, + flagCount, + metaData: null, + client, + translate: res.t, + mentions, + mentionedMembers}); let toSave = [newChatMessage.save()]; if (group.type === 'party') { @@ -232,28 +239,6 @@ api.postChat = { toSave.push(user.save()); } - mentionedMembers.forEach((member) => { - if (member._id === user._id) return; - const pushNotifPrefs = member.preferences.pushNotifications; - if (group.type === 'party') { - if (pushNotifPrefs.mentionParty !== true) { - return; - } - } else if (member.guilds.contains(group._id)) { - if (pushNotifPrefs.mentionJoinedGuild !== true) { - return; - } - } else { - if (group.privacy !== 'public') { - return; - } - if (pushNotifPrefs.mentionUnjoinedGuild !== true) { - return; - } - } - sendNotification(member, {identifier: 'chatMention', title: `${user.profile.name} mentioned you in ${group.name}`, message: req.body.message}); - }); - await Promise.all(toSave); diff --git a/website/server/libs/chat.js b/website/server/libs/chat.js index a19e9b260c..0e27535099 100644 --- a/website/server/libs/chat.js +++ b/website/server/libs/chat.js @@ -18,15 +18,18 @@ export async function getAuthorEmailFromMessage (message) { } } -export async function sendChatPushNotifications (user, group, message, translate) { +export async function sendChatPushNotifications (user, group, message, mentions, translate) { let members = await User.find({ 'party._id': group._id, _id: {$ne: user._id}, }) - .select('preferences.pushNotifications preferences.language profile.name pushDevices') + .select('preferences.pushNotifications preferences.language profile.name pushDevices auth.local.username') .exec(); members.forEach(member => { if (member.preferences.pushNotifications.partyActivity !== false) { + if (mentions && mentions.includes(`@${member.auth.local.username}`) && member.preferences.pushNotifications.mentionParty !== false) { + return; + } sendPushNotification( member, { diff --git a/website/server/models/group.js b/website/server/models/group.js index f7325bc636..f577218a7a 100644 --- a/website/server/models/group.js +++ b/website/server/models/group.js @@ -513,7 +513,7 @@ schema.methods.getMemberCount = async function getMemberCount () { }; schema.methods.sendChat = function sendChat (options = {}) { - const {message, user, metaData, client, flagCount = 0, info = {}, translate} = options; + const {message, user, metaData, client, flagCount = 0, info = {}, translate, mentions, mentionedMembers} = options; let newMessage = messageDefaults(message, user, client, flagCount, info); let newChatMessage = new Chat(); newChatMessage = Object.assign(newChatMessage, newMessage); @@ -576,8 +576,29 @@ schema.methods.sendChat = function sendChat (options = {}) { }); if (this.type === 'party' && user) { - sendChatPushNotifications(user, this, newChatMessage, translate); + sendChatPushNotifications(user, this, newChatMessage, mentions, translate); } + mentionedMembers.forEach((member) => { + if (member._id === user._id) return; + const pushNotifPrefs = member.preferences.pushNotifications; + if (this.type === 'party') { + if (pushNotifPrefs.mentionParty !== true) { + return; + } + } else if (member.guilds && member.guilds.includes(this._id)) { + if (pushNotifPrefs.mentionJoinedGuild !== true) { + return; + } + } else { + if (this.privacy !== 'public') { + return; + } + if (pushNotifPrefs.mentionUnjoinedGuild !== true) { + return; + } + } + sendPushNotification(member, {identifier: 'chatMention', title: `${user.profile.name} mentioned you in ${this.name}`, message}); + }); return newChatMessage; }; From e2781964bb176acbc1d826d7f3ac47f87af94634 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Tue, 1 Oct 2019 13:26:42 +0200 Subject: [PATCH 75/79] Fix lint error --- website/server/controllers/api-v3/auth.js | 2 -- website/server/controllers/api-v3/chat.js | 1 - 2 files changed, 3 deletions(-) diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index 6d14cc10ba..9d5d2a4977 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -308,8 +308,6 @@ api.resetPassword = { ]); await user.save(); - } else { - let user = await User.findOne({ 'auth.google.email': email }).exec(); } res.respond(200, {}, res.t('passwordReset')); diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index ba2312bae3..4d43368a68 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -20,7 +20,6 @@ import { getMatchesByWordArray } from '../../libs/stringUtils'; import bannedSlurs from '../../libs/bannedSlurs'; import apiError from '../../libs/apiError'; import {highlightMentions} from '../../libs/highlightMentions'; -import {sendNotification} from '../../libs/pushNotifications'; const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { return { email, canSend: true }; From 3a6c29688378d7c63590353fb6837a257391b67a Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 14 Oct 2019 16:20:52 +0200 Subject: [PATCH 76/79] Update schema.js --- website/server/models/user/schema.js | 1 - 1 file changed, 1 deletion(-) diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index b2eb337a0d..af67e08522 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -469,7 +469,6 @@ let schema = new Schema({ reverseChatOrder: {$type: Boolean, default: false}, background: String, displayInviteToPartyWhenPartyIs1: {$type: Boolean, default: true}, - searchableUsername: {$type: Boolean, default: false}, webhooks: {$type: Schema.Types.Mixed, default: () => { return {}; }}, From 4cccaf33e2a0bed5e7783339a53b48396e0dfe4f Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 14 Oct 2019 16:45:20 +0200 Subject: [PATCH 77/79] Fix failing test --- website/server/models/group.js | 43 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/website/server/models/group.js b/website/server/models/group.js index f577218a7a..d9b8be0bec 100644 --- a/website/server/models/group.js +++ b/website/server/models/group.js @@ -578,28 +578,29 @@ schema.methods.sendChat = function sendChat (options = {}) { if (this.type === 'party' && user) { sendChatPushNotifications(user, this, newChatMessage, mentions, translate); } - mentionedMembers.forEach((member) => { - if (member._id === user._id) return; - const pushNotifPrefs = member.preferences.pushNotifications; - if (this.type === 'party') { - if (pushNotifPrefs.mentionParty !== true) { - return; + if (mentionedMembers) { + mentionedMembers.forEach((member) => { + if (member._id === user._id) return; + const pushNotifPrefs = member.preferences.pushNotifications; + if (this.type === 'party') { + if (pushNotifPrefs.mentionParty !== true) { + return; + } + } else if (member.guilds && member.guilds.includes(this._id)) { + if (pushNotifPrefs.mentionJoinedGuild !== true) { + return; + } + } else { + if (this.privacy !== 'public') { + return; + } + if (pushNotifPrefs.mentionUnjoinedGuild !== true) { + return; + } } - } else if (member.guilds && member.guilds.includes(this._id)) { - if (pushNotifPrefs.mentionJoinedGuild !== true) { - return; - } - } else { - if (this.privacy !== 'public') { - return; - } - if (pushNotifPrefs.mentionUnjoinedGuild !== true) { - return; - } - } - sendPushNotification(member, {identifier: 'chatMention', title: `${user.profile.name} mentioned you in ${this.name}`, message}); - }); - + sendPushNotification(member, {identifier: 'chatMention', title: `${user.profile.name} mentioned you in ${this.name}`, message}); + }); + } return newChatMessage; }; From 0d9010572c8ad0437e75158fb33aec22b6383102 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Tue, 15 Oct 2019 12:48:51 +0200 Subject: [PATCH 78/79] Don't send push notification to users who aren't in the party --- website/server/models/group.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/server/models/group.js b/website/server/models/group.js index d9b8be0bec..4d4f6ed5bf 100644 --- a/website/server/models/group.js +++ b/website/server/models/group.js @@ -583,10 +583,10 @@ schema.methods.sendChat = function sendChat (options = {}) { if (member._id === user._id) return; const pushNotifPrefs = member.preferences.pushNotifications; if (this.type === 'party') { - if (pushNotifPrefs.mentionParty !== true) { + if (pushNotifPrefs.mentionParty !== true || !this.isMember(member)) { return; } - } else if (member.guilds && member.guilds.includes(this._id)) { + } else if (this.isMember(member)) { if (pushNotifPrefs.mentionJoinedGuild !== true) { return; } From 7cd59cef35cd0b300a87436650f33c4db1dd3690 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 16 Oct 2019 19:47:17 +0200 Subject: [PATCH 79/79] Remove tributejs from dependencies --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 952aa5c982..2db80df4b3 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,6 @@ "svg-url-loader": "^3.0.0", "svgo": "^1.2.0", "svgo-loader": "^2.1.0", - "tributejs": "^3.4.0", "universal-analytics": "^0.4.17", "update": "^0.7.4", "upgrade": "^1.1.0", @@ -108,7 +107,6 @@ "vue-mugen-scroll": "^0.2.1", "vue-router": "^3.0.0", "vue-style-loader": "^4.1.0", - "vue-tribute": "^1.0.1", "vue-template-compiler": "^2.6.10", "vuedraggable": "^2.20.0", "vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",