1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 03:12:42 +02:00

Right-to-left CSS (using module for conversion) (#7072)

* Create RTL stylesheets using `gulp-rtl`

* Handle RTL stylesheet special cases

Certain blocks of Sass  were set to bypass "rtlcss" using ignore
comments. Certain icons had to be flipped 180 degrees.

* Switch stylesheets when locale changes

A second stylesheet has been added to each HTML page for use with
right-to-left locales. It is disabled by default. It is enabled on
startup if a RTL locale is set, and when switching to a RTL locale.
Similarly the LTR stylesheet is disabled when a RTL locale is used.

Unfortunately there is an unpleasant flash of unstyled content when
switching between a LTR and a RTL locale. There is also a slightly
longer page load time when using a RTL locale (<1s difference). We
couldn't think of an easy way to avoid these problems.

* Set `dir="auto"` as default on `TextFields`
This commit is contained in:
Nick Doiron 2019-09-03 10:47:54 -07:00 committed by Mark Stacey
parent 361a19a850
commit d589d2dec0
36 changed files with 268 additions and 14 deletions

View File

@ -4,7 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<title>MetaMask</title>
<link rel="stylesheet" type="text/css" href="./index.css">
<link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head>
<body>
<div id="app-content"></div>

View File

@ -28,7 +28,8 @@
margin-top: 1rem;
}
</style>
<link rel="stylesheet" type="text/css" href="./index.css">
<link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head>
<body class="notification" style="height:600px;">
<div id="app-content">

View File

@ -4,7 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
<title>MetaMask</title>
<link rel="stylesheet" type="text/css" href="./index.css">
<link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>
</head>
<body style="width:357px; height:600px;">
<div id="app-content"></div>

View File

@ -211,7 +211,12 @@ class PreferencesController {
*
*/
setCurrentLocale (key) {
this.store.updateState({ currentLocale: key })
const textDirection = (['ar', 'dv', 'fa', 'he', 'ku'].includes(key)) ? 'rtl' : 'auto'
this.store.updateState({
currentLocale: key,
textDirection: textDirection,
})
return textDirection
}
/**

View File

@ -1723,8 +1723,8 @@ module.exports = class MetamaskController extends EventEmitter {
*/
setCurrentLocale (key, cb) {
try {
this.preferencesController.setCurrentLocale(key)
cb(null)
const direction = this.preferencesController.setCurrentLocale(key)
cb(null, direction)
} catch (err) {
cb(err)
}

View File

@ -19,6 +19,8 @@ const gulpStylelint = require('gulp-stylelint')
const stylefmt = require('gulp-stylefmt')
const uglify = require('gulp-uglify-es').default
const pify = require('pify')
const rtlcss = require('gulp-rtlcss')
const rename = require('gulp-rename')
const gulpMultiProcess = require('gulp-multi-process')
const endOfStream = pify(require('end-of-stream'))
@ -274,6 +276,10 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sourcemaps.write())
.pipe(autoprefixer())
.pipe(gulp.dest(dest))
.pipe(rtlcss())
.pipe(rename({ suffix: '-rtl' }))
.pipe(sourcemaps.write())
.pipe(gulp.dest(dest))
}
function buildScss () {
@ -281,6 +287,9 @@ function createScssBuildTask ({ src, dest, devMode, pattern }) {
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(gulp.dest(dest))
.pipe(rtlcss())
.pipe(rename({ suffix: '-rtl' }))
.pipe(gulp.dest(dest))
}
}

View File

@ -218,7 +218,9 @@
"gulp-json-editor": "^2.2.1",
"gulp-livereload": "4.0.0",
"gulp-multi-process": "^1.3.1",
"gulp-rename": "^1.4.0",
"gulp-replace": "^0.6.1",
"gulp-rtlcss": "^1.4.0",
"gulp-sass": "^4.0.0",
"gulp-sourcemaps": "^2.6.0",
"gulp-stylefmt": "^1.1.0",

View File

