diff --git a/bin/cli-setup b/bin/cli-setup index 9ecdecc95..2e5c1e5b8 100755 --- a/bin/cli-setup +++ b/bin/cli-setup @@ -94,7 +94,7 @@ const performSetup = async () => { name: 'requireEmailConfirmation', default: settings.requireEmailConfirmation, message: 'Should emails always be confirmed' - } + }, ]); // Update the settings that were changed. @@ -104,6 +104,32 @@ const performSetup = async () => { } }); + answers = await inquirer.prompt([ + { + type: 'confirm', + name: 'inputWhitelistedDomains', + default: true, + message: 'Would you like to specify a whitelisted domain' + }, + { + type: 'input', + name: 'whitelistedDomain', + message: 'Whitelisted Domain', + when: ({inputWhitelistedDomains}) => inputWhitelistedDomains, + validate: (input) => { + if (input && input.length > 0) { + return true; + } + + return 'Whitelisted Domain cannot be empty.'; + } + } + ]); + + if (answers.inputWhitelistedDomains) { + settings.domains.whitelist = [answers.whitelistedDomain]; + } + console.log('\nWe\'ll ask you some questions about your first admin user.\n'); let user = await inquirer.prompt([ @@ -147,7 +173,11 @@ const performSetup = async () => { name: 'confirmPassword', message: 'Confirm Password', type: 'password', - filter: (confirmPassword) => { + filter: (confirmPassword, {password}) => { + if (password !== confirmPassword) { + return Promise.reject(new Error('Passwords do not match')); + } + return UsersService .isValidPassword(confirmPassword) .catch((err) => { @@ -157,10 +187,6 @@ const performSetup = async () => { }, ]); - if (user.password !== user.confirmPassword) { - return Promise.reject(new Error('Passwords do not match')); - } - let {user: newUser} = await SetupService.setup({ settings: settings.toObject(), user: { diff --git a/client/coral-admin/src/components/CommentType.css b/client/coral-admin/src/components/CommentType.css index b5dbc229b..e4851275e 100644 --- a/client/coral-admin/src/components/CommentType.css +++ b/client/coral-admin/src/components/CommentType.css @@ -3,11 +3,13 @@ color: white; background: grey; box-sizing: border-box; - padding: 2px 8px; + padding: 0px 5px; border-radius: 2px; font-size: 12px; - height: 28px; - + height: 24px; + letter-spacing: 0.4px; + margin-bottom: 1px; + > i { font-size: 14px; vertical-align: text-top; diff --git a/client/coral-admin/src/components/FlagBox.css b/client/coral-admin/src/components/FlagBox.css index 402a88045..232803203 100644 --- a/client/coral-admin/src/components/FlagBox.css +++ b/client/coral-admin/src/components/FlagBox.css @@ -1,6 +1,6 @@ .flagBox { border-top: 1px solid rgba(66, 66, 66, 0.12); - + margin-top: 10px; .container { padding: 0 14px; } diff --git a/client/coral-admin/src/components/ModerationList.css b/client/coral-admin/src/components/ModerationList.css index 89e43e02a..4ac894290 100644 --- a/client/coral-admin/src/components/ModerationList.css +++ b/client/coral-admin/src/components/ModerationList.css @@ -186,7 +186,6 @@ .actionButton { transform: scale(.8); margin: 0; - width: 140px; } .minimal { diff --git a/client/coral-admin/src/components/ui/Logo.css b/client/coral-admin/src/components/ui/Logo.css index af2758bcb..62a223683 100644 --- a/client/coral-admin/src/components/ui/Logo.css +++ b/client/coral-admin/src/components/ui/Logo.css @@ -10,16 +10,18 @@ .logo span { display: inline-block; margin-left: 10px; - font-size: 18px; + font-size: 26px; vertical-align: middle; font-weight: 500; + color: white; } .logo { - background: #E5E5E5; + background: #696969; height: 100%; width: 128px; z-index: 10; + border-right: 1px #757575 solid; } .base { diff --git a/client/coral-admin/src/routes/Moderation/components/CommentCount.css b/client/coral-admin/src/routes/Moderation/components/CommentCount.css index 4d24d5702..998133d07 100644 --- a/client/coral-admin/src/routes/Moderation/components/CommentCount.css +++ b/client/coral-admin/src/routes/Moderation/components/CommentCount.css @@ -1,16 +1,16 @@ .count { display: inline-block; - background: #989797; + background: #616161; margin: 2px; vertical-align: middle; - padding: 1px 7px; + padding: 1px 5px; border-radius: 2px; margin-left: 2px; - line-height: 20px; + line-height: 18px; box-sizing: border-box; - height: 21px; + height: 18px; right: 0; - margin-top: -2px; + margin-top: 0px; font-size: 12px; color: white; } diff --git a/client/coral-admin/src/routes/Moderation/components/styles.css b/client/coral-admin/src/routes/Moderation/components/styles.css index 72c5e4d63..061e5351d 100644 --- a/client/coral-admin/src/routes/Moderation/components/styles.css +++ b/client/coral-admin/src/routes/Moderation/components/styles.css @@ -18,7 +18,7 @@ .tab { flex: 1; - color: #C0C0C0; + color: #BDBDBD; text-transform: capitalize; font-weight: 100; font-size: 14px; @@ -29,7 +29,7 @@ margin-right: 20px; &:hover { color: white; - border-bottom: solid 2px #F36451; + /*border-bottom: solid 2px #F36451;*/ box-sizing: border-box; } } @@ -111,7 +111,7 @@ span { color: white; text-transform: capitalize; font-weight: 400; - font-size: 15px; + font-size: 20px; letter-spacing: 1px; transition: background-color 200ms; opacity: 1; @@ -173,7 +173,7 @@ span { border-bottom: 1px solid #e0e0e0; font-size: 18px; width: 100%; - max-width: 700px; + max-width: 650px; min-width: 400px; margin: 0 auto; position: relative; @@ -470,7 +470,7 @@ span { .searchTrigger { position: relative; - top: .3em; + top: .2em; } .adminCommentInfoBar { diff --git a/client/coral-ui/components/Button.css b/client/coral-ui/components/Button.css index 7bd1d4379..1b7efb205 100644 --- a/client/coral-ui/components/Button.css +++ b/client/coral-ui/components/Button.css @@ -27,9 +27,10 @@ } .icon { - margin-right: 13px; + margin-right: 5px; font-size: 18px; vertical-align: middle; + margin-top: -3px; } .type--black { @@ -143,7 +144,7 @@ border-radius: 3px; text-transform: capitalize; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09); - width: 128px; + width: 129px; &:hover { box-shadow: none; @@ -166,7 +167,7 @@ border-radius: 3px; text-transform: capitalize; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.03), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.09); - width: 128px; + width: 129px; &:hover { color: white; diff --git a/config.js b/config.js index 4472af26e..4a3609dc8 100644 --- a/config.js +++ b/config.js @@ -7,6 +7,8 @@ // entrypoint for the entire applications configuration. require('env-rewrite').rewrite(); +const uniq = require('lodash/uniq'); + //============================================================================== // CONFIG INITIALIZATION //============================================================================== @@ -31,6 +33,13 @@ const CONFIG = { // token. JWT_COOKIE_NAME: process.env.TALK_JWT_COOKIE_NAME || 'authorization', + // JWT_SIGNING_COOKIE_NAME will be the cookie set when cookies are issued. + // This defaults to the TALK_JWT_COOKIE_NAME value. + JWT_SIGNING_COOKIE_NAME: process.env.TALK_JWT_SIGNING_COOKIE_NAME || process.env.TALK_JWT_COOKIE_NAME || 'authorization', + + // JWT_COOKIE_NAMES declares the many cookie names used for verification. + JWT_COOKIE_NAMES: process.env.TALK_JWT_COOKIE_NAMES || null, + // JWT_CLEAR_COOKIE_LOGOUT specifies whether the named cookie should be // cleared when the user is logged out. JWT_CLEAR_COOKIE_LOGOUT: process.env.TALK_JWT_CLEAR_COOKIE_LOGOUT ? process.env.TALK_JWT_CLEAR_COOKIE_LOGOUT !== 'FALSE' : true, @@ -165,6 +174,16 @@ if (CONFIG.JWT_DISABLE_ISSUER) { CONFIG.JWT_ISSUER = undefined; } +// Parse and handle cookie names. +if (CONFIG.JWT_COOKIE_NAMES) { + CONFIG.JWT_COOKIE_NAMES = CONFIG.JWT_COOKIE_NAMES.split(','); +} else { + CONFIG.JWT_COOKIE_NAMES = []; +} + +// Add in the default cookie names and strip duplicates. +CONFIG.JWT_COOKIE_NAMES = uniq(CONFIG.JWT_COOKIE_NAMES.concat([CONFIG.JWT_COOKIE_NAME, CONFIG.JWT_SIGNING_COOKIE_NAME])); + //------------------------------------------------------------------------------ // External database url's //------------------------------------------------------------------------------ diff --git a/docs/_docs/02-01-configuration.md b/docs/_docs/02-01-configuration.md index 74bd8972e..18a483723 100644 --- a/docs/_docs/02-01-configuration.md +++ b/docs/_docs/02-01-configuration.md @@ -87,8 +87,16 @@ on the contents of those variables.** These are advanced settings for fine tuning the auth integration, and is not needed in most situations. -- `TALK_JWT_COOKIE_NAME` (_optional_) - the name of the cookie to extract the - JWT from (Default `authorization`) +- `TALK_JWT_COOKIE_NAME` (_optional_) - the default cookie name to check for a + valid JWT token to use for verifying a user. (Default `authorization`) +- `TALK_JWT_SIGNING_COOKIE_NAME` (_optional_) - the default cookie name that is + use to set a cookie containing a JWT that was issued by Talk. + (Default `process.env.TALK_JWT_COOKIE_NAME`) +- `TALK_JWT_COOKIE_NAMES` (_optional_) - the different cookie names to check for + a JWT token in, seperated by `,`. By default, we always use the + `process.env.TALK_JWT_COOKIE_NAME` and `process.env.TALK_JWT_SIGNING_COOKIE_NAME` + for this value. Any additional cookie names specified here will be appended to + the list of cookie names to inspect. - `TALK_JWT_CLEAR_COOKIE_LOGOUT` (_optional_) - when `FALSE`, Talk will not clear the cookie with name `TALK_JWT_COOKIE_NAME` when logging out (Default `TRUE`) @@ -115,6 +123,14 @@ will be used: } ``` +When our passport middleware checks for JWT tokens, it searches in the following +order: + +1. Custom cookies named from the list in `TALK_JWT_COOKIE_NAMES`. +2. Default cookies named `TALK_JWT_COOKIE_NAME` then `TALK_JWT_SIGNING_COOKIE_NAME`. +3. Query parameter `?access_token={TOKEN}`. +4. Header: `Authorization: Bearer {TOKEN}`. + ### Email - `TALK_SMTP_EMAIL` (*required for email*) - the address to send emails from diff --git a/package.json b/package.json index 476e7eda5..bb0a724ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "3.0.0", + "version": "3.1.0", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "scripts": { @@ -93,7 +93,7 @@ "graphql-tools": "^0.10.1", "helmet": "^3.5.0", "immutability-helper": "^2.2.0", - "inquirer": "^3.0.6", + "inquirer": "^3.2.1", "joi": "^10.4.1", "jsonwebtoken": "^7.3.0", "jwt-decode": "^2.2.0", diff --git a/plugins/talk-plugin-featured-comments/client/components/ModTag.css b/plugins/talk-plugin-featured-comments/client/components/ModTag.css index c8ba1b6ba..683c16570 100644 --- a/plugins/talk-plugin-featured-comments/client/components/ModTag.css +++ b/plugins/talk-plugin-featured-comments/client/components/ModTag.css @@ -4,13 +4,14 @@ color: #696969; background-color: white; box-sizing: border-box; - padding: 2px 8px; + padding: 0px 5px; border-radius: 2px; font-size: 12px; - height: 28px; + height: 24px; transition: background-color .2s cubic-bezier(.4,0,.2,1), color .2s cubic-bezier(.4,0,.2,1), border-color .2s cubic-bezier(.4,0,.2,1); margin: 2px 0px; letter-spacing: 0.4px; + } .tag:hover { @@ -39,4 +40,3 @@ font-size: 15px; vertical-align: text-bottom; } - \ No newline at end of file diff --git a/services/passport.js b/services/passport.js index 409bb2279..14a2134ce 100644 --- a/services/passport.js +++ b/services/passport.js @@ -23,7 +23,8 @@ const { JWT_ALG, RECAPTCHA_SECRET, RECAPTCHA_ENABLED, - JWT_COOKIE_NAME, + JWT_SIGNING_COOKIE_NAME, + JWT_COOKIE_NAMES, JWT_CLEAR_COOKIE_LOGOUT, JWT_USER_ID_CLAIM, } = require('../config'); @@ -53,7 +54,7 @@ const GenerateToken = (user) => { const SetTokenForSafari = (req, res, token) => { const browser = bowser._detect(req.headers['user-agent']); if (browser.ios || browser.safari) { - res.cookie(JWT_COOKIE_NAME, token, { + res.cookie(JWT_SIGNING_COOKIE_NAME, token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', expires: new Date(Date.now() + ms(JWT_EXPIRY)) @@ -169,7 +170,7 @@ const HandleLogout = (req, res, next) => { // Only clear the cookie on logout if enabled. if (JWT_CLEAR_COOKIE_LOGOUT) { - res.clearCookie(JWT_COOKIE_NAME); + res.clearCookie(JWT_SIGNING_COOKIE_NAME); } res.status(204).end(); @@ -209,14 +210,20 @@ const CheckBlacklisted = async (jwt) => { const JwtStrategy = require('passport-jwt').Strategy; const ExtractJwt = require('passport-jwt').ExtractJwt; -let cookieExtractor = function(req) { - let token = null; - +let cookieExtractor = (req) => { if (req && req.cookies) { - token = req.cookies[JWT_COOKIE_NAME]; + + // Walk over all the cookie names in JWT_COOKIE_NAMES. + for (const cookieName of JWT_COOKIE_NAMES) { + + // Check to see if that cookie is set. + if (cookieName in req.cookies && req.cookies[cookieName] !== null && req.cookies[cookieName].length > 0) { + return req.cookies[cookieName]; + } + } } - return token; + return null; }; // Override the JwtVerifier method on the JwtStrategy so we can pack the diff --git a/services/tags.js b/services/tags.js index fbe6b58ec..b0d0c4b96 100644 --- a/services/tags.js +++ b/services/tags.js @@ -205,8 +205,8 @@ class TagsService { return updateModel(item_type, query, { $pull: { tags: { - name: link.tag.name - } + 'tag.name': link.tag.name, + }, } }); } diff --git a/test/server/services/tags.js b/test/server/services/tags.js index 7cdad829e..1080563f0 100644 --- a/test/server/services/tags.js +++ b/test/server/services/tags.js @@ -27,7 +27,7 @@ describe('services.TagsService', () => { const id = comment.id; const name = 'BEST'; const assigned_by = user.id; - + await TagsService.add(id, 'COMMENTS', { tag: { name @@ -45,7 +45,7 @@ describe('services.TagsService', () => { const id = comment.id; const name = 'BEST'; const assigned_by = user.id; - + await TagsService.add(id, 'COMMENTS', { tag: { name @@ -103,5 +103,43 @@ describe('services.TagsService', () => { expect(tags.length).to.equal(0); } }); + it('removes a tag out of 2', async () => { + const id = comment.id; + const name = 'BEST'; + const assigned_by = user.id; + + await TagsService.add(id, 'COMMENTS', { + tag: { + name: 'ANOTHER' + }, + assigned_by + }); + + await TagsService.add(id, 'COMMENTS', { + tag: { + name + }, + assigned_by + }); + + { + const {tags} = await CommentsService.findById(id); + expect(tags.length).to.equal(2); + } + + // ok now to remove it + await TagsService.remove(id, 'COMMENTS', { + tag: { + name + }, + assigned_by + }); + + { + const {tags} = await CommentsService.findById(id); + expect(tags.length).to.equal(1); + expect(tags[0].tag.name).to.equal('ANOTHER'); + } + }); }); }); diff --git a/yarn.lock b/yarn.lock index 255dc7415..a5d73a756 100644 --- a/yarn.lock +++ b/yarn.lock @@ -162,6 +162,10 @@ ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" + ansi-regex@^1.0.0, ansi-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-1.1.1.tgz#41c847194646375e6a1a5d10c3ca054ef9fc980d" @@ -170,10 +174,20 @@ ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + any-promise@^0.1.0, any-promise@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-0.1.0.tgz#830b680aa7e56f33451d4b049f3bd8044498ee27" @@ -1498,6 +1512,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + change-emitter@^0.1.2: version "0.1.6" resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" @@ -1727,7 +1749,7 @@ codemirror@*: version "5.25.2" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.25.2.tgz#8c77677ca9c9248d757d3a07ed1e89a8404850b7" -color-convert@^1.3.0: +color-convert@^1.3.0, color-convert@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" dependencies: @@ -3053,10 +3075,12 @@ extend@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8" -external-editor@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" tmp "^0.0.31" extglob@^0.3.1: @@ -3757,6 +3781,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -3972,6 +4000,10 @@ iconv-lite@0.4.15, iconv-lite@^0.4.5, iconv-lite@~0.4.13: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" +iconv-lite@^0.4.17: + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" + icss-replace-symbols@1.0.2, icss-replace-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5" @@ -4103,22 +4135,23 @@ inquirer@0.8.2: rx "^2.4.3" through "^2.3.6" -inquirer@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" +inquirer@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175" dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" + ansi-escapes "^2.0.0" + chalk "^2.0.0" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^2.0.1" + external-editor "^2.0.4" figures "^2.0.0" lodash "^4.3.0" mute-stream "0.0.7" run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" through "^2.3.6" interpret@^1.0.0: @@ -4560,6 +4593,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.1.tgz#c519f629f86b3a5bedba58a88d311309eec097f9" + jsdom@^7.0.2: version "7.2.2" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" @@ -7434,6 +7471,16 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" @@ -7442,10 +7489,6 @@ rx@^2.4.3: version "2.5.3" resolved "https://registry.yarnpkg.com/rx/-/rx-2.5.3.tgz#21adc7d80f02002af50dae97fd9dbf248755f566" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - safe-buffer@^5.0.1, safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" @@ -7833,6 +7876,13 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^3.0.0" +string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string.prototype.codepointat@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz#6b26e9bd3afcaa7be3b4269b526de1b82000ac78" @@ -7871,6 +7921,12 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -7961,6 +8017,12 @@ supports-color@^3.1.2, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" + dependencies: + has-flag "^2.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"