@ -15,6 +15,10 @@
display: flex;
justify-content: center;
align-items: center;
[dir='rtl'] & img {
transform: rotate(180deg);
}
}
&__back-button {

View File

@ -47,6 +47,8 @@
}
&__input {
/*rtl:ignore*/
direction: ltr;
border: 1px solid $dusty-gray;
border-radius: 4px;
color: $mid-gray;
@ -69,6 +71,7 @@
&__input-arrows {
position: absolute;
top: 7px;
/*rtl:ignore*/
right: 0px;
width: 17px;
height: 24px;

View File

@ -36,6 +36,8 @@
}
&__time-remaining {
/*rtl:ignore*/
direction: ltr;
color: #313A5E;
font-size: 16px;
@ -137,6 +139,8 @@
}
&__input {
/*rtl:ignore*/
direction: ltr;
border: 1px solid $dusty-gray;
border-radius: 4px;
color: $mid-gray;
@ -159,6 +163,7 @@
&__input-arrows {
position: absolute;
top: 7px;
/*rtl:ignore*/
right: 0px;
width: 17px;
height: 24px;

View File

@ -3,10 +3,11 @@
align-items: center;
&__text {
/*rtl:ignore*/
direction: ltr;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__suffix {

View File

@ -37,6 +37,7 @@ class EditableLabel extends Component {
h('input.large-input.editable-label__input', {
type: 'text',
required: true,
dir: 'auto',
value: this.state.value,
onKeyPress: (event) => {
if (event.key === 'Enter') {

View File

@ -1,4 +1,6 @@
.identicon {
/*rtl:ignore*/
direction: ltr;
display: flex;
flex-shrink: 0;
align-items: center;

View File

@ -50,6 +50,10 @@
display: flex;
align-items: center;
justify-content: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
&__arrow-circle {
@ -70,6 +74,19 @@
text-overflow: ellipsis;
white-space: nowrap;
font-size: .875rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
}
}
}
@ -102,12 +119,29 @@
text-overflow: ellipsis;
white-space: nowrap;
font-size: .5rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
}
&__arrow-container {
display: flex;
justify-content: center;
align-items: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}
}
@ -137,12 +171,29 @@
text-overflow: ellipsis;
white-space: nowrap;
font-size: .6875rem;
[dir='rtl'] & {
/*rtl:ignore*/
direction: ltr;
/*rtl:ignore*/
text-align: right;
span {
display: block;
/*rtl:ignore*/
direction: rtl;
}
}
}
&__arrow-container {
display: flex;
justify-content: center;
align-items: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}
}

View File

@ -66,7 +66,8 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ senderAddressCopied: false })}
>
<div className="sender-to-recipient__name">
{ addressOnly ? `${t('from')}: ${checksummedSenderAddress}` : senderName }
<span>{ addressOnly ? `${t('from')}: ` : '' }</span>
{ addressOnly ? checksummedSenderAddress : senderName }
</div>
</Tooltip>
)
@ -112,9 +113,10 @@ export default class SenderToRecipient extends PureComponent {
onHidden={() => this.setState({ recipientAddressCopied: false })}
>
<div className="sender-to-recipient__name">
<span>{ addressOnly ? `${t('to')}: ` : '' }</span>
{
addressOnly
? `${t('to')}: ${checksummedRecipientAddress}`
? checksummedRecipientAddress
: (recipientNickname || recipientName || this.context.t('newContract'))
}
</div>

View File

@ -67,7 +67,7 @@ const styles = {
}
const TextField = props => {
const { error, classes, material, startAdornment, largeLabel, ...textFieldProps } = props
const { error, classes, material, startAdornment, largeLabel, dir, ...textFieldProps } = props
return (
<MaterialTextField
@ -91,6 +91,9 @@ const TextField = props => {
underline: material ? classes.materialUnderline : '',
focused: material ? '' : classes.inputFocused,
},
inputProps: {
dir,
},
}}
{...textFieldProps}
/>
@ -99,11 +102,13 @@ const TextField = props => {
TextField.defaultProps = {
error: null,
dir: 'auto',
}
TextField.propTypes = {
error: PropTypes.string,
classes: PropTypes.object,
dir: PropTypes.string,
material: PropTypes.bool,
startAdornment: PropTypes.element,
largeLabel: PropTypes.bool,

View File

@ -84,6 +84,7 @@ export default class UnitInput extends PureComponent {
<div className="unit-input__input-container">
<input
type="number"
dir="ltr"
className={classnames('unit-input__input', { 'unit-input__disabled': maxModeOn })}
value={value}
placeholder={placeholder}

View File

@ -18,6 +18,8 @@
}
.qr-ellip-address, .ellip-address {
/*rtl:ignore*/
direction: ltr;
width: 247px;
border: none;
font-family: Roboto;

View File

@ -57,6 +57,13 @@ $wallet-view-bg: $alabaster;
z-index: 200;
position: relative;
[dir='rtl'] & i.fa.fa-clipboard {
/*rtl:ignore*/
margin-left: 0 !important;
/*rtl:ignore*/
margin-right: 8px !important;
}
@media screen and (min-width: 576px) {
overflow-y: scroll;
overflow-x: hidden;
@ -103,6 +110,11 @@ $wallet-view-bg: $alabaster;
box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px;
width: 85%;
height: calc(100% - 56px);
[dir='rtl'] & {
/* rtl:ignore */
left: 15%;
}
}
// main-container media queries

View File

@ -414,6 +414,8 @@ textarea.twelve-word-phrase {
}
.qr-ellip-address, .ellip-address {
/*rtl:ignore*/
direction: ltr;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -62,6 +62,10 @@
background-size: contain;
background-repeat: no-repeat;
background-position: center;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}

View File

@ -0,0 +1,30 @@
/**
* Switch the CSS stylesheet used between 'rtl' and 'ltr'
* @param {('ltr' | 'rtl')} direction Text direction, either left-to-right (ltr) or right-to-left (rtl)
*/
const switchDirection = async (direction) => {
if (direction === 'auto') {
direction = 'ltr'
}
let updatedLink
Array.from(document.getElementsByTagName('link'))
.filter(link => link.rel === 'stylesheet')
.forEach(link => {
if (link.title === direction && link.disabled) {
link.disabled = false
updatedLink = link
} else if (link.title !== direction && !link.disabled) {
link.disabled = true
}
})
if (updatedLink) {
return new Promise((resolve, reject) => {
updatedLink.onload = () => {
resolve()
}
updatedLink.onerror = () => reject(new Error(`Failed to load '${direction}' stylesheet`))
})
}
}
export default switchDirection

View File

@ -58,6 +58,8 @@
}
&__token-name {
/*rtl:ignore*/
direction: ltr;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View File

@ -73,6 +73,8 @@
}
&__textarea {
/*rtl:ignore*/
direction: ltr;
font-size: 1rem;
font-family: Roboto;
height: 190px;

View File

@ -64,6 +64,8 @@
}
&__selected-seed-words {
/*rtl:ignore*/
direction: ltr;
display: flex;
flex-flow: row wrap;
min-height: 161px;

View File

@ -170,6 +170,7 @@ class Routes extends Component {
const {
isLoading,
alertMessage,
textDirection,
loadingMessage,
network,
provider,
@ -208,6 +209,7 @@ class Routes extends Component {
return (
<div
className={classnames('app', { 'mouse-user-styles': isMouseUser})}
dir={textDirection}
onClick={() => setMouseUserState(true)}
onKeyDown={e => {
if (e.keyCode === 9) {
@ -323,6 +325,7 @@ Routes.propTypes = {
isLoading: PropTypes.bool,
loadingMessage: PropTypes.string,
alertMessage: PropTypes.string,
textDirection: PropTypes.string,
network: PropTypes.string,
provider: PropTypes.object,
frequentRpcListDetail: PropTypes.array,
@ -360,6 +363,7 @@ function mapStateToProps (state) {
sidebar,
alertOpen,
alertMessage,
textDirection: state.metamask.textDirection,
isLoading,
loadingMessage,
isUnlocked: state.metamask.isUnlocked,

View File

@ -155,6 +155,7 @@ export default class EnsInput extends Component {
<input
className="ens-input__wrapper__input"
type="text"
dir="auto"
placeholder={t('recipientAddressPlaceholder')}
onChange={this.onChange}
onPaste={this.onPaste}

View File

@ -60,6 +60,10 @@
width: 18px;
height: 18px;
margin-right: .5rem;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}

View File

@ -99,6 +99,7 @@ ToAutoComplete.prototype.render = function () {
h(`input.send-v2__to-autocomplete__input${qrScanner ? '.with-qr' : ''}`, {
placeholder: this.context.t('recipientAddress'),
className: inError ? `send-v2__error-border` : '',
dir: 'auto',
value: to,
onChange: event => onChange(event.target.value),
onFocus: event => this.handleInputEvent(event),

View File

@ -197,6 +197,10 @@
width: 30px;
opacity: .5;
background-repeat: no-repeat;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}
}

View File

@ -97,6 +97,10 @@
background-position: center;
margin-right: 16px;
cursor: pointer;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}
@ -244,4 +248,12 @@
}
}
}
.toggle-button {
/*rtl:ignore*/
direction: ltr;
[dir='rtl'] & {
justify-content: flex-end;
}
}
}

View File

@ -38,6 +38,10 @@
cursor: pointer;
position: absolute;
margin-left: 10px;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}
@ -190,6 +194,10 @@
position: absolute;
width: 24px;
height: 24px;
[dir='rtl'] & {
transform: rotate(180deg);
}
}
}

View File

@ -10,6 +10,7 @@ const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../helpers/utils/i18n-helper')
const { getMethodDataAsync } = require('../helpers/utils/transactions.util')
const { fetchSymbolAndDecimals } = require('../helpers/utils/token-util')
import switchDirection from '../helpers/utils/switch-direction'
const log = require('loglevel')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enums')
const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util')
@ -2597,11 +2598,13 @@ function updateCurrentLocale (key) {
return fetchLocale(key)
.then((localeMessages) => {
log.debug(`background.setCurrentLocale`)
background.setCurrentLocale(key, (err) => {
dispatch(actions.hideLoadingIndication())
background.setCurrentLocale(key, (err, textDirection) => {
if (err) {
dispatch(actions.hideLoadingIndication())
return dispatch(actions.displayWarning(err.message))
}
switchDirection(textDirection)
dispatch(actions.hideLoadingIndication())
dispatch(actions.setCurrentLocale(key))
dispatch(actions.setLocaleMessages(localeMessages))
})

View File

@ -12,6 +12,7 @@
<!-- design reference -->
<link rel="stylesheet" type="text/css" href="./app/css/debug.css">
<link rel="stylesheet" type="text/css" href="./app/css/debug-rtl.css" disabled="true">
<div id="design-container">
<img id="design-img" src="./design/metamask_wfs_jan_13.png">
</div>

View File

@ -5,6 +5,7 @@ const actions = require('./app/store/actions')
const configureStore = require('./app/store/store')
const txHelper = require('./lib/tx-helper')
const { fetchLocale } = require('./app/helpers/utils/i18n-helper')
import switchDirection from './app/helpers/utils/switch-direction'
const log = require('loglevel')
module.exports = launchMetamaskUi
@ -33,6 +34,10 @@ async function startApp (metamaskState, backgroundConnection, opts) {
: {}
const enLocaleMessages = await fetchLocale('en')
if (metamaskState.textDirection === 'rtl') {
await switchDirection('rtl')
}
const store = configureStore({
activeTab: opts.activeTab,

View File

@ -5728,6 +5728,11 @@ colors@^1.1.0, colors@^1.1.2:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
colors@~0.6.0-1:
version "0.6.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc"
integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=
columnify@1.5.4:
version "1.5.4"
resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
@ -5806,6 +5811,11 @@ commander@^2.8.1, commander@~2.8.1:
dependencies:
graceful-readlink ">= 1.0.0"
commander@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781"
integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=
commander@~2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
@ -9851,6 +9861,14 @@ findup-sync@^3.0.0:
micromatch "^3.0.4"
resolve-dir "^1.0.1"
findup@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb"
integrity sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=
dependencies:
colors "~0.6.0-1"
commander "~2.1.0"
fined@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
@ -11039,6 +11057,11 @@ gulp-multi-process@^1.3.1:
dependencies:
async.queue "^0.5.2"
gulp-rename@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd"
integrity sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==
gulp-replace@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066"
@ -11048,6 +11071,16 @@ gulp-replace@^0.6.1:
readable-stream "^2.0.1"
replacestream "^4.0.0"
gulp-rtlcss@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-rtlcss/-/gulp-rtlcss-1.4.0.tgz#a1e4caef39182af03778cb9c18add9d3ee5e1c97"
integrity sha512-66UmUSacTzdV3L0KcsdwzExEu1+dTfNlq3emUZGgHPLgUaCrsZUgZwjsgKjPwkYJUZOucLpjOxAkB37k+H80Kw==
dependencies:
plugin-error "^1.0.1"
rtlcss "^2.4.0"
through2 "^2.0.5"
vinyl-sourcemaps-apply "^0.2.1"
gulp-sass@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9"
@ -16768,6 +16801,15 @@ postcss@^6.0.1, postcss@^6.0.19:
source-map "^0.6.1"
supports-color "^5.2.0"
postcss@^6.0.14:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
dependencies:
chalk "^2.4.1"
source-map "^0.6.1"
supports-color "^5.4.0"
postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.17"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f"
@ -18010,7 +18052,7 @@ readable-stream@1.1, readable-stream@1.1.x, "readable-stream@>=1.1.13-1 <1.2.0-0
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6:
readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@ -18883,6 +18925,17 @@ rtcpeerconnection-shim@^1.2.10:
dependencies:
sdp "^2.6.0"
rtlcss@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.4.0.tgz#482ea28f2b9fe06dd0ab3057997be9af13da84c1"
integrity sha512-hdjFhZ5FCI0ABOfyXOMOhBtwPWtANLCG7rOiOcRf+yi5eDdxmDjqBruWouEnwVdzfh/TWF6NNncIEsigOCFZOA==
dependencies:
chalk "^2.3.0"
findup "^0.1.5"
mkdirp "^0.5.1"
postcss "^6.0.14"
strip-json-comments "^2.0.0"
run-async@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
@ -20573,7 +20626,7 @@ strip-json-comments@1.0.x:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=
strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@ -21276,6 +21329,14 @@ through2@^1.1.1:
readable-stream ">=1.1.13-1 <1.2.0-0"
xtend ">=4.0.0 <4.1.0-0"
through2@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
dependencies:
readable-stream "~2.3.6"
xtend "~4.0.1"
through2@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"