diff options
71 files changed, 1956 insertions, 997 deletions
diff --git a/Gemfile b/Gemfile index 55c1de693..c97f80bde 100644 --- a/Gemfile +++ b/Gemfile @@ -35,6 +35,7 @@ gem 'devise-two-factor' gem 'doorkeeper' gem 'rabl' gem 'rqrcode' +gem 'twitter-text' gem 'oj' gem 'hiredis' gem 'redis', '~>3.2' diff --git a/Gemfile.lock b/Gemfile.lock index f50edaf95..8ab50773f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -73,9 +73,10 @@ GEM rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - browserify-rails (3.1.0) + browserify-rails (4.1.0) + addressable (>= 2.4.0) railties (>= 4.0.0, < 5.1) - sprockets (>= 3.5.2) + sprockets (>= 3.6.0) builder (3.2.3) bullet (5.3.0) activesupport (>= 3.0.0) @@ -111,7 +112,7 @@ GEM coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.10.0) + coffee-script-source (1.12.2) colorize (0.8.1) concurrent-ruby (1.0.4) connection_pool (2.2.1) @@ -184,7 +185,7 @@ GEM http_parser.rb (0.6.0) httplog (0.3.2) colorize - i18n (0.7.0) + i18n (0.8.1) i18n-tasks (0.9.6) activesupport (>= 4.0.2) ast (>= 2.1.0) @@ -313,7 +314,7 @@ GEM rake (12.0.0) rdoc (4.2.2) json (~> 1.4) - react-rails (1.8.2) + react-rails (1.10.0) babel-transpiler (>= 0.7.0) coffee-script-source (~> 1.8) connection_pool @@ -419,9 +420,11 @@ GEM unicode-display_width (~> 1.1) thor (0.19.4) thread (0.2.2) - thread_safe (0.3.5) - tilt (2.0.5) + thread_safe (0.3.6) + tilt (2.0.6) tins (1.12.0) + twitter-text (1.14.5) + unf (~> 0.1.0) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (3.0.1) @@ -514,6 +517,7 @@ DEPENDENCIES simple_form simplecov statsd-instrument + twitter-text uglifier (>= 1.3.0) webmock will_paginate diff --git a/app/assets/javascripts/components/actions/accounts.jsx b/app/assets/javascripts/components/actions/accounts.jsx index 0be05034e..47c0d9f85 100644 --- a/app/assets/javascripts/components/actions/accounts.jsx +++ b/app/assets/javascripts/components/actions/accounts.jsx @@ -138,7 +138,8 @@ export function fetchAccountFail(id, error) { return { type: ACCOUNT_FETCH_FAIL, id, - error + error, + skipAlert: true }; }; @@ -231,7 +232,8 @@ export function fetchAccountTimelineFail(id, error, skipLoading) { type: ACCOUNT_TIMELINE_FETCH_FAIL, id, error, - skipLoading + skipLoading, + skipAlert: error.response.status === 404 }; }; diff --git a/app/assets/javascripts/components/actions/cards.jsx b/app/assets/javascripts/components/actions/cards.jsx index cc7baf376..d4c1eda60 100644 --- a/app/assets/javascripts/components/actions/cards.jsx +++ b/app/assets/javascripts/components/actions/cards.jsx @@ -46,6 +46,7 @@ export function fetchStatusCardFail(id, error) { type: STATUS_CARD_FETCH_FAIL, id, error, - skipLoading: true + skipLoading: true, + skipAlert: true }; }; diff --git a/app/assets/javascripts/components/actions/compose.jsx b/app/assets/javascripts/components/actions/compose.jsx index 03aae885e..8d030fd30 100644 --- a/app/assets/javascripts/components/actions/compose.jsx +++ b/app/assets/javascripts/components/actions/compose.jsx @@ -85,6 +85,7 @@ export function submitCompose() { dispatch(updateTimeline('home', { ...response.data })); if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { + dispatch(updateTimeline('community', { ...response.data })); dispatch(updateTimeline('public', { ...response.data })); } }).catch(function (error) { diff --git a/app/assets/javascripts/components/actions/notifications.jsx b/app/assets/javascripts/components/actions/notifications.jsx index df82e73fc..980b7d63e 100644 --- a/app/assets/javascripts/components/actions/notifications.jsx +++ b/app/assets/javascripts/components/actions/notifications.jsx @@ -14,7 +14,8 @@ export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST'; export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS'; export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'; -export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; +export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; +export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'; const fetchRelatedRelationships = (dispatch, notifications) => { const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id); @@ -151,3 +152,10 @@ export function clearNotifications() { api(getState).post('/api/v1/notifications/clear'); }; }; + +export function scrollTopNotifications(top) { + return { + type: NOTIFICATIONS_SCROLL_TOP, + top + }; +}; diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx index ee662fe79..19df2c36c 100644 --- a/app/assets/javascripts/components/actions/statuses.jsx +++ b/app/assets/javascripts/components/actions/statuses.jsx @@ -57,7 +57,8 @@ export function fetchStatusFail(id, error, skipLoading) { type: STATUS_FETCH_FAIL, id, error, - skipLoading + skipLoading, + skipAlert: true }; }; @@ -102,7 +103,12 @@ export function fetchContext(id) { api(getState).get(`/api/v1/statuses/${id}/context`).then(response => { dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants)); + }).catch(error => { + if (error.response.status === 404) { + dispatch(deleteFromTimelines(id)); + } + dispatch(fetchContextFail(id, error)); }); }; @@ -129,6 +135,7 @@ export function fetchContextFail(id, error) { return { type: CONTEXT_FETCH_FAIL, id, - error + error, + skipAlert: true }; }; diff --git a/app/assets/javascripts/components/actions/timelines.jsx b/app/assets/javascripts/components/actions/timelines.jsx index 1531b89a3..311b08033 100644 --- a/app/assets/javascripts/components/actions/timelines.jsx +++ b/app/assets/javascripts/components/actions/timelines.jsx @@ -1,4 +1,4 @@ -import api from '../api' +import api, { getLinks } from '../api' import Immutable from 'immutable'; export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; @@ -14,12 +14,13 @@ export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'; export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'; -export function refreshTimelineSuccess(timeline, statuses, skipLoading) { +export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) { return { type: TIMELINE_REFRESH_SUCCESS, timeline, statuses, - skipLoading + skipLoading, + next }; }; @@ -69,25 +70,22 @@ export function refreshTimeline(timeline, id = null) { const ids = getState().getIn(['timelines', timeline, 'items'], Immutable.List()); const newestId = ids.size > 0 ? ids.first() : null; + let params = getState().getIn(['timelines', timeline, 'params'], {}); + const path = getState().getIn(['timelines', timeline, 'path'])(id); - let params = ''; - let path = timeline; let skipLoading = false; if (newestId !== null && getState().getIn(['timelines', timeline, 'loaded']) && (id === null || getState().getIn(['timelines', timeline, 'id']) === id)) { - params = `?since_id=${newestId}`; - skipLoading = true; - } - - if (id) { - path = `${path}/${id}` + params = { ...params, since_id: newestId }; + skipLoading = true; } dispatch(refreshTimelineRequest(timeline, id, skipLoading)); - api(getState).get(`/api/v1/timelines/${path}${params}`).then(function (response) { - dispatch(refreshTimelineSuccess(timeline, response.data, skipLoading)); - }).catch(function (error) { + api(getState).get(path, { params }).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(refreshTimelineSuccess(timeline, response.data, skipLoading, next ? next.uri : null)); + }).catch(error => { dispatch(refreshTimelineFail(timeline, error, skipLoading)); }); }; @@ -102,50 +100,48 @@ export function refreshTimelineFail(timeline, error, skipLoading) { }; }; -export function expandTimeline(timeline, id = null) { +export function expandTimeline(timeline) { return (dispatch, getState) => { - const lastId = getState().getIn(['timelines', timeline, 'items'], Immutable.List()).last(); - - if (!lastId || getState().getIn(['timelines', timeline, 'isLoading'])) { - // If timeline is empty, don't try to load older posts since there are none - // Also if already loading + if (getState().getIn(['timelines', timeline, 'isLoading'])) { return; } - dispatch(expandTimelineRequest(timeline, id)); + const next = getState().getIn(['timelines', timeline, 'next']); + const params = getState().getIn(['timelines', timeline, 'params'], {}); - let path = timeline; - - if (id) { - path = `${path}/${id}` + if (next === null) { + return; } - api(getState).get(`/api/v1/timelines/${path}`, { + dispatch(expandTimelineRequest(timeline)); + + api(getState).get(next, { params: { - limit: 10, - max_id: lastId + ...params, + limit: 10 } }).then(response => { - dispatch(expandTimelineSuccess(timeline, response.data)); + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(expandTimelineSuccess(timeline, response.data, next ? next.uri : null)); }).catch(error => { dispatch(expandTimelineFail(timeline, error)); }); }; }; -export function expandTimelineRequest(timeline, id) { +export function expandTimelineRequest(timeline) { return { type: TIMELINE_EXPAND_REQUEST, - timeline, - id + timeline }; }; -export function expandTimelineSuccess(timeline, statuses) { +export function expandTimelineSuccess(timeline, statuses, next) { return { type: TIMELINE_EXPAND_SUCCESS, timeline, - statuses + statuses, + next }; }; diff --git a/app/assets/javascripts/components/components/column_collapsable.jsx b/app/assets/javascripts/components/components/column_collapsable.jsx index 676759055..729d00617 100644 --- a/app/assets/javascripts/components/components/column_collapsable.jsx +++ b/app/assets/javascripts/components/components/column_collapsable.jsx @@ -7,7 +7,8 @@ const iconStyle = { position: 'absolute', right: '0', top: '-48px', - cursor: 'pointer' + cursor: 'pointer', + zIndex: '3' }; const ColumnCollapsable = React.createClass({ @@ -41,7 +42,7 @@ const ColumnCollapsable = React.createClass({ const { icon, fullHeight, children } = this.props; const { collapsed } = this.state; const collapsedClassName = collapsed ? 'collapsable-collapsed' : 'collapsable'; - + return ( <div style={{ position: 'relative' }}> <div style={{...iconStyle }} className={collapsedClassName} onClick={this.handleToggleCollapsed}><i className={`fa fa-${icon}`} /></div> diff --git a/app/assets/javascripts/components/components/display_name.jsx b/app/assets/javascripts/components/components/display_name.jsx index 053b5290c..aa48608d3 100644 --- a/app/assets/javascripts/components/components/display_name.jsx +++ b/app/assets/javascripts/components/components/display_name.jsx @@ -1,6 +1,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PureRenderMixin from 'react-addons-pure-render-mixin'; -import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser'; +import escapeTextContentForBrowser from 'escape-html'; import emojify from '../emoji'; const DisplayName = React.createClass({ diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx index 66c41b5f7..110d26c6d 100644 --- a/app/assets/javascripts/components/components/status.jsx +++ b/app/assets/javascripts/components/components/status.jsx @@ -9,7 +9,7 @@ import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import { FormattedMessage } from 'react-intl'; import emojify from '../emoji'; -import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser'; +import escapeTextContentForBrowser from 'escape-html'; const Status = React.createClass({ diff --git a/app/assets/javascripts/components/components/status_content.jsx b/app/assets/javascripts/components/components/status_content.jsx index c0397e81c..43bbb9582 100644 --- a/app/assets/javascripts/components/components/status_content.jsx +++ b/app/assets/javascripts/components/components/status_content.jsx @@ -1,6 +1,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PureRenderMixin from 'react-addons-pure-render-mixin'; -import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser'; +import escapeTextContentForBrowser from 'escape-html'; import emojify from '../emoji'; import { FormattedMessage } from 'react-intl'; import Permalink from './permalink'; diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx index 69a2354c7..345944e4d 100644 --- a/app/assets/javascripts/components/components/status_list.jsx +++ b/app/assets/javascripts/components/components/status_list.jsx @@ -14,6 +14,8 @@ const StatusList = React.createClass({ onScroll: React.PropTypes.func, trackScroll: React.PropTypes.bool, isLoading: React.PropTypes.bool, + isUnread: React.PropTypes.bool, + hasMore: React.PropTypes.bool, prepend: React.PropTypes.node, emptyMessage: React.PropTypes.node }, @@ -72,18 +74,25 @@ const StatusList = React.createClass({ }, render () { - const { statusIds, onScrollToBottom, trackScroll, isLoading, prepend, emptyMessage } = this.props; + const { statusIds, onScrollToBottom, trackScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props; - let loadMore = ''; + let loadMore = ''; let scrollableArea = ''; + let unread = ''; - if (!isLoading && statusIds.size > 0) { + if (!isLoading && statusIds.size > 0 && hasMore) { loadMore = <LoadMore onClick={this.handleLoadMore} />; } + if (isUnread) { + unread = <div className='status-list__unread-indicator' />; + } + if (isLoading || statusIds.size > 0 || !emptyMessage) { scrollableArea = ( <div className='scrollable' ref={this.setRef}> + {unread} + <div> {prepend} diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index ebef5c81b..40fbac525 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -21,6 +21,7 @@ import UI from '../features/ui'; import Status from '../features/status'; import GettingStarted from '../features/getting_started'; import PublicTimeline from '../features/public_timeline'; +import CommunityTimeline from '../features/community_timeline'; import AccountTimeline from '../features/account_timeline'; import HomeTimeline from '../features/home_timeline'; import Compose from '../features/compose'; @@ -116,6 +117,7 @@ const Mastodon = React.createClass({ <Route path='getting-started' component={GettingStarted} /> <Route path='timelines/home' component={HomeTimeline} /> <Route path='timelines/public' component={PublicTimeline} /> + <Route path='timelines/public/local' component={CommunityTimeline} /> <Route path='timelines/tag/:id' component={HashtagTimeline} /> <Route path='notifications' component={Notifications} /> diff --git a/app/assets/javascripts/components/containers/status_container.jsx b/app/assets/javascripts/components/containers/status_container.jsx index fc096a375..81265bc50 100644 --- a/app/assets/javascripts/components/containers/status_container.jsx +++ b/app/assets/javascripts/components/containers/status_container.jsx @@ -18,45 +18,12 @@ import { openMedia } from '../actions/modal'; import { createSelector } from 'reselect' import { isMobile } from '../is_mobile' -const mapStateToProps = (state, props) => ({ - statusBase: state.getIn(['statuses', props.id]), - me: state.getIn(['meta', 'me']) -}); - -const makeMapStateToPropsInner = () => { - const getStatus = (() => { - return createSelector( - [ - (_, base) => base, - (state, base) => (base ? state.getIn(['accounts', base.get('account')]) : null), - (state, base) => (base ? state.getIn(['statuses', base.get('reblog')], null) : null) - ], - - (base, account, reblog) => (base ? base.set('account', account).set('reblog', reblog) : null) - ); - })(); - - const mapStateToProps = (state, { statusBase }) => ({ - status: getStatus(state, statusBase) - }); - - return mapStateToProps; -}; - -const makeMapStateToPropsLast = () => { - const getStatus = (() => { - return createSelector( - [ - (_, status) => status, - (state, status) => (status ? state.getIn(['accounts', status.getIn(['reblog', 'account'])], null) : null) - ], - - (status, reblogAccount) => (status && status.get('reblog') ? status.setIn(['reblog', 'account'], reblogAccount) : status) - ); - })(); +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); - const mapStateToProps = (state, { status }) => ({ - status: getStatus(state, status) + const mapStateToProps = (state, props) => ({ + status: getStatus(state, props.id), + me: state.getIn(['meta', 'me']) }); return mapStateToProps; @@ -106,8 +73,4 @@ const mapDispatchToProps = (dispatch) => ({ }); -export default connect(mapStateToProps, mapDispatchToProps)( - connect(makeMapStateToPropsInner)( - connect(makeMapStateToPropsLast)(Status) - ) -); +export default connect(makeMapStateToProps, mapDispatchToProps)(Status); diff --git a/app/assets/javascripts/components/features/account/components/header.jsx b/app/assets/javascripts/components/features/account/components/header.jsx index a4f0ca768..e1aae3c77 100644 --- a/app/assets/javascripts/components/features/account/components/header.jsx +++ b/app/assets/javascripts/components/features/account/components/header.jsx @@ -1,7 +1,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import emojify from '../../../emoji'; -import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser'; +import escapeTextContentForBrowser from 'escape-html'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import IconButton from '../../../components/icon_button'; @@ -14,7 +14,7 @@ const messages = defineMessages({ const Header = React.createClass({ propTypes: { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, me: React.PropTypes.number.isRequired, onFollow: React.PropTypes.func.isRequired, intl: React.PropTypes.object.isRequired @@ -25,6 +25,10 @@ const Header = React.createClass({ render () { const { account, me, intl } = this.props; + if (!account) { + return null; + } + let displayName = account.get('display_name'); let info = ''; let actionBtn = ''; diff --git a/app/assets/javascripts/components/features/account_timeline/components/header.jsx b/app/assets/javascripts/components/features/account_timeline/components/header.jsx index 0cdfc8b02..2dd3ca7b1 100644 --- a/app/assets/javascripts/components/features/account_timeline/components/header.jsx +++ b/app/assets/javascripts/components/features/account_timeline/components/header.jsx @@ -2,6 +2,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import InnerHeader from '../../account/components/header'; import ActionBar from '../../account/components/action_bar'; +import MissingIndicator from '../../../components/missing_indicator'; const Header = React.createClass({ contextTypes: { @@ -9,7 +10,7 @@ const Header = React.createClass({ }, propTypes: { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, me: React.PropTypes.number.isRequired, onFollow: React.PropTypes.func.isRequired, onBlock: React.PropTypes.func.isRequired, @@ -39,8 +40,8 @@ const Header = React.createClass({ render () { const { account, me } = this.props; - if (!account) { - return null; + if (account === null) { + return <MissingIndicator />; } return ( diff --git a/app/assets/javascripts/components/features/account_timeline/index.jsx b/app/assets/javascripts/components/features/account_timeline/index.jsx index 349510295..f92e1b49c 100644 --- a/app/assets/javascripts/components/features/account_timeline/index.jsx +++ b/app/assets/javascripts/components/features/account_timeline/index.jsx @@ -16,6 +16,7 @@ import Immutable from 'immutable'; const mapStateToProps = (state, props) => ({ statusIds: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'items'], Immutable.List()), isLoading: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'isLoading']), + hasMore: !!state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'next']), me: state.getIn(['meta', 'me']) }); @@ -26,6 +27,7 @@ const AccountTimeline = React.createClass({ dispatch: React.PropTypes.func.isRequired, statusIds: ImmutablePropTypes.list, isLoading: React.PropTypes.bool, + hasMore: React.PropTypes.bool, me: React.PropTypes.number.isRequired }, @@ -48,7 +50,7 @@ const AccountTimeline = React.createClass({ }, render () { - const { statusIds, isLoading, me } = this.props; + const { statusIds, isLoading, hasMore, me } = this.props; if (!statusIds && isLoading) { return ( @@ -66,6 +68,7 @@ const AccountTimeline = React.createClass({ prepend={<HeaderContainer accountId={this.props.params.accountId} />} statusIds={statusIds} isLoading={isLoading} + hasMore={hasMore} me={me} onScrollToBottom={this.handleScrollToBottom} /> diff --git a/app/assets/javascripts/components/features/community_timeline/index.jsx b/app/assets/javascripts/components/features/community_timeline/index.jsx new file mode 100644 index 000000000..aa1b8368e --- /dev/null +++ b/app/assets/javascripts/components/features/community_timeline/index.jsx @@ -0,0 +1,75 @@ +import { connect } from 'react-redux'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import StatusListContainer from '../ui/containers/status_list_container'; +import Column from '../ui/components/column'; +import { + refreshTimeline, + updateTimeline, + deleteFromTimelines +} from '../../actions/timelines'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import ColumnBackButtonSlim from '../../components/column_back_button_slim'; +import createStream from '../../stream'; + +const messages = defineMessages({ + title: { id: 'column.community', defaultMessage: 'Local' } +}); + +const mapStateToProps = state => ({ + hasUnread: state.getIn(['timelines', 'community', 'unread']) > 0, + accessToken: state.getIn(['meta', 'access_token']) +}); + +const CommunityTimeline = React.createClass({ + + propTypes: { + dispatch: React.PropTypes.func.isRequired, + intl: React.PropTypes.object.isRequired, + accessToken: React.PropTypes.string.isRequired, + hasUnread: React.PropTypes.bool + }, + + mixins: [PureRenderMixin], + + componentDidMount () { + const { dispatch, accessToken } = this.props; + + dispatch(refreshTimeline('community')); + + this.subscription = createStream(accessToken, 'public:local', { + + received (data) { + switch(data.event) { + case 'update': + dispatch(updateTimeline('community', JSON.parse(data.payload))); + break; + case 'delete': + dispatch(deleteFromTimelines(data.payload)); + break; + } + } + + }); + }, + + componentWillUnmount () { + if (typeof this.subscription !== 'undefined') { + this.subscription.close(); + this.subscription = null; + } + }, + + render () { + const { intl, hasUnread } = this.props; + + return ( + <Column icon='users' active={hasUnread} heading={intl.formatMessage(messages.title)}> + <ColumnBackButtonSlim /> + <StatusListContainer type='community' emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />} /> + </Column> + ); + }, + +}); + +export default connect(mapStateToProps)(injectIntl(CommunityTimeline)); diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 9edc01ed7..31ae8e034 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -2,7 +2,7 @@ import CharacterCounter from './character_counter'; import Button from '../../../components/button'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import ReplyIndicator from './reply_indicator'; +import ReplyIndicatorContainer from '../containers/reply_indicator_container'; import UploadButton from './upload_button'; import AutosuggestTextarea from '../../../components/autosuggest_textarea'; import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container'; @@ -11,6 +11,10 @@ import UploadButtonContainer from '../containers/upload_button_container'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Toggle from 'react-toggle'; import Collapsable from '../../../components/collapsable'; +import UnlistedToggleContainer from '../containers/unlisted_toggle_container'; +import SpoilerToggleContainer from '../containers/spoiler_toggle_container'; +import PrivateToggleContainer from '../containers/private_toggle_container'; +import SensitiveToggleContainer from '../containers/sensitive_toggle_container'; const messages = defineMessages({ placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' }, @@ -25,30 +29,24 @@ const ComposeForm = React.createClass({ text: React.PropTypes.string.isRequired, suggestion_token: React.PropTypes.string, suggestions: ImmutablePropTypes.list, - sensitive: React.PropTypes.bool, spoiler: React.PropTypes.bool, - spoiler_text: React.PropTypes.string, - unlisted: React.PropTypes.bool, private: React.PropTypes.bool, + unlisted: React.PropTypes.bool, + spoiler_text: React.PropTypes.string, fileDropDate: React.PropTypes.instanceOf(Date), + focusDate: React.PropTypes.instanceOf(Date), + preselectDate: React.PropTypes.instanceOf(Date), is_submitting: React.PropTypes.bool, is_uploading: React.PropTypes.bool, - in_reply_to: ImmutablePropTypes.map, - media_count: React.PropTypes.number, me: React.PropTypes.number, needsPrivacyWarning: React.PropTypes.bool, mentionedDomains: React.PropTypes.array.isRequired, onChange: React.PropTypes.func.isRequired, onSubmit: React.PropTypes.func.isRequired, - onCancelReply: React.PropTypes.func.isRequired, onClearSuggestions: React.PropTypes.func.isRequired, onFetchSuggestions: React.PropTypes.func.isRequired, onSuggestionSelected: React.PropTypes.func.isRequired, - onChangeSensitivity: React.PropTypes.func.isRequired, - onChangeSpoilerness: React.PropTypes.func.isRequired, onChangeSpoilerText: React.PropTypes.func.isRequired, - onChangeVisibility: React.PropTypes.func.isRequired, - onChangeListability: React.PropTypes.func.isRequired, }, mixins: [PureRenderMixin], @@ -80,34 +78,17 @@ const ComposeForm = React.createClass({ this.props.onSuggestionSelected(tokenStart, token, value); }, - handleChangeSensitivity (e) { - this.props.onChangeSensitivity(e.target.checked); - }, - - handleChangeSpoilerness (e) { - this.props.onChangeSpoilerness(e.target.checked); - this.props.onChangeSpoilerText(''); - }, - handleChangeSpoilerText (e) { this.props.onChangeSpoilerText(e.target.value); }, - handleChangeVisibility (e) { - this.props.onChangeVisibility(e.target.checked); - }, - - handleChangeListability (e) { - this.props.onChangeListability(e.target.checked); - }, - componentDidUpdate (prevProps) { - if ((prevProps.in_reply_to === null && this.props.in_reply_to !== null) || (prevProps.in_reply_to !== null && this.props.in_reply_to !== null && prevProps.in_reply_to.get('id') !== this.props.in_reply_to.get('id'))) { + if (this.props.focusDate !== prevProps.focusDate) { // If replying to zero or one users, places the cursor at the end of the textbox. // If replying to more than one user, selects any usernames past the first; // this provides a convenient shortcut to drop everyone else from the conversation. - const selectionStart = this.props.text.search(/\s/) + 1; const selectionEnd = this.props.text.length; + const selectionStart = (this.props.preselectDate !== prevProps.preselectDate) ? (this.props.text.search(/\s/) + 1) : selectionEnd; this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.focus(); @@ -122,14 +103,9 @@ const ComposeForm = React.createClass({ const { intl, needsPrivacyWarning, mentionedDomains } = this.props; const disabled = this.props.is_submitting || this.props.is_uploading; - let replyArea = ''; let publishText = ''; let privacyWarning = ''; - let reply_to_other = !!this.props.in_reply_to && (this.props.in_reply_to.getIn(['account', 'id']) !== this.props.me); - - if (this.props.in_reply_to) { - replyArea = <ReplyIndicator status={this.props.in_reply_to} onCancel={this.props.onCancelReply} />; - } + let reply_to_other = false; if (needsPrivacyWarning) { privacyWarning = ( @@ -158,7 +134,8 @@ const ComposeForm = React.createClass({ </Collapsable> {privacyWarning} - {replyArea} + + <ReplyIndicatorContainer /> <AutosuggestTextarea ref={this.setAutosuggestTextarea} @@ -180,29 +157,10 @@ const ComposeForm = React.createClass({ <UploadButtonContainer style={{ paddingTop: '4px' }} /> </div> - <label className='compose-form__label with-border' style={{ marginTop: '10px' }}> - <Toggle checked={this.props.spoiler} onChange={this.handleChangeSpoilerness} /> - <span className='compose-form__label__text'><FormattedMessage id='compose_form.spoiler' defaultMessage='Hide text behind warning' /></span> - </label> - - <label className='compose-form__label with-border'> - <Toggle checked={this.props.private} onChange={this.handleChangeVisibility} /> - <span className='compose-form__label__text'><FormattedMessage id='compose_form.private' defaultMessage='Mark as private' /></span> - </label> - - <Collapsable isVisible={!(this.props.private || reply_to_other)} fullHeight={39.5}> - <label className='compose-form__label'> - <Toggle checked={this.props.unlisted} onChange={this.handleChangeListability} /> - <span className='compose-form__label__text'><FormattedMessage id='compose_form.unlisted' defaultMessage='Do not display in public timeline' /></span> - </label> - </Collapsable> - - <Collapsable isVisible={this.props.media_count > 0} fullHeight={39.5}> - <label className='compose-form__label'> - <Toggle checked={this.props.sensitive} onChange={this.handleChangeSensitivity} /> - <span className='compose-form__label__text'><FormattedMessage id='compose_form.sensitive' defaultMessage='Mark media as sensitive' /></span> - </label> - </Collapsable> + <SpoilerToggleContainer /> + <PrivateToggleContainer /> + <UnlistedToggleContainer /> + <SensitiveToggleContainer /> </div> ); } diff --git a/app/assets/javascripts/components/features/compose/components/drawer.jsx b/app/assets/javascripts/components/features/compose/components/drawer.jsx index 83f3fa27d..ab67c86ea 100644 --- a/app/assets/javascripts/components/features/compose/components/drawer.jsx +++ b/app/assets/javascripts/components/features/compose/components/drawer.jsx @@ -3,7 +3,8 @@ import { injectIntl, defineMessages } from 'react-intl'; const messages = defineMessages({ start: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, - public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Public timeline' }, + public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Whole Known Network' }, + community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' } }); @@ -15,6 +16,7 @@ const Drawer = ({ children, withHeader, intl }) => { header = ( <div className='drawer__header'> <Link title={intl.formatMessage(messages.start)} className='drawer__tab' to='/getting-started'><i className='fa fa-fw fa-asterisk' /></Link> + <Link title={intl.formatMessage(messages.community)} className='drawer__tab' to='/timelines/public/local'><i className='fa fa-fw fa-users' /></Link> <Link title={intl.formatMessage(messages.public)} className='drawer__tab' to='/timelines/public'><i className='fa fa-fw fa-globe' /></Link> <a title={intl.formatMessage(messages.preferences)} className='drawer__tab' href='/settings/preferences'><i className='fa fa-fw fa-cog' /></a> <a title={intl.formatMessage(messages.logout)} className='drawer__tab' href='/auth/sign_out' data-method='delete'><i className='fa fa-fw fa-sign-out' /></a> diff --git a/app/assets/javascripts/components/features/compose/components/private_toggle.jsx b/app/assets/javascripts/components/features/compose/components/private_toggle.jsx new file mode 100644 index 000000000..902ee70ca --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/private_toggle.jsx @@ -0,0 +1,27 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { FormattedMessage } from 'react-intl'; +import Toggle from 'react-toggle'; + +const PrivateToggle = React.createClass({ + + propTypes: { + isPrivate: React.PropTypes.bool, + onChange: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const { isPrivate, onChange } = this.props; + + return ( + <label className='compose-form__label with-border'> + <Toggle checked={isPrivate} onChange={onChange} /> + <span className='compose-form__label__text'><FormattedMessage id='compose_form.private' defaultMessage='Mark as private' /></span> + </label> + ); + } + +}); + +export default PrivateToggle; diff --git a/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx index 73e5ee99e..a72bd32c2 100644 --- a/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx +++ b/app/assets/javascripts/components/features/compose/components/reply_indicator.jsx @@ -17,7 +17,7 @@ const ReplyIndicator = React.createClass({ }, propTypes: { - status: ImmutablePropTypes.map.isRequired, + status: ImmutablePropTypes.map, onCancel: React.PropTypes.func.isRequired, intl: React.PropTypes.object.isRequired }, @@ -36,17 +36,22 @@ const ReplyIndicator = React.createClass({ }, render () { - const { intl } = this.props; - const content = { __html: emojify(this.props.status.get('content')) }; + const { status, intl } = this.props; + + if (!status) { + return null; + } + + const content = { __html: emojify(status.get('content')) }; return ( <div className='reply-indicator'> <div style={{ overflow: 'hidden', marginBottom: '5px' }}> <div style={{ float: 'right', lineHeight: '24px' }}><IconButton title={intl.formatMessage(messages.cancel)} icon='times' onClick={this.handleClick} /></div> - <a href={this.props.status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name' style={{ display: 'block', maxWidth: '100%', paddingRight: '25px', textDecoration: 'none', overflow: 'hidden', lineHeight: '24px' }}> - <div style={{ float: 'left', marginRight: '5px' }}><Avatar size={24} src={this.props.status.getIn(['account', 'avatar'])} /></div> - <DisplayName account={this.props.status.get('account')} /> + <a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name' style={{ display: 'block', maxWidth: '100%', paddingRight: '25px', textDecoration: 'none', overflow: 'hidden', lineHeight: '24px' }}> + <div style={{ float: 'left', marginRight: '5px' }}><Avatar size={24} src={status.getIn(['account', 'avatar'])} /></div> + <DisplayName account={status.get('account')} /> </a> </div> diff --git a/app/assets/javascripts/components/features/compose/components/sensitive_toggle.jsx b/app/assets/javascripts/components/features/compose/components/sensitive_toggle.jsx new file mode 100644 index 000000000..97cc9487e --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/sensitive_toggle.jsx @@ -0,0 +1,31 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { FormattedMessage } from 'react-intl'; +import Toggle from 'react-toggle'; +import Collapsable from '../../../components/collapsable'; + +const SensitiveToggle = React.createClass({ + + propTypes: { + hasMedia: React.PropTypes.bool, + isSensitive: React.PropTypes.bool, + onChange: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const { hasMedia, isSensitive, onChange } = this.props; + + return ( + <Collapsable isVisible={hasMedia} fullHeight={39.5}> + <label className='compose-form__label'> + <Toggle checked={isSensitive} onChange={onChange} /> + <span className='compose-form__label__text'><FormattedMessage id='compose_form.sensitive' defaultMessage='Mark media as sensitive' /></span> + </label> + </Collapsable> + ); + } + +}); + +export default SensitiveToggle; diff --git a/app/assets/javascripts/components/features/compose/components/spoiler_toggle.jsx b/app/assets/javascripts/components/features/compose/components/spoiler_toggle.jsx new file mode 100644 index 000000000..1c59e4393 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/spoiler_toggle.jsx @@ -0,0 +1,27 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { FormattedMessage } from 'react-intl'; +import Toggle from 'react-toggle'; + +const SpoilerToggle = React.createClass({ + + propTypes: { + isSpoiler: React.PropTypes.bool, + onChange: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const { isSpoiler, onChange } = this.props; + + return ( + <label className='compose-form__label with-border' style={{ marginTop: '10px' }}> + <Toggle checked={isSpoiler} onChange={onChange} /> + <span className='compose-form__label__text'><FormattedMessage id='compose_form.spoiler' defaultMessage='Hide text behind warning' /></span> + </label> + ); + } + +}); + +export default SpoilerToggle; diff --git a/app/assets/javascripts/components/features/compose/components/unlisted_toggle.jsx b/app/assets/javascripts/components/features/compose/components/unlisted_toggle.jsx new file mode 100644 index 000000000..0745051eb --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/unlisted_toggle.jsx @@ -0,0 +1,32 @@ +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import { FormattedMessage } from 'react-intl'; +import Toggle from 'react-toggle'; +import Collapsable from '../../../components/collapsable'; + +const UnlistedToggle = React.createClass({ + + propTypes: { + isPrivate: React.PropTypes.bool, + isUnlisted: React.PropTypes.bool, + isReplyToOther: React.PropTypes.bool, + onChangeListability: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + render () { + const { isPrivate, isUnlisted, isReplyToOther, onChangeListability } = this.props; + + return ( + <Collapsable isVisible={!(isPrivate || isReplyToOther)} fullHeight={39.5}> + <label className='compose-form__label'> + <Toggle checked={isUnlisted} onChange={onChangeListability} /> + <span className='compose-form__label__text'><FormattedMessage id='compose_form.unlisted' defaultMessage='Do not display on public timelines' /></span> + </label> + </Collapsable> + ); + } + +}); + +export default UnlistedToggle; diff --git a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx index 2671ea618..53129af6e 100644 --- a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx +++ b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx @@ -1,95 +1,70 @@ import { connect } from 'react-redux'; import ComposeForm from '../components/compose_form'; +import { createSelector } from 'reselect'; import { changeCompose, submitCompose, - cancelReplyCompose, clearComposeSuggestions, fetchComposeSuggestions, selectComposeSuggestion, - changeComposeSensitivity, - changeComposeSpoilerness, changeComposeSpoilerText, - changeComposeVisibility, - changeComposeListability } from '../../../actions/compose'; -import { makeGetStatus } from '../../../selectors'; -const makeMapStateToProps = () => { - const getStatus = makeGetStatus(); +const getMentionedUsernames = createSelector(state => state.getIn(['compose', 'text']), text => text.match(/(?:^|[^\/\w])@([a-z0-9_]+@[a-z0-9\.\-]+)/ig)); - const mapStateToProps = function (state, props) { - const mentionedUsernamesWithDomains = state.getIn(['compose', 'text']).match(/(?:^|[^\/\w])@([a-z0-9_]+@[a-z0-9\.\-]+)/ig); +const getMentionedDomains = createSelector(getMentionedUsernames, mentionedUsernamesWithDomains => { + return mentionedUsernamesWithDomains !== null ? [...new Set(mentionedUsernamesWithDomains.map(item => item.split('@')[2]))] : []; +}); - return { - text: state.getIn(['compose', 'text']), - suggestion_token: state.getIn(['compose', 'suggestion_token']), - suggestions: state.getIn(['compose', 'suggestions']), - sensitive: state.getIn(['compose', 'sensitive']), - spoiler: state.getIn(['compose', 'spoiler']), - spoiler_text: state.getIn(['compose', 'spoiler_text']), - unlisted: state.getIn(['compose', 'unlisted'], ), - private: state.getIn(['compose', 'private']), - fileDropDate: state.getIn(['compose', 'fileDropDate']), - is_submitting: state.getIn(['compose', 'is_submitting']), - is_uploading: state.getIn(['compose', 'is_uploading']), - in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])), - media_count: state.getIn(['compose', 'media_attachments']).size, - me: state.getIn(['compose', 'me']), - needsPrivacyWarning: state.getIn(['compose', 'private']) && mentionedUsernamesWithDomains !== null, - mentionedDomains: mentionedUsernamesWithDomains !== null ? [...new Set(mentionedUsernamesWithDomains.map(item => item.split('@')[2]))] : [] - }; - }; - - return mapStateToProps; -}; +const mapStateToProps = (state, props) => { + const mentionedUsernames = getMentionedUsernames(state); + const mentionedUsernamesWithDomains = getMentionedDomains(state); -const mapDispatchToProps = function (dispatch) { return { - onChange (text) { - dispatch(changeCompose(text)); - }, - - onSubmit () { - dispatch(submitCompose()); - }, - - onCancelReply () { - dispatch(cancelReplyCompose()); - }, + text: state.getIn(['compose', 'text']), + suggestion_token: state.getIn(['compose', 'suggestion_token']), + suggestions: state.getIn(['compose', 'suggestions']), + spoiler: state.getIn(['compose', 'spoiler']), + spoiler_text: state.getIn(['compose', 'spoiler_text']), + unlisted: state.getIn(['compose', 'unlisted'], ), + private: state.getIn(['compose', 'private']), + fileDropDate: state.getIn(['compose', 'fileDropDate']), + focusDate: state.getIn(['compose', 'focusDate']), + preselectDate: state.getIn(['compose', 'preselectDate']), + is_submitting: state.getIn(['compose', 'is_submitting']), + is_uploading: state.getIn(['compose', 'is_uploading']), + me: state.getIn(['compose', 'me']), + needsPrivacyWarning: state.getIn(['compose', 'private']) && mentionedUsernames !== null, + mentionedDomains: mentionedUsernamesWithDomains + }; +}; - onClearSuggestions () { - dispatch(clearComposeSuggestions()); - }, +const mapDispatchToProps = (dispatch) => ({ - onFetchSuggestions (token) { - dispatch(fetchComposeSuggestions(token)); - }, + onChange (text) { + dispatch(changeCompose(text)); + }, - onSuggestionSelected (position, token, accountId) { - dispatch(selectComposeSuggestion(position, token, accountId)); - }, + onSubmit () { + dispatch(submitCompose()); + }, - onChangeSensitivity (checked) { - dispatch(changeComposeSensitivity(checked)); - }, + onClearSuggestions () { + dispatch(clearComposeSuggestions()); + }, - onChangeSpoilerness (checked) { - dispatch(changeComposeSpoilerness(checked)); - }, + onFetchSuggestions (token) { + dispatch(fetchComposeSuggestions(token)); + }, - onChangeSpoilerText (checked) { - dispatch(changeComposeSpoilerText(checked)); - }, + onSuggestionSelected (position, token, accountId) { + dispatch(selectComposeSuggestion(position, token, accountId)); + }, - onChangeVisibility (checked) { - dispatch(changeComposeVisibility(checked)); - }, + onChangeSpoilerText (checked) { + dispatch(changeComposeSpoilerText(checked)); + }, - onChangeListability (checked) { - dispatch(changeComposeListability(checked)); - } - } -}; +}); -export default connect(makeMapStateToProps, mapDispatchToProps)(ComposeForm); +export default connect(mapStateToProps, mapDispatchToProps)(ComposeForm); diff --git a/app/assets/javascripts/components/features/compose/containers/private_toggle_container.jsx b/app/assets/javascripts/components/features/compose/containers/private_toggle_container.jsx new file mode 100644 index 000000000..ee3596902 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/private_toggle_container.jsx @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import PrivateToggle from '../components/private_toggle'; +import { changeComposeVisibility } from '../../../actions/compose'; + +const mapStateToProps = state => ({ + isPrivate: state.getIn(['compose', 'private']) +}); + +const mapDispatchToProps = dispatch => ({ + + onChange (e) { + dispatch(changeComposeVisibility(e.target.checked)); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(PrivateToggle); diff --git a/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx b/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx new file mode 100644 index 000000000..39b48f3b6 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx @@ -0,0 +1,24 @@ +import { connect } from 'react-redux'; +import { cancelReplyCompose } from '../../../actions/compose'; +import { makeGetStatus } from '../../../selectors'; +import ReplyIndicator from '../components/reply_indicator'; + +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); + + const mapStateToProps = (state, props) => ({ + status: getStatus(state, state.getIn(['compose', 'in_reply_to'])), + }); + + return mapStateToProps; +}; + +const mapDispatchToProps = dispatch => ({ + + onCancel () { + dispatch(cancelReplyCompose()); + } + +}); + +export default connect(makeMapStateToProps, mapDispatchToProps)(ReplyIndicator); diff --git a/app/assets/javascripts/components/features/compose/containers/sensitive_toggle_container.jsx b/app/assets/javascripts/components/features/compose/containers/sensitive_toggle_container.jsx new file mode 100644 index 000000000..97b3361ba --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/sensitive_toggle_container.jsx @@ -0,0 +1,18 @@ +import { connect } from 'react-redux'; +import SensitiveToggle from '../components/sensitive_toggle'; +import { changeComposeSensitivity } from '../../../actions/compose'; + +const mapStateToProps = state => ({ + hasMedia: state.getIn(['compose', 'media_attachments']).size > 0, + isSensitive: state.getIn(['compose', 'sensitive']) +}); + +const mapDispatchToProps = dispatch => ({ + + onChange (e) { + dispatch(changeComposeSensitivity(e.target.checked)); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(SensitiveToggle); diff --git a/app/assets/javascripts/components/features/compose/containers/spoiler_toggle_container.jsx b/app/assets/javascripts/components/features/compose/containers/spoiler_toggle_container.jsx new file mode 100644 index 000000000..0bd4df759 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/spoiler_toggle_container.jsx @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import SpoilerToggle from '../components/spoiler_toggle'; +import { changeComposeSpoilerness } from '../../../actions/compose'; + +const mapStateToProps = state => ({ + isSpoiler: state.getIn(['compose', 'spoiler']) +}); + +const mapDispatchToProps = dispatch => ({ + + onChange (e) { + dispatch(changeComposeSpoilerness(e.target.checked)); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(SpoilerToggle); diff --git a/app/assets/javascripts/components/features/compose/containers/unlisted_toggle_container.jsx b/app/assets/javascripts/components/features/compose/containers/unlisted_toggle_container.jsx new file mode 100644 index 000000000..ceac903d9 --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/unlisted_toggle_container.jsx @@ -0,0 +1,31 @@ +import { connect } from 'react-redux'; +import UnlistedToggle from '../components/unlisted_toggle'; +import { makeGetStatus } from '../../../selectors'; +import { changeComposeListability } from '../../../actions/compose'; + +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); + + const mapStateToProps = state => { + const status = getStatus(state, state.getIn(['compose', 'in_reply_to'])); + const me = state.getIn(['compose', 'me']); + + return { + isPrivate: state.getIn(['compose', 'private']), + isUnlisted: state.getIn(['compose', 'unlisted']), + isReplyToOther: status ? status.getIn(['account', 'id']) !== me : false + }; + }; + + return mapStateToProps; +}; + +const mapDispatchToProps = dispatch => ({ + + onChangeListability (e) { + dispatch(changeComposeListability(e.target.checked)); + } + +}); + +export default connect(makeMapStateToProps, mapDispatchToProps)(UnlistedToggle); diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index af86919c1..f8433b8f4 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -7,7 +7,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; const messages = defineMessages({ heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, - public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Public timeline' }, + public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Whole Known Network' }, + community_timeline: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Sign out' }, @@ -30,6 +31,7 @@ const GettingStarted = ({ intl, me }) => { return ( <Column icon='asterisk' heading={intl.formatMessage(messages.heading)}> <div style={{ position: 'relative' }}> + <ColumnLink icon='users' text={intl.formatMessage(messages.community_timeline)} to='/timelines/public/local' /> <ColumnLink icon='globe' text={intl.formatMessage(messages.public_timeline)} to='/timelines/public' /> <ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' /> <ColumnLink icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' /> diff --git a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx index 6cb9e5482..7fb413336 100644 --- a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx +++ b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx @@ -12,6 +12,7 @@ import { FormattedMessage } from 'react-intl'; import createStream from '../../stream'; const mapStateToProps = state => ({ + hasUnread: state.getIn(['timelines', 'tag', 'unread']) > 0, accessToken: state.getIn(['meta', 'access_token']) }); @@ -20,7 +21,8 @@ const HashtagTimeline = React.createClass({ propTypes: { params: React.PropTypes.object.isRequired, dispatch: React.PropTypes.func.isRequired, - accessToken: React.PropTypes.string.isRequired + accessToken: React.PropTypes.string.isRequired, + hasUnread: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -72,10 +74,10 @@ const HashtagTimeline = React.createClass({ }, render () { - const { id } = this.props.params; + const { id, hasUnread } = this.props.params; return ( - <Column icon='hashtag' heading={id}> + <Column icon='hashtag' active={hasUnread} heading={id}> <ColumnBackButtonSlim /> <StatusListContainer type='tag' id={id} emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />} /> </Column> diff --git a/app/assets/javascripts/components/features/home_timeline/index.jsx b/app/assets/javascripts/components/features/home_timeline/index.jsx index 23e198701..a2b775764 100644 --- a/app/assets/javascripts/components/features/home_timeline/index.jsx +++ b/app/assets/javascripts/components/features/home_timeline/index.jsx @@ -1,3 +1,4 @@ +import { connect } from 'react-redux'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../ui/components/column'; @@ -9,25 +10,30 @@ const messages = defineMessages({ title: { id: 'column.home', defaultMessage: 'Home' } }); +const mapStateToProps = state => ({ + hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0 +}); + const HomeTimeline = React.createClass({ propTypes: { - intl: React.PropTypes.object.isRequired + intl: React.PropTypes.object.isRequired, + hasUnread: React.PropTypes.bool }, mixins: [PureRenderMixin], render () { - const { intl } = this.props; + const { intl, hasUnread } = this.props; return ( - <Column icon='home' heading={intl.formatMessage(messages.title)}> + <Column icon='home' active={hasUnread} heading={intl.formatMessage(messages.title)}> <ColumnSettingsContainer /> - <StatusListContainer {...this.props} type='home' emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage="You aren’t following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />} /> + <StatusListContainer {...this.props} type='home' emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage="You aren't following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />} /> </Column> ); }, }); -export default injectIntl(HomeTimeline); +export default connect(mapStateToProps)(injectIntl(HomeTimeline)); diff --git a/app/assets/javascripts/components/features/notifications/components/notification.jsx b/app/assets/javascripts/components/features/notifications/components/notification.jsx index fa8466140..0de4df52e 100644 --- a/app/assets/javascripts/components/features/notifications/components/notification.jsx +++ b/app/assets/javascripts/components/features/notifications/components/notification.jsx @@ -5,7 +5,7 @@ import AccountContainer from '../../../containers/account_container'; import { FormattedMessage } from 'react-intl'; import Permalink from '../../../components/permalink'; import emojify from '../../../emoji'; -import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser'; +import escapeTextContentForBrowser from 'escape-html'; const linkStyle = { fontWeight: '500' diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx index 9532b8af8..0da3544f6 100644 --- a/app/assets/javascripts/components/features/notifications/index.jsx +++ b/app/assets/javascripts/components/features/notifications/index.jsx @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Column from '../ui/components/column'; -import { expandNotifications, clearNotifications } from '../../actions/notifications'; +import { expandNotifications, clearNotifications, scrollTopNotifications } from '../../actions/notifications'; import NotificationContainer from './containers/notification_container'; import { ScrollContainer } from 'react-router-scroll'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; @@ -23,7 +23,8 @@ const getNotifications = createSelector([ const mapStateToProps = state => ({ notifications: getNotifications(state), - isLoading: state.getIn(['notifications', 'isLoading'], true) + isLoading: state.getIn(['notifications', 'isLoading'], true), + isUnread: state.getIn(['notifications', 'unread']) > 0 }); const Notifications = React.createClass({ @@ -33,7 +34,8 @@ const Notifications = React.createClass({ dispatch: React.PropTypes.func.isRequired, trackScroll: React.PropTypes.bool, intl: React.PropTypes.object.isRequired, - isLoading: React.PropTypes.bool + isLoading: React.PropTypes.bool, + isUnread: React.PropTypes.bool }, getDefaultProps () { @@ -51,6 +53,10 @@ const Notifications = React.createClass({ if (250 > offset && !this.props.isLoading) { this.props.dispatch(expandNotifications()); + } else if (scrollTop < 100) { + this.props.dispatch(scrollTopNotifications(true)); + } else { + this.props.dispatch(scrollTopNotifications(false)); } }, @@ -74,18 +80,25 @@ const Notifications = React.createClass({ }, render () { - const { intl, notifications, trackScroll, isLoading } = this.props; + const { intl, notifications, trackScroll, isLoading, isUnread } = this.props; let loadMore = ''; let scrollableArea = ''; + let unread = ''; if (!isLoading && notifications.size > 0) { loadMore = <LoadMore onClick={this.handleLoadMore} />; } + if (isUnread) { + unread = <div className='notifications__unread-indicator' />; + } + if (isLoading || notifications.size > 0) { scrollableArea = ( <div className='scrollable' onScroll={this.handleScroll} ref={this.setRef}> + {unread} + <div> {notifications.map(item => <NotificationContainer key={item.get('id')} notification={item} accountId={item.get('account')} />)} {loadMore} @@ -102,7 +115,7 @@ const Notifications = React.createClass({ if (trackScroll) { return ( - <Column icon='bell' heading={intl.formatMessage(messages.title)}> + <Column icon='bell' active={isUnread} heading={intl.formatMessage(messages.title)}> <ColumnSettingsContainer /> <ClearColumnButton onClick={this.handleClear} /> <ScrollContainer scrollKey='notifications'> @@ -112,7 +125,7 @@ const Notifications = React.createClass({ ); } else { return ( - <Column icon='bell' heading={intl.formatMessage(messages.title)}> + <Column icon='bell' active={isUnread} heading={intl.formatMessage(messages.title)}> <ColumnSettingsContainer /> <ClearColumnButton onClick={this.handleClear} /> {scrollableArea} diff --git a/app/assets/javascripts/components/features/public_timeline/index.jsx b/app/assets/javascripts/components/features/public_timeline/index.jsx index 36d68dbbb..ce4eacc92 100644 --- a/app/assets/javascripts/components/features/public_timeline/index.jsx +++ b/app/assets/javascripts/components/features/public_timeline/index.jsx @@ -7,15 +7,16 @@ import { updateTimeline, deleteFromTimelines } from '../../actions/timelines'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ColumnBackButtonSlim from '../../components/column_back_button_slim'; import createStream from '../../stream'; const messages = defineMessages({ - title: { id: 'column.public', defaultMessage: 'Public' } + title: { id: 'column.public', defaultMessage: 'Whole Known Network' } }); const mapStateToProps = state => ({ + hasUnread: state.getIn(['timelines', 'public', 'unread']) > 0, accessToken: state.getIn(['meta', 'access_token']) }); @@ -24,7 +25,8 @@ const PublicTimeline = React.createClass({ propTypes: { dispatch: React.PropTypes.func.isRequired, intl: React.PropTypes.object.isRequired, - accessToken: React.PropTypes.string.isRequired + accessToken: React.PropTypes.string.isRequired, + hasUnread: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -58,12 +60,12 @@ const PublicTimeline = React.createClass({ }, render () { - const { intl } = this.props; + const { intl, hasUnread } = this.props; return ( - <Column icon='globe' heading={intl.formatMessage(messages.title)}> + <Column icon='globe' active={hasUnread} heading={intl.formatMessage(messages.title)}> <ColumnBackButtonSlim /> - <StatusListContainer type='public' /> + <StatusListContainer type='public' emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other instances to fill it up' />} /> </Column> ); }, diff --git a/app/assets/javascripts/components/features/status/index.jsx b/app/assets/javascripts/components/features/status/index.jsx index e17c078d2..6a7635cc6 100644 --- a/app/assets/javascripts/components/features/status/index.jsx +++ b/app/assets/javascripts/components/features/status/index.jsx @@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { fetchStatus } from '../../actions/statuses'; import Immutable from 'immutable'; import EmbeddedStatus from '../../components/status'; -import LoadingIndicator from '../../components/loading_indicator'; +import MissingIndicator from '../../components/missing_indicator'; import DetailedStatus from './components/detailed_status'; import ActionBar from './components/action_bar'; import Column from '../ui/components/column'; @@ -117,7 +117,8 @@ const Status = React.createClass({ if (status === null) { return ( <Column> - <LoadingIndicator /> + <ColumnBackButton /> + <MissingIndicator /> </Column> ); } diff --git a/app/assets/javascripts/components/features/ui/components/column.jsx b/app/assets/javascripts/components/features/ui/components/column.jsx index 5b0603ee9..2b7e11bf1 100644 --- a/app/assets/javascripts/components/features/ui/components/column.jsx +++ b/app/assets/javascripts/components/features/ui/components/column.jsx @@ -34,7 +34,8 @@ const Column = React.createClass({ propTypes: { heading: React.PropTypes.string, icon: React.PropTypes.string, - children: React.PropTypes.node + children: React.PropTypes.node, + active: React.PropTypes.bool }, mixins: [PureRenderMixin], @@ -51,12 +52,12 @@ const Column = React.createClass({ }, render () { - const { heading, icon, children } = this.props; + const { heading, icon, children, active } = this.props; let header = ''; if (heading) { - header = <ColumnHeader icon={icon} type={heading} onClick={this.handleHeaderClick} />; + header = <ColumnHeader icon={icon} active={active} type={heading} onClick={this.handleHeaderClick} />; } return ( diff --git a/app/assets/javascripts/components/features/ui/components/column_header.jsx b/app/assets/javascripts/components/features/ui/components/column_header.jsx index 8b072d723..de55fa748 100644 --- a/app/assets/javascripts/components/features/ui/components/column_header.jsx +++ b/app/assets/javascripts/components/features/ui/components/column_header.jsx @@ -5,6 +5,7 @@ const ColumnHeader = React.createClass({ propTypes: { icon: React.PropTypes.string, type: React.PropTypes.string, + active: React.PropTypes.bool, onClick: React.PropTypes.func }, @@ -15,6 +16,8 @@ const ColumnHeader = React.createClass({ }, render () { + const { type, active } = this.props; + let icon = ''; if (this.props.icon) { @@ -22,9 +25,9 @@ const ColumnHeader = React.createClass({ } return ( - <div className='column-header' onClick={this.handleClick}> + <div className={`column-header ${active ? 'active' : ''}`} onClick={this.handleClick}> {icon} - {this.props.type} + {type} </div> ); } diff --git a/app/assets/javascripts/components/features/ui/containers/modal_container.jsx b/app/assets/javascripts/components/features/ui/containers/modal_container.jsx index 4c47fb8c5..d8301b20f 100644 --- a/app/assets/javascripts/components/features/ui/containers/modal_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/modal_container.jsx @@ -131,19 +131,14 @@ const Modal = React.createClass({ return null; } - const url = media.get(index).get('url'); - const hasLeft = index > 0; - const hasRight = index + 1 < media.size; + const url = media.get(index).get('url'); let leftNav, rightNav; leftNav = rightNav = ''; - if (hasLeft) { - leftNav = <div style={leftNavStyle} className='modal-container--nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>; - } - - if (hasRight) { + if (media.size > 1) { + leftNav = <div style={leftNavStyle} className='modal-container--nav' onClick={this.handlePrevClick}><i className='fa fa-fw fa-chevron-left' /></div>; rightNav = <div style={rightNavStyle} className='modal-container--nav' onClick={this.handleNextClick}><i className='fa fa-fw fa-chevron-right' /></div>; } diff --git a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx index 100989d22..f249240d8 100644 --- a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx @@ -3,8 +3,9 @@ import StatusList from '../../../components/status_list'; import { expandTimeline, scrollTopTimeline } from '../../../actions/timelines'; import Immutable from 'immutable'; import { createSelector } from 'reselect'; +import { debounce } from 'react-decoration'; -const getStatusIds = createSelector([ +const makeGetStatusIds = () => createSelector([ (state, { type }) => state.getIn(['settings', type], Immutable.Map()), (state, { type }) => state.getIn(['timelines', type, 'items'], Immutable.List()), (state) => state.get('statuses'), @@ -33,26 +34,37 @@ const getStatusIds = createSelector([ return showStatus; })); -const mapStateToProps = (state, props) => ({ - statusIds: getStatusIds(state, props), - isLoading: state.getIn(['timelines', props.type, 'isLoading'], true) -}); +const makeMapStateToProps = () => { + const getStatusIds = makeGetStatusIds(); + + const mapStateToProps = (state, props) => ({ + statusIds: getStatusIds(state, props), + isLoading: state.getIn(['timelines', props.type, 'isLoading'], true), + isUnread: state.getIn(['timelines', props.type, 'unread']) > 0, + hasMore: !!state.getIn(['timelines', props.type, 'next']) + }); + + return mapStateToProps; +}; const mapDispatchToProps = (dispatch, { type, id }) => ({ + @debounce(300, true) onScrollToBottom () { dispatch(scrollTopTimeline(type, false)); dispatch(expandTimeline(type, id)); }, + @debounce(100) onScrollToTop () { dispatch(scrollTopTimeline(type, true)); }, + @debounce(100) onScroll () { dispatch(scrollTopTimeline(type, false)); } }); -export default connect(mapStateToProps, mapDispatchToProps)(StatusList); +export default connect(makeMapStateToProps, mapDispatchToProps)(StatusList); diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx index 95962fd73..f1d6a6dbc 100644 --- a/app/assets/javascripts/components/locales/en.jsx +++ b/app/assets/javascripts/components/locales/en.jsx @@ -28,13 +28,13 @@ const en = { "getting_started.about_developer": "The developer of this project can be followed as Gargron@mastodon.social", "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on github at {github}.", "column.home": "Home", - "column.mentions": "Mentions", - "column.public": "Public", + "column.community": "Local", + "column.public": "Whole Known Network", "column.notifications": "Notifications", "tabs_bar.compose": "Compose", "tabs_bar.home": "Home", "tabs_bar.mentions": "Mentions", - "tabs_bar.public": "Public", + "tabs_bar.public": "Whole Known Network", "tabs_bar.notifications": "Notifications", "compose_form.placeholder": "What is on your mind?", "compose_form.publish": "Toot", @@ -42,10 +42,11 @@ const en = { "compose_form.spoiler": "Hide text behind warning", "compose_form.private": "Mark as private", "compose_form.privacy_disclaimer": "Your private status will be delivered to mentioned users on {domains}. Do you trust {domainsCount, plural, one {that server} other {those servers}} to not leak your status?", - "compose_form.unlisted": "Do not display in public timeline", + "compose_form.unlisted": "Do not display on public timelines", "navigation_bar.edit_profile": "Edit profile", "navigation_bar.preferences": "Preferences", - "navigation_bar.public_timeline": "Public timeline", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.public_timeline": "Whole Known Network", "navigation_bar.logout": "Logout", "reply_indicator.cancel": "Cancel", "search.placeholder": "Search", diff --git a/app/assets/javascripts/components/middleware/errors.jsx b/app/assets/javascripts/components/middleware/errors.jsx index 74d77f0f9..4aca75f1e 100644 --- a/app/assets/javascripts/components/middleware/errors.jsx +++ b/app/assets/javascripts/components/middleware/errors.jsx @@ -5,7 +5,7 @@ const defaultFailSuffix = 'FAIL'; export default function errorsMiddleware() { return ({ dispatch }) => next => action => { - if (action.type) { + if (action.type && !action.skipAlert) { const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); const isSuccess = new RegExp(`${defaultSuccessSuffix}$`, 'g'); diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx index 8d281048e..dead5fd77 100644 --- a/app/assets/javascripts/components/reducers/compose.jsx +++ b/app/assets/javascripts/components/reducers/compose.jsx @@ -35,6 +35,8 @@ const initialState = Immutable.Map({ private: false, text: '', fileDropDate: null, + focusDate: null, + preselectDate: null, in_reply_to: null, is_submitting: false, is_uploading: false, @@ -99,6 +101,7 @@ const insertSuggestion = (state, position, token, completion) => { map.update('text', oldText => `${oldText.slice(0, position)}${completion} ${oldText.slice(position + token.length)}`); map.set('suggestion_token', null); map.update('suggestions', Immutable.List(), list => list.clear()); + map.set('focusDate', new Date()); }); }; @@ -113,7 +116,10 @@ export default function compose(state = initialState, action) { case COMPOSE_SENSITIVITY_CHANGE: return state.set('sensitive', action.checked); case COMPOSE_SPOILERNESS_CHANGE: - return (action.checked ? state : state.set('spoiler_text', '')).set('spoiler', action.checked); + return state.withMutations(map => { + map.set('spoiler_text', ''); + map.set('spoiler', action.checked); + }); case COMPOSE_SPOILER_TEXT_CHANGE: return state.set('spoiler_text', action.text); case COMPOSE_VISIBILITY_CHANGE: @@ -128,6 +134,8 @@ export default function compose(state = initialState, action) { map.set('text', statusToTextMentions(state, action.status)); map.set('unlisted', action.status.get('visibility') === 'unlisted' || state.get('default_privacy') === 'unlisted'); map.set('private', action.status.get('visibility') === 'private' || state.get('default_privacy') === 'private'); + map.set('focusDate', new Date()); + map.set('preselectDate', new Date()); }); case COMPOSE_REPLY_CANCEL: return state.withMutations(map => { @@ -156,7 +164,7 @@ export default function compose(state = initialState, action) { case COMPOSE_UPLOAD_PROGRESS: return state.set('progress', Math.round((action.loaded / action.total) * 100)); case COMPOSE_MENTION: - return state.update('text', text => `${text}@${action.account.get('acct')} `); + return state.update('text', text => `${text}@${action.account.get('acct')} `).set('focusDate', new Date()); case COMPOSE_SUGGESTIONS_CLEAR: return state.update('suggestions', Immutable.List(), list => list.clear()).set('suggestion_token', null); case COMPOSE_SUGGESTIONS_READY: diff --git a/app/assets/javascripts/components/reducers/modal.jsx b/app/assets/javascripts/components/reducers/modal.jsx index 07da65771..37ffbc62b 100644 --- a/app/assets/javascripts/components/reducers/modal.jsx +++ b/app/assets/javascripts/components/reducers/modal.jsx @@ -23,9 +23,9 @@ export default function modal(state = initialState, action) { case MODAL_CLOSE: return state.set('open', false); case MODAL_INDEX_DECREASE: - return state.update('index', index => Math.max(index - 1, 0)); + return state.update('index', index => (index - 1) % state.get('media').size); case MODAL_INDEX_INCREASE: - return state.update('index', index => Math.min(index + 1, state.get('media').size - 1)); + return state.update('index', index => (index + 1) % state.get('media').size); default: return state; } diff --git a/app/assets/javascripts/components/reducers/notifications.jsx b/app/assets/javascripts/components/reducers/notifications.jsx index 4a7af8856..1406a388a 100644 --- a/app/assets/javascripts/components/reducers/notifications.jsx +++ b/app/assets/javascripts/components/reducers/notifications.jsx @@ -6,7 +6,8 @@ import { NOTIFICATIONS_EXPAND_REQUEST, NOTIFICATIONS_REFRESH_FAIL, NOTIFICATIONS_EXPAND_FAIL, - NOTIFICATIONS_CLEAR + NOTIFICATIONS_CLEAR, + NOTIFICATIONS_SCROLL_TOP } from '../actions/notifications'; import { ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts'; import Immutable from 'immutable'; @@ -14,6 +15,8 @@ import Immutable from 'immutable'; const initialState = Immutable.Map({ items: Immutable.List(), next: null, + top: true, + unread: 0, loaded: false, isLoading: true }); @@ -26,6 +29,10 @@ const notificationToMap = notification => Immutable.Map({ }); const normalizeNotification = (state, notification) => { + if (!state.get('top')) { + state = state.update('unread', unread => unread + 1); + } + return state.update('items', list => list.unshift(notificationToMap(notification))); }; @@ -37,9 +44,12 @@ const normalizeNotifications = (state, notifications, next) => { items = items.set(i, notificationToMap(n)); }); + if (state.get('next') === null) { + state = state.set('next', next); + } + return state .update('items', list => loaded ? list.unshift(...items) : list.push(...items)) - .set('next', next) .set('loaded', true) .set('isLoading', false); }; @@ -61,6 +71,14 @@ const filterNotifications = (state, relationship) => { return state.update('items', list => list.filterNot(item => item.get('account') === relationship.id)); }; +const updateTop = (state, top) => { + if (top) { + state = state.set('unread', 0); + } + + return state.set('top', top); +}; + export default function notifications(state = initialState, action) { switch(action.type) { case NOTIFICATIONS_REFRESH_REQUEST: @@ -68,6 +86,8 @@ export default function notifications(state = initialState, action) { case NOTIFICATIONS_REFRESH_FAIL: case NOTIFICATIONS_EXPAND_FAIL: return state.set('isLoading', true); + case NOTIFICATIONS_SCROLL_TOP: + return updateTop(state, action.top); case NOTIFICATIONS_UPDATE: return normalizeNotification(state, action.notification); case NOTIFICATIONS_REFRESH_SUCCESS: diff --git a/app/assets/javascripts/components/reducers/statuses.jsx b/app/assets/javascripts/components/reducers/statuses.jsx index 6323e0fbe..ce791eab6 100644 --- a/app/assets/javascripts/components/reducers/statuses.jsx +++ b/app/assets/javascripts/components/reducers/statuses.jsx @@ -39,14 +39,15 @@ const normalizeStatus = (state, status) => { return state; } - status.account = status.account.id; + const normalStatus = { ...status }; + normalStatus.account = status.account.id; if (status.reblog && status.reblog.id) { - state = normalizeStatus(state, status.reblog); - status.reblog = status.reblog.id; + state = normalizeStatus(state, status.reblog); + normalStatus.reblog = status.reblog.id; } - return state.update(status.id, Immutable.Map(), map => map.mergeDeep(Immutable.fromJS(status))); + return state.update(status.id, Immutable.Map(), map => map.mergeDeep(Immutable.fromJS(normalStatus))); }; const normalizeStatuses = (state, statuses) => { diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx index 6f2d26dcb..6472ac6a0 100644 --- a/app/assets/javascripts/components/reducers/timelines.jsx +++ b/app/assets/javascripts/components/reducers/timelines.jsx @@ -31,31 +31,44 @@ import Immutable from 'immutable'; const initialState = Immutable.Map({ home: Immutable.Map({ + path: () => '/api/v1/timelines/home', + next: null, isLoading: false, loaded: false, top: true, + unread: 0, items: Immutable.List() }), - mentions: Immutable.Map({ + public: Immutable.Map({ + path: () => '/api/v1/timelines/public', + next: null, isLoading: false, loaded: false, top: true, + unread: 0, items: Immutable.List() }), - public: Immutable.Map({ + community: Immutable.Map({ + path: () => '/api/v1/timelines/public', + next: null, + params: { local: true }, isLoading: false, loaded: false, top: true, + unread: 0, items: Immutable.List() }), tag: Immutable.Map({ + path: (id) => `/api/v1/timelines/tag/${id}`, + next: null, isLoading: false, id: null, loaded: false, top: true, + unread: 0, items: Immutable.List() }), @@ -81,7 +94,7 @@ const normalizeStatus = (state, status) => { return state; }; -const normalizeTimeline = (state, timeline, statuses, replace = false) => { +const normalizeTimeline = (state, timeline, statuses, next) => { let ids = Immutable.List(); const loaded = state.getIn([timeline, 'loaded']); @@ -93,10 +106,14 @@ const normalizeTimeline = (state, timeline, statuses, replace = false) => { state = state.setIn([timeline, 'loaded'], true); state = state.setIn([timeline, 'isLoading'], false); + if (state.getIn([timeline, 'next']) === null) { + state = state.setIn([timeline, 'next'], next); + } + return state.updateIn([timeline, 'items'], Immutable.List(), list => (loaded ? list.unshift(...ids) : ids)); }; -const appendNormalizedTimeline = (state, timeline, statuses) => { +const appendNormalizedTimeline = (state, timeline, statuses, next) => { let moreIds = Immutable.List(); statuses.forEach((status, i) => { @@ -105,6 +122,7 @@ const appendNormalizedTimeline = (state, timeline, statuses) => { }); state = state.setIn([timeline, 'isLoading'], false); + state = state.setIn([timeline, 'next'], next); return state.updateIn([timeline, 'items'], Immutable.List(), list => list.push(...moreIds)); }; @@ -141,6 +159,10 @@ const updateTimeline = (state, timeline, status, references) => { state = normalizeStatus(state, status); + if (!top) { + state = state.updateIn([timeline, 'unread'], unread => unread + 1); + } + state = state.updateIn([timeline, 'items'], Immutable.List(), list => { if (top && list.size > 40) { list = list.take(20); @@ -169,7 +191,7 @@ const deleteStatus = (state, id, accountId, references, reblogOf) => { } // Remove references from timelines - ['home', 'mentions', 'public', 'tag'].forEach(function (timeline) { + ['home', 'public', 'community', 'tag'].forEach(function (timeline) { state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id)); }); @@ -221,11 +243,13 @@ const normalizeContext = (state, id, ancestors, descendants) => { }; const resetTimeline = (state, timeline, id) => { - if (timeline === 'tag' && state.getIn([timeline, 'id']) !== id) { + if (timeline === 'tag' && typeof id !== 'undefined' && state.getIn([timeline, 'id']) !== id) { state = state.update(timeline, map => map .set('id', id) .set('isLoading', true) .set('loaded', false) + .set('next', null) + .set('top', true) .update('items', list => list.clear())); } else { state = state.setIn([timeline, 'isLoading'], true); @@ -234,6 +258,14 @@ const resetTimeline = (state, timeline, id) => { return state; }; +const updateTop = (state, timeline, top) => { + if (top) { + state = state.setIn([timeline, 'unread'], 0); + } + + return state.setIn([timeline, 'top'], top); +}; + export default function timelines(state = initialState, action) { switch(action.type) { case TIMELINE_REFRESH_REQUEST: @@ -243,9 +275,9 @@ export default function timelines(state = initialState, action) { case TIMELINE_EXPAND_FAIL: return state.setIn([action.timeline, 'isLoading'], false); case TIMELINE_REFRESH_SUCCESS: - return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses)); + return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses), action.next); case TIMELINE_EXPAND_SUCCESS: - return appendNormalizedTimeline(state, action.timeline, Immutable.fromJS(action.statuses)); + return appendNormalizedTimeline(state, action.timeline, Immutable.fromJS(action.statuses), action.next); case TIMELINE_UPDATE: return updateTimeline(state, action.timeline, Immutable.fromJS(action.status), action.references); case TIMELINE_DELETE: @@ -265,7 +297,7 @@ export default function timelines(state = initialState, action) { case ACCOUNT_BLOCK_SUCCESS: return filterTimelines(state, action.relationship, action.statuses); case TIMELINE_SCROLL_TOP: - return state.setIn([action.timeline, 'top'], action.top); + return updateTop(state, action.timeline, action.top); default: return state; } diff --git a/app/assets/javascripts/components/selectors/index.jsx b/app/assets/javascripts/components/selectors/index.jsx index 20debe604..0e88654a1 100644 --- a/app/assets/javascripts/components/selectors/index.jsx +++ b/app/assets/javascripts/components/selectors/index.jsx @@ -1,4 +1,4 @@ -import { createSelector } from 'reselect' +import { createSelector } from 'reselect'; import Immutable from 'immutable'; const getStatuses = state => state.get('statuses'); @@ -17,37 +17,32 @@ export const makeGetAccount = () => { }); }; -const getStatusBase = (state, id) => state.getIn(['statuses', id], null); - export const makeGetStatus = () => { - return createSelector([getStatusBase, getStatuses, getAccounts], (base, statuses, accounts) => { - if (base === null) { - return null; + return createSelector( + [ + (state, id) => state.getIn(['statuses', id]), + (state, id) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]), + (state, id) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), + (state, id) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), + ], + + (statusBase, statusReblog, accountBase, accountReblog) => { + if (!statusBase) { + return null; + } + + if (statusReblog) { + statusReblog = statusReblog.set('account', accountReblog); + } else { + statusReblog = null; + } + + return statusBase.withMutations(map => { + map.set('reblog', statusReblog); + map.set('account', accountBase); + }); } - - return assembleStatus(base.get('id'), statuses, accounts); - }); -}; - -const assembleStatus = (id, statuses, accounts) => { - let status = statuses.get(id, null); - let reblog = null; - - if (status === null) { - return null; - } - - if (status.get('reblog', null) !== null) { - reblog = statuses.get(status.get('reblog'), null); - - if (reblog !== null) { - reblog = reblog.set('account', accounts.get(reblog.get('account'))); - } else { - return null; - } - } - - return status.set('reblog', reblog).set('account', accounts.get(status.get('account'))); + ); }; const getAlertsBase = state => state.get('alerts'); diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index bc56891f3..94c351520 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -786,6 +786,7 @@ a.status__content__spoiler-link { flex: 0 0 auto; cursor: pointer; color: $color4; + z-index: 3; &:hover { text-decoration: underline; @@ -1079,6 +1080,17 @@ button.active i.fa-retweet { background: lighten($color1, 4%); flex: 0 0 auto; cursor: pointer; + position: relative; + z-index: 2; + + &.active { + box-shadow: 0 1px 0 rgba($color4, 0.3); + } + + &.active .fa { + color: $color4; + text-shadow: 0 0 10px rgba($color4, 0.4); + } } .search { @@ -1201,3 +1213,16 @@ button.active i.fa-retweet { } } } + +.status-list__unread-indicator, .notifications__unread-indicator { + position: absolute; + top: 35px; + left: 0; + right: 0; + margin: 0 auto; + width: 60%; + pointer-events: none; + height: 28px; + z-index: 1; + background: radial-gradient(ellipse, rgba($color4, 0.23) 0%, rgba($color4, 0) 60%); +} diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 0d02294eb..94dba1d03 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -52,7 +52,7 @@ class Api::V1::AccountsController < ApiController set_maps(@statuses) set_counters_maps(@statuses) - next_path = statuses_api_v1_account_url(max_id: @statuses.last.id) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) + next_path = statuses_api_v1_account_url(max_id: @statuses.last.id) unless @statuses.empty? prev_path = statuses_api_v1_account_url(since_id: @statuses.first.id) unless @statuses.empty? set_pagination_headers(next_path, prev_path) @@ -66,7 +66,7 @@ class Api::V1::AccountsController < ApiController set_maps(@statuses) set_counters_maps(@statuses) - next_path = media_statuses_api_v1_account_url(max_id: @statuses.last.id) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) + next_path = media_statuses_api_v1_account_url(max_id: @statuses.last.id) unless @statuses.empty? prev_path = media_statuses_api_v1_account_url(since_id: @statuses.first.id) unless @statuses.empty? set_pagination_headers(next_path, prev_path) diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index 877356a75..544ba2442 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -17,7 +17,7 @@ class Api::V1::NotificationsController < ApiController set_counters_maps(statuses) set_account_counters_maps(@notifications.map(&:from_account)) - next_path = api_v1_notifications_url(max_id: @notifications.last.id) if @notifications.size == limit_param(DEFAULT_NOTIFICATIONS_LIMIT) + next_path = api_v1_notifications_url(max_id: @notifications.last.id) unless @notifications.empty? prev_path = api_v1_notifications_url(since_id: @notifications.first.id) unless @notifications.empty? set_pagination_headers(next_path, prev_path) diff --git a/app/controllers/api/v1/timelines_controller.rb b/app/controllers/api/v1/timelines_controller.rb index a8cc2b288..af6e5b7df 100644 --- a/app/controllers/api/v1/timelines_controller.rb +++ b/app/controllers/api/v1/timelines_controller.rb @@ -14,7 +14,7 @@ class Api::V1::TimelinesController < ApiController set_counters_maps(@statuses) set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) - next_path = api_v1_home_timeline_url(max_id: @statuses.last.id) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) + next_path = api_v1_home_timeline_url(max_id: @statuses.last.id) unless @statuses.empty? prev_path = api_v1_home_timeline_url(since_id: @statuses.first.id) unless @statuses.empty? set_pagination_headers(next_path, prev_path) @@ -30,7 +30,7 @@ class Api::V1::TimelinesController < ApiController set_counters_maps(@statuses) set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) - next_path = api_v1_public_timeline_url(max_id: @statuses.last.id) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) + next_path = api_v1_public_timeline_url(max_id: @statuses.last.id) unless @statuses.empty? prev_path = api_v1_public_timeline_url(since_id: @statuses.first.id) unless @statuses.empty? set_pagination_headers(next_path, prev_path) @@ -47,7 +47,7 @@ class Api::V1::TimelinesController < ApiController set_counters_maps(@statuses) set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) - next_path = api_v1_hashtag_timeline_url(params[:id], max_id: @statuses.last.id) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) + next_path = api_v1_hashtag_timeline_url(params[:id], max_id: @statuses.last.id) unless @statuses.empty? prev_path = api_v1_hashtag_timeline_url(params[:id], since_id: @statuses.first.id) unless @statuses.empty? set_pagination_headers(next_path, prev_path) diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 044407a6c..e353c3504 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -9,6 +9,8 @@ class Formatter include ActionView::Helpers::TextHelper include ActionView::Helpers::SanitizeHelper + AUTOLINK_RE = /https?:\/\/([\S]+\.[!#$&-;=?-[\]_a-z~]|%[\w\d]{2}]+[\w])/i + def format(status) return reformat(status.content) unless status.local? @@ -24,7 +26,7 @@ class Formatter end def reformat(html) - sanitize(html, tags: %w(a br p), attributes: %w(href rel)) + sanitize(html, tags: %w(a br p span), attributes: %w(href rel class)) end def simplified_format(account) @@ -44,9 +46,9 @@ class Formatter end def link_urls(html) - html.gsub(URI.regexp(%w(http https))) do |match| - link_html(match) - end + Twitter::Autolink.auto_link_urls(html, url_target: '_blank', + link_attribute_block: lambda { |_, a| a[:rel] << ' noopener' }, + link_text_block: lambda { |_, text| link_html(text) }) end def link_mentions(html, mentions) @@ -70,7 +72,7 @@ class Formatter suffix = url[prefix.length + 30..-1] cutoff = url[prefix.length..-1].length > 30 - "<a rel=\"nofollow noopener\" target=\"_blank\" href=\"#{url}\"><span class=\"invisible\">#{prefix}</span><span class=\"#{cutoff ? 'ellipsis' : ''}\">#{text}</span><span class=\"invisible\">#{suffix}</span></a>" + "<span class=\"invisible\">#{prefix}</span><span class=\"#{cutoff ? 'ellipsis' : ''}\">#{text}</span><span class=\"invisible\">#{suffix}</span>" end def hashtag_html(match) diff --git a/app/models/account.rb b/app/models/account.rb index ed5c46197..469695acd 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -138,7 +138,7 @@ class Account < ApplicationRecord def avatar_remote_url=(url) parsed_url = URI.parse(url) - return if !%w(http https).include?(parsed_url.scheme) || self[:avatar_remote_url] == url + return if !%w(http https).include?(parsed_url.scheme) || parsed_url.host.empty? || self[:avatar_remote_url] == url self.avatar = parsed_url self[:avatar_remote_url] = url diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index b4606da60..3548ccd69 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -6,6 +6,6 @@ class DomainBlock < ApplicationRecord validates :domain, presence: true, uniqueness: true def self.blocked?(domain) - where(domain: domain).exists? + where(domain: domain, severity: :suspend).exists? end end diff --git a/app/models/status.rb b/app/models/status.rb index 46d92ea33..1b40897f3 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -192,6 +192,6 @@ class Status < ApplicationRecord private def filter_from_context?(status, account) - account&.blocking?(status.account_id) || !status.permitted?(account) + account&.blocking?(status.account_id) || (status.account.silenced? && !account&.following?(status.account_id)) || !status.permitted?(account) end end diff --git a/app/services/favourite_service.rb b/app/services/favourite_service.rb index 824729ed6..818898302 100644 --- a/app/services/favourite_service.rb +++ b/app/services/favourite_service.rb @@ -22,10 +22,13 @@ class FavouriteService < BaseService private def build_xml(favourite) + description = "#{favourite.account.acct} favourited a status by #{favourite.status.account.acct}" + Nokogiri::XML::Builder.new do |xml| entry(xml, true) do unique_id xml, favourite.created_at, favourite.id, 'Favourite' - title xml, "#{favourite.account.acct} favourited a status by #{favourite.status.account.acct}" + title xml, description + content xml, description author(xml) do include_author xml, favourite.account diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index d67b1bf2d..915f95b4c 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -55,10 +55,13 @@ class FollowService < BaseService end def build_follow_request_xml(follow_request) + description = "#{follow_request.account.acct} requested to follow #{follow_request.target_account.acct}" + Nokogiri::XML::Builder.new do |xml| entry(xml, true) do unique_id xml, follow_request.created_at, follow_request.id, 'FollowRequest' - title xml, "#{follow_request.account.acct} requested to follow #{follow_request.target_account.acct}" + title xml, description + content xml, description author(xml) do include_author xml, follow_request.account @@ -75,10 +78,13 @@ class FollowService < BaseService end def build_follow_xml(follow) + description = "#{follow.account.acct} started following #{follow.target_account.acct}" + Nokogiri::XML::Builder.new do |xml| entry(xml, true) do unique_id xml, follow.created_at, follow.id, 'Follow' - title xml, "#{follow.account.acct} started following #{follow.target_account.acct}" + title xml, description + content xml, description author(xml) do include_author xml, follow.account diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb index f0a62aa14..5d952df6f 100644 --- a/app/services/process_feed_service.rb +++ b/app/services/process_feed_service.rb @@ -181,6 +181,9 @@ class ProcessFeedService < BaseService next unless link['href'] media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, remote_url: link['href']) + parsed_url = URI.parse(link['href']) + + next if !%w(http https).include?(parsed_url.scheme) || parsed_url.host.empty? begin media.file_remote_url = link['href'] diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 73b545f17..cf1f432e4 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -59,7 +59,7 @@ class RemoveStatusService < BaseService end def unpush(type, receiver, status) - if status.reblog? + if status.reblog? && !redis.zscore(FeedManager.instance.key(type, receiver.id), status.reblog_of_id).nil? redis.zadd(FeedManager.instance.key(type, receiver.id), status.reblog_of_id, status.reblog_of_id) else redis.zremrangebyscore(FeedManager.instance.key(type, receiver.id), status.id, status.id) diff --git a/app/services/unfavourite_service.rb b/app/services/unfavourite_service.rb index 1d3e6f06d..5f0ba4254 100644 --- a/app/services/unfavourite_service.rb +++ b/app/services/unfavourite_service.rb @@ -13,10 +13,13 @@ class UnfavouriteService < BaseService private def build_xml(favourite) + description = "#{favourite.account.acct} no longer favourites a status by #{favourite.status.account.acct}" + Nokogiri::XML::Builder.new do |xml| entry(xml, true) do unique_id xml, Time.now.utc, favourite.id, 'Favourite' - title xml, "#{favourite.account.acct} no longer favourites a status by #{favourite.status.account.acct}" + title xml, description + content xml, description author(xml) do include_author xml, favourite.account diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb index 07f9b93dd..3440da364 100644 --- a/app/services/unfollow_service.rb +++ b/app/services/unfollow_service.rb @@ -13,10 +13,13 @@ class UnfollowService < BaseService private def build_xml(follow) + description = "#{follow.account.acct} is no longer following #{follow.target_account.acct}" + Nokogiri::XML::Builder.new do |xml| entry(xml, true) do unique_id xml, Time.now.utc, follow.id, 'Follow' - title xml, "#{follow.account.acct} is no longer following #{follow.target_account.acct}" + title xml, description + content xml, description author(xml) do include_author xml, follow.account diff --git a/config/environments/production.rb b/config/environments/production.rb index 62ea217ef..67ff63914 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -43,7 +43,7 @@ Rails.application.configure do config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different logger for distributed setups. # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) diff --git a/docs/README.md b/docs/README.md index 5036ea22c..d35dece14 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,6 +22,7 @@ Index - [Development guide](Running-Mastodon/Development-guide.md) - [Alternative: Development with Vagrant](Running-Mastodon/Vagrant-guide.md) - [Administration guide](Running-Mastodon/Administration-guide.md) +- [Tuning Mastodon](Running-Mastodon/Tuning.md) ### Contributing to Mastodon - [Sponsors](Contributing-to-Mastodon/Sponsors.md) diff --git a/docs/Running-Mastodon/Tuning.md b/docs/Running-Mastodon/Tuning.md new file mode 100644 index 000000000..c4acb9927 --- /dev/null +++ b/docs/Running-Mastodon/Tuning.md @@ -0,0 +1,104 @@ +Tuning Mastodon +=============== + +Mastodon has three types of processes: + +- web +- streaming API +- background processing + +By default, the web type spawns two worker processes with 5 threads each, the streaming API is a single thread/process with 10 database pool connections, and background processing spawns one process with 5 threads. + +### Web + +The web process serves short-lived HTTP requests for most of the application. The following environment variables control it: + +- `WEB_CONCURRENCY` controls the number of worker processes +- `MAX_THREADS` controls the number of threads per process + +The default is 2 workers with 5 threads each. Threads share the memory of their parent process. Different processes allocate their own memory each. Threads in Ruby are not native threads, so it's more or less: threads equal concurrency, processes equal parallelism. A larger number of threads maxes out your CPU first, a larger number of processes maxes out your RAM first. + +These values affect how many HTTP requests can be served at the same time. When not enough threads are available, requests are queued until they can be answered. + +For a single-user instance, 1 process with 5 threads should be more than enough. + +### Streaming API + +The streaming API handles long-lived HTTP and WebSockets connections, through which clients receive real-time updates. It is a single-threaded process. By default it has a database connection pool of 10, which means 10 different database queries can run *at the same time*. The database is not heavily used in the streaming API, only for initial authentication of the request, and for some special receiver-specific filter queries when receiving new messages. At the time of writing this value cannot be reconfigured, but mostly doesn't need to. + +If you need to scale up the streaming API, spawn more separate processes on different ports (e.g. 4000, 4001, 4003, etc) and load-balance between them with nginx. + +### Background processing + +Many tasks in Mastodon are delegated to background processing to ensure the HTTP requests are fast, and to prevent HTTP request aborts from affecting the execution of those tasks. Sidekiq is a single process, with a configurable numbero of threads. By default, it is 5. That means, 5 different jobs can be executed at the same time. Others will be queued until they can be processed. + +While the amount of threads in the web process affects the responsiveness of the Mastodon instance to the end-user, the amount of threads allocated to background processing affects how quickly posts can be delivered from the author to anyone else, how soon e-mails are sent out, etc. + +The amount of threads is not controlled by an environment variable in this case, but a command line argument in the invocation of Sidekiq: + + bundle exec sidekiq -c 15 -q default -q mailers -q push + +Would start the sidekiq process with 15 threads. Please mind that each threads needs to be able to connect to the database, which means that the database pool needs to be large enough to support all the threads. The database pool size is controlled with the `DB_POOL` environment variable, and defaults to the value of `MAX_THREADS` (therefore, is 5 by default). + +You might notice that the above command specifies three queues to be processed: + +- "default" contains most tasks such as delivering messages to followers and processing incoming notifications from other instances +- "mailers" contains tasks that send e-mails +- "push" contains tasks that deliver messages to other instances + +If you wish, you could start three different processes for each queue, to ensure that even when there is a lot of tasks of one type, important tasks of other types still get executed in a timely manner. + +___ + +### How to set environment variables +#### With systemd + +In the `.service` file: + +```systemd +... +Environment="WEB_CONCURRENCY=1" +Environment="MAX_THREADS=5" +ExecStart="..." +... +``` + +Don't forget to `sudo systemctl daemon-reload` before restarting the services so that the changes would take effect! + +#### With docker-compose + +Edit `docker-compose.yml`: + +```yml +... + web: + restart: always + build: . + env_file: .env.production + environment: + - WEB_CONCURRENCY=1 + - MAX_THREADS=5 +... +``` + +Re-create the containers with `docker-compose up -d` for the changes to take effect. + +You can also scale the number of containers per "service" (where service is "web", "sidekiq" and "streaming"): + + docker-compose scale web=1 sidekiq=2 streaming=3 + +Realistically the `docker-compose.yml` file needs to be modified a bit further for the above to work, because by default it wants to bind the web container to host port 3000 and streaming container to host port 4000, of either of which there is only one on the host system. However, if you change: + +```yml +ports: + - "3000:3000" +``` + +to simply: + +```yml +ports: + - "3000" +``` + +for each service respectively, Docker will allocate random host ports of the services, allowing multiple containers to run alongside each other. But it will be on you to look up which host ports those are (e.g. with `docker ps`), and they will be different on each container restart. diff --git a/package.json b/package.json index 9f2bd3df9..45702d5f4 100644 --- a/package.json +++ b/package.json @@ -6,51 +6,52 @@ "start": "babel-node ./streaming/index.js --presets es2015,stage-2" }, "dependencies": { - "@kadira/storybook": "^2.24.0", - "axios": "^0.14.0", - "babel-cli": "^6.22.2", + "@kadira/storybook": "^2.35.3", + "axios": "^0.15.3", + "babel-cli": "^6.23.0", "babel-plugin-react-transform": "^2.0.2", "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-plugin-transform-object-rest-spread": "^6.8.0", + "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.11.1", "babel-preset-stage-2": "^6.22.0", "babelify": "^7.3.0", - "browserify": "^13.1.0", + "browserify": "^14.1.0", "browserify-incremental": "^3.1.1", - "bufferutil": "^2.0.0", + "bufferutil": "^2.0.1", "chai": "^3.5.0", - "chai-enzyme": "^0.5.2", - "css-loader": "^0.26.1", + "chai-enzyme": "^0.6.1", + "css-loader": "^0.26.2", "dotenv": "^4.0.0", "emojione": "latest", - "enzyme": "^2.4.1", + "enzyme": "^2.7.1", "es6-promise": "^3.2.1", + "escape-html": "^1.0.3", "eventsource": "^0.2.1", "express": "^4.14.1", "http-link-header": "^0.5.0", "immutable": "^3.8.1", "intl": "^1.2.5", - "jsdom": "^9.6.0", - "mocha": "^3.1.1", - "node-sass": "^4.0.0", + "jsdom": "^9.11.0", + "mocha": "^3.2.0", + "node-sass": "^4.5.0", "npmlog": "^4.0.2", "pg": "^6.1.2", - "react": "^15.3.2", - "react-addons-perf": "^15.3.2", - "react-addons-pure-render-mixin": "^15.3.1", - "react-addons-test-utils": "^15.3.2", + "react": "^15.4.2", + "react-addons-perf": "^15.4.2", + "react-addons-pure-render-mixin": "^15.4.2", + "react-addons-test-utils": "^15.4.2", "react-autosuggest": "^7.0.1", "react-decoration": "^1.4.0", - "react-dom": "^15.3.0", + "react-dom": "^15.4.2", "react-imageloader": "^2.1.0", "react-immutable-proptypes": "^2.1.0", "react-intl": "^2.1.5", "react-motion": "^0.4.5", - "react-notification": "^6.4.0", + "react-notification": "^6.6.0", "react-proxy": "^1.1.8", - "react-redux": "^5.0.1", - "react-redux-loading-bar": "^2.4.1", + "react-redux": "^5.0.3", + "react-redux-loading-bar": "2.4.1", "react-router": "^2.8.0", "react-router-scroll": "^0.3.2", "react-simple-dropdown": "^1.1.4", @@ -58,17 +59,17 @@ "react-toggle": "^2.1.1", "redis": "^2.6.5", "redux": "^3.6.0", - "redux-immutable": "^3.0.8", + "redux-immutable": "^3.1.0", "redux-sounds": "^1.1.1", - "redux-thunk": "^2.1.0", + "redux-thunk": "^2.2.0", "reselect": "^2.5.4", - "sass-loader": "^4.0.2", + "sass-loader": "^6.0.2", "sinon": "^1.17.6", - "style-loader": "^0.13.1", - "utf-8-validate": "^3.0.0", + "style-loader": "^0.13.2", + "utf-8-validate": "^3.0.1", "uuid": "^3.0.1", - "webpack": "^1.14.0", + "webpack": "^2.2.1", "websocket.js": "^0.1.7", - "ws": "^2.0.2" + "ws": "^2.1.0" } } diff --git a/spec/lib/formatter_spec.rb b/spec/lib/formatter_spec.rb index 0db1634e9..4b003b8e5 100644 --- a/spec/lib/formatter_spec.rb +++ b/spec/lib/formatter_spec.rb @@ -17,8 +17,38 @@ RSpec.describe Formatter do end it 'contains a link' do - expect(subject).to match('<a rel="nofollow noopener" target="_blank" href="http://google.com"><span class="invisible">http://</span><span class="">google.com</span><span class="invisible"></span></a>') + expect(subject).to match('<a href="http://google.com" rel="nofollow noopener" target="_blank"><span class="invisible">http://</span><span class="">google.com</span><span class="invisible"></span></a>') end + +=begin + it 'matches a stand-alone medium URL' do + expect(subject.match('https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4')[0]).to eq 'https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4' + end + + it 'matches a stand-alone google URL' do + expect(subject.match('http://google.com')[0]).to eq 'http://google.com' + end + + it 'matches a URL without trailing period' do + expect(subject.match('http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona. ')[0]).to eq 'http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona' + end + + it 'matches a URL without closing paranthesis' do + expect(subject.match('(http://google.com/)')[0]).to eq 'http://google.com' + end + + it 'matches a URL without exclamation point' do + expect(subject.match('http://www.google.com! ')[0]).to eq 'http://www.google.com' + end + + it 'matches a URL with a query string' do + expect(subject.match('https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink')[0]).to eq 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink' + end + + it 'matches a URL with parenthesis in it' do + expect(subject.match('https://en.wikipedia.org/wiki/Diaspora_(software)')[0]).to eq 'https://en.wikipedia.org/wiki/Diaspora_(software)' + end +=end end describe '#reformat' do diff --git a/yarn.lock b/yarn.lock index 89236d45a..a77fe59eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,9 +22,9 @@ version "1.5.0" resolved "https://registry.yarnpkg.com/@kadira/storybook-addons/-/storybook-addons-1.5.0.tgz#f92cd2059282a9b4b8bdac4bef28269f85e40be4" -"@kadira/storybook-channel-postmsg@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@kadira/storybook-channel-postmsg/-/storybook-channel-postmsg-1.0.3.tgz#958d182ca8b8206b8942c0aa586e1f52af47bdcc" +"@kadira/storybook-channel-postmsg@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@kadira/storybook-channel-postmsg/-/storybook-channel-postmsg-2.0.1.tgz#2a9065bf0647c940b8f9a3a7342a3e12e321af72" dependencies: "@kadira/storybook-channel" "^1.1.0" json-stringify-safe "^5.0.1" @@ -33,9 +33,9 @@ version "1.1.0" resolved "https://registry.yarnpkg.com/@kadira/storybook-channel/-/storybook-channel-1.1.0.tgz#806d1cdf2498d11cce09871a6fd27bbb41ed3564" -"@kadira/storybook-ui@^3.6.0": - version "3.6.2" - resolved "https://registry.yarnpkg.com/@kadira/storybook-ui/-/storybook-ui-3.6.2.tgz#04a620665f599c7fb83a7e24449464b8828f0b56" +"@kadira/storybook-ui@^3.10.1": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@kadira/storybook-ui/-/storybook-ui-3.11.0.tgz#a5ccdcc479aa5e08465c58e7df493e37e4b2a14a" dependencies: "@kadira/react-split-pane" "^1.4.0" babel-runtime "^6.5.0" @@ -45,35 +45,39 @@ json-stringify-safe "^5.0.1" keycode "^2.1.1" lodash.pick "^4.2.1" - mantra-core "^1.6.1" + lodash.sortby "^4.7.0" + mantra-core "^1.7.0" + podda "^1.2.1" qs "^6.2.0" react-fuzzy "^0.3.3" react-inspector "^1.1.0" + react-komposer "^2.0.0" react-modal "^1.2.1" redux "^3.5.2" -"@kadira/storybook@^2.24.0": - version "2.24.0" - resolved "https://registry.yarnpkg.com/@kadira/storybook/-/storybook-2.24.0.tgz#31e7ac085f6ac5894fd316bdb986e17938f86cfc" +"@kadira/storybook@^2.35.3": + version "2.35.3" + resolved "https://registry.yarnpkg.com/@kadira/storybook/-/storybook-2.35.3.tgz#8106195e1733623baf60db6adaa678dc29285d12" dependencies: "@kadira/react-split-pane" "^1.4.0" "@kadira/storybook-addon-actions" "^1.0.2" "@kadira/storybook-addon-links" "^1.0.0" "@kadira/storybook-addons" "^1.5.0" - "@kadira/storybook-channel-postmsg" "^1.0.3" - "@kadira/storybook-ui" "^3.6.0" + "@kadira/storybook-channel-postmsg" "^2.0.1" + "@kadira/storybook-ui" "^3.10.1" airbnb-js-shims "^1.0.1" autoprefixer "^6.3.7" babel-core "^6.11.4" babel-loader "^6.2.4" - babel-preset-react-app "^0.2.1" + babel-plugin-react-docgen "^1.4.2" + babel-preset-react-app "^1.0.0" babel-runtime "^6.9.2" case-sensitive-paths-webpack-plugin "^1.1.2" chalk "^1.1.3" commander "^2.9.0" common-tags "^1.3.1" configstore "^2.0.0" - css-loader "0.25.0" + css-loader "^0.26.1" express "^4.13.3" file-loader "^0.9.0" find-cache-dir "^0.1.1" @@ -81,21 +85,19 @@ json-stringify-safe "^5.0.1" json5 "^0.5.0" lodash.pick "^4.2.0" - postcss-loader "0.13.0" + postcss-loader "1.1.0" qs "^6.1.0" react-modal "^1.2.0" - redbox-react "^1.2.2" redux "^3.5.2" request "^2.74.0" serve-favicon "^2.3.0" shelljs "^0.7.4" - stack-source-map "^1.0.5" style-loader "0.13.1" url-loader "^0.5.7" - uuid "^2.0.2" + uuid "^2.0.3" webpack "^1.13.1" webpack-dev-middleware "^1.6.0" - webpack-hot-middleware "^2.10.0" + webpack-hot-middleware "^2.13.2" JSONStream@^0.10.0: version "0.10.0" @@ -111,7 +113,7 @@ JSONStream@^1.0.3: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^1.0.0: +abab@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" @@ -126,17 +128,23 @@ accepts@~1.3.3: mime-types "~2.1.11" negotiator "0.6.1" -acorn-globals@^1.0.4: - version "1.0.9" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" +acorn-dynamic-import@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.1.tgz#23f671eb6e650dab277fef477c321b1178a8cca2" dependencies: - acorn "^2.1.0" + acorn "^4.0.3" + +acorn-globals@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" + dependencies: + acorn "^4.0.4" acorn@^1.0.3: version "1.2.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014" -acorn@^2.1.0, acorn@^2.4.0, acorn@^2.7.0: +acorn@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" @@ -144,6 +152,10 @@ acorn@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" +acorn@^4.0.3, acorn@^4.0.4: + version "4.0.11" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" + airbnb-js-shims@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-1.0.1.tgz#7d5a7d772c8c6fdeb624ea3cef62506091b180b5" @@ -157,6 +169,17 @@ airbnb-js-shims@^1.0.1: string.prototype.padend "^3.0.0" string.prototype.padstart "^3.0.0" +ajv-keywords@^1.1.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0: + version "4.11.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.3.tgz#ce30bdb90d1254f762c75af915fb3a63e7183d22" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -173,9 +196,9 @@ amdefine@>=0.0.4: version "1.0.0" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.0.tgz#fd17474700cb5cc9c2b709f0be9d23ce3c198c33" -ansi-html@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.5.tgz#0dcaa5a081206866bc240a3b773a184ea3b88b64" +ansi-html@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" ansi-regex@^2.0.0: version "2.0.0" @@ -293,9 +316,9 @@ assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -assert@^1.1.1, assert@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.3.0.tgz#03939a622582a812cc202320a0b9a56c9b815849" +assert@^1.1.1, assert@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" dependencies: util "0.10.3" @@ -303,6 +326,10 @@ assertion-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" +ast-types@0.9.5: + version "0.9.5" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.5.tgz#1a660a09945dbceb1f9c9cbb715002617424e04a" + astw@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astw/-/astw-2.0.0.tgz#08121ac8288d35611c0ceec663f6cd545604897d" @@ -321,13 +348,13 @@ async@^0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" -async@^1.3.0, async@^1.5.2: +async@^1.3.0, async@^1.4.2, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.0.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" +async@^2.1.2, async@^2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" dependencies: lodash "^4.14.0" @@ -362,19 +389,19 @@ aws4@^1.2.1: version "1.5.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" -axios@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.14.0.tgz#40f24f2f4e913b9faa43d3a7b2e40ab8729afa90" +axios@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" dependencies: - follow-redirects "0.0.7" + follow-redirects "1.0.0" -babel-cli@^6.22.2: - version "6.22.2" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.22.2.tgz#3f814c8acf52759082b8fedd9627f938936ab559" +babel-cli@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.23.0.tgz#52ff946a2b0f64645c35e7bd5eea267aa0948c0f" dependencies: - babel-core "^6.22.1" - babel-polyfill "^6.22.0" - babel-register "^6.22.0" + babel-core "^6.23.0" + babel-polyfill "^6.23.0" + babel-register "^6.23.0" babel-runtime "^6.22.0" commander "^2.8.1" convert-source-map "^1.1.0" @@ -389,7 +416,7 @@ babel-cli@^6.22.2: optionalDependencies: chokidar "^1.6.1" -babel-code-frame@^6.11.0, babel-code-frame@^6.16.0: +babel-code-frame@^6.11.0: version "6.16.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.16.0.tgz#f90e60da0862909d3ce098733b5d3987c97cb8de" dependencies: @@ -405,19 +432,19 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@^6.0.14, babel-core@^6.14.0, babel-core@^6.22.0, babel-core@^6.22.1: - version "6.22.1" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.22.1.tgz#9c5fd658ba1772d28d721f6d25d968fc7ae21648" +babel-core@^6.0.14, babel-core@^6.23.0: + version "6.23.1" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.22.0" - babel-helpers "^6.22.0" - babel-messages "^6.22.0" - babel-register "^6.22.0" + babel-generator "^6.23.0" + babel-helpers "^6.23.0" + babel-messages "^6.23.0" + babel-register "^6.23.0" babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-traverse "^6.22.1" - babel-types "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.1" + babel-types "^6.23.0" babylon "^6.11.0" convert-source-map "^1.1.0" debug "^2.1.1" @@ -430,43 +457,29 @@ babel-core@^6.0.14, babel-core@^6.14.0, babel-core@^6.22.0, babel-core@^6.22.1: source-map "^0.5.0" babel-core@^6.11.4: - version "6.17.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.17.0.tgz#6c4576447df479e241e58c807e4bc7da4db7f425" + version "6.22.1" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.22.1.tgz#9c5fd658ba1772d28d721f6d25d968fc7ae21648" dependencies: - babel-code-frame "^6.16.0" - babel-generator "^6.17.0" - babel-helpers "^6.16.0" - babel-messages "^6.8.0" - babel-register "^6.16.0" - babel-runtime "^6.9.1" - babel-template "^6.16.0" - babel-traverse "^6.16.0" - babel-types "^6.16.0" + babel-code-frame "^6.22.0" + babel-generator "^6.22.0" + babel-helpers "^6.22.0" + babel-messages "^6.22.0" + babel-register "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.22.0" + babel-traverse "^6.22.1" + babel-types "^6.22.0" babylon "^6.11.0" convert-source-map "^1.1.0" debug "^2.1.1" - json5 "^0.4.0" + json5 "^0.5.0" lodash "^4.2.0" minimatch "^3.0.2" - path-exists "^1.0.0" path-is-absolute "^1.0.0" private "^0.1.6" - shebang-regex "^1.0.0" slash "^1.0.0" source-map "^0.5.0" -babel-generator@^6.17.0: - version "6.17.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.17.0.tgz#b894e3808beef7800f2550635bfe024b6226cf33" - dependencies: - babel-messages "^6.8.0" - babel-runtime "^6.9.0" - babel-types "^6.16.0" - detect-indent "^3.0.1" - jsesc "^1.3.0" - lodash "^4.2.0" - source-map "^0.5.0" - babel-generator@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.22.0.tgz#d642bf4961911a8adc7c692b0c9297f325cda805" @@ -479,6 +492,19 @@ babel-generator@^6.22.0: lodash "^4.2.0" source-map "^0.5.0" +babel-generator@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.23.0.tgz#6b8edab956ef3116f79d8c84c5a3c05f32a74bc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + babel-helper-bindify-decorators@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.22.0.tgz#d7f5bc261275941ac62acfc4e20dacfb8a3fe952" @@ -504,7 +530,7 @@ babel-helper-builder-react-jsx@^6.8.0: esutils "^2.0.0" lodash "^4.2.0" -babel-helper-call-delegate@^6.22.0: +babel-helper-call-delegate@^6.22.0, babel-helper-call-delegate@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" dependencies: @@ -549,7 +575,7 @@ babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.8.0: babel-traverse "^6.22.0" babel-types "^6.22.0" -babel-helper-get-function-arity@^6.22.0: +babel-helper-get-function-arity@^6.22.0, babel-helper-get-function-arity@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" dependencies: @@ -599,13 +625,6 @@ babel-helper-replace-supers@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" -babel-helpers@^6.16.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.16.0.tgz#1095ec10d99279460553e67eb3eee9973d3867e3" - dependencies: - babel-runtime "^6.0.0" - babel-template "^6.16.0" - babel-helpers@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.22.0.tgz#d275f55f2252b8101bff07bc0c556deda657392c" @@ -613,6 +632,13 @@ babel-helpers@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" +babel-helpers@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-loader@^6.2.4: version "6.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.2.5.tgz#576d548520689a5e6b70c65b85d76af1ffedd005" @@ -627,18 +653,26 @@ babel-messages@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-messages@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.8.0.tgz#bf504736ca967e6d65ef0adb5a2a5f947c8e0eb9" +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" dependencies: - babel-runtime "^6.0.0" + babel-runtime "^6.22.0" -babel-plugin-check-es2015-constants@^6.22.0: +babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" dependencies: babel-runtime "^6.22.0" +babel-plugin-react-docgen@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-1.4.2.tgz#04c02133b84b6cc182d35de2162f15764da03e7c" + dependencies: + babel-types "^6.16.0" + lodash "4.x.x" + react-docgen "^2.12.1" + babel-plugin-react-transform@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz#515bbfa996893981142d90b1f9b1635de2995109" @@ -681,7 +715,7 @@ babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" -babel-plugin-syntax-trailing-function-commas@^6.22.0, babel-plugin-syntax-trailing-function-commas@^6.8.0: +babel-plugin-syntax-trailing-function-commas@^6.13.0, babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" @@ -693,7 +727,7 @@ babel-plugin-transform-async-generator-functions@^6.22.0: babel-plugin-syntax-async-generators "^6.5.0" babel-runtime "^6.22.0" -babel-plugin-transform-async-to-generator@^6.16.0, babel-plugin-transform-async-to-generator@^6.22.0: +babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" dependencies: @@ -701,9 +735,9 @@ babel-plugin-transform-async-to-generator@^6.16.0, babel-plugin-transform-async- babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-class-properties@6.11.5: - version "6.11.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.11.5.tgz#429c7a4e7d8ac500448eb14ec502604bc568c91c" +babel-plugin-transform-class-properties@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.16.0.tgz#969bca24d34e401d214f36b8af5c1346859bc904" dependencies: babel-helper-function-name "^6.8.0" babel-plugin-syntax-class-properties "^6.8.0" @@ -736,19 +770,19 @@ babel-plugin-transform-decorators@^6.22.0: babel-template "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-arrow-functions@^6.22.0: +babel-plugin-transform-es2015-arrow-functions@^6.22.0, babel-plugin-transform-es2015-arrow-functions@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0, babel-plugin-transform-es2015-block-scoped-functions@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoping@^6.14.0, babel-plugin-transform-es2015-block-scoping@^6.22.0: +babel-plugin-transform-es2015-block-scoping@^6.22.0, babel-plugin-transform-es2015-block-scoping@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.22.0.tgz#00d6e3a0bebdcfe7536b9d653b44a9141e63e47e" dependencies: @@ -758,7 +792,7 @@ babel-plugin-transform-es2015-block-scoping@^6.14.0, babel-plugin-transform-es20 babel-types "^6.22.0" lodash "^4.2.0" -babel-plugin-transform-es2015-classes@^6.22.0: +babel-plugin-transform-es2015-classes@^6.22.0, babel-plugin-transform-es2015-classes@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.22.0.tgz#54d44998fd823d9dca15292324161c331c1b6f14" dependencies: @@ -772,33 +806,39 @@ babel-plugin-transform-es2015-classes@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-computed-properties@^6.22.0: +babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7" dependencies: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-destructuring@^6.22.0: +babel-plugin-transform-es2015-destructuring@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.16.0.tgz#050fe0866f5d53b36062ee10cdf5bfe64f929627" + dependencies: + babel-runtime "^6.9.0" + +babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.22.0.tgz#8e0af2f885a0b2cf999d47c4c1dd23ce88cfa4c6" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: +babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b" dependencies: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.8.0: +babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.22.0.tgz#180467ad63aeea592a1caeee4bf1c8b3e2616265" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.22.0: +babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" dependencies: @@ -806,13 +846,13 @@ babel-plugin-transform-es2015-function-name@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-literals@^6.22.0: +babel-plugin-transform-es2015-literals@^6.22.0, babel-plugin-transform-es2015-literals@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.22.0: +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.22.0.tgz#bf69cd34889a41c33d90dfb740e0091ccff52f21" dependencies: @@ -820,7 +860,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-modules-commonjs@^6.22.0: +babel-plugin-transform-es2015-modules-commonjs@^6.22.0, babel-plugin-transform-es2015-modules-commonjs@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.22.0.tgz#6ca04e22b8e214fb50169730657e7a07dc941145" dependencies: @@ -829,7 +869,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.22.0: babel-template "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-modules-systemjs@^6.22.0: +babel-plugin-transform-es2015-modules-systemjs@^6.12.0, babel-plugin-transform-es2015-modules-systemjs@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.22.0.tgz#810cd0cd025a08383b84236b92c6e31f88e644ad" dependencies: @@ -837,7 +877,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-modules-umd@^6.22.0: +babel-plugin-transform-es2015-modules-umd@^6.12.0, babel-plugin-transform-es2015-modules-umd@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.22.0.tgz#60d0ba3bd23258719c64391d9bf492d648dc0fae" dependencies: @@ -845,14 +885,25 @@ babel-plugin-transform-es2015-modules-umd@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-object-super@^6.22.0: +babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc" dependencies: babel-helper-replace-supers "^6.22.0" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.22.0: +babel-plugin-transform-es2015-parameters@6.17.0: + version "6.17.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.17.0.tgz#e06d30cef897f46adb4734707bbe128a0d427d58" + dependencies: + babel-helper-call-delegate "^6.8.0" + babel-helper-get-function-arity "^6.8.0" + babel-runtime "^6.9.0" + babel-template "^6.16.0" + babel-traverse "^6.16.0" + babel-types "^6.16.0" + +babel-plugin-transform-es2015-parameters@^6.22.0, babel-plugin-transform-es2015-parameters@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.22.0.tgz#57076069232019094f27da8c68bb7162fe208dbb" dependencies: @@ -863,20 +914,20 @@ babel-plugin-transform-es2015-parameters@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: +babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723" dependencies: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-spread@^6.22.0: +babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.22.0: +babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" dependencies: @@ -884,19 +935,19 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-template-literals@^6.22.0: +babel-plugin-transform-es2015-template-literals@^6.22.0, babel-plugin-transform-es2015-template-literals@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: +babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.22.0.tgz#87faf2336d3b6a97f68c4d906b0cd0edeae676e1" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-unicode-regex@^6.22.0: +babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.3.13: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" dependencies: @@ -904,7 +955,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.3.13: +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" dependencies: @@ -919,27 +970,20 @@ babel-plugin-transform-flow-strip-types@^6.3.13: babel-plugin-syntax-flow "^6.8.0" babel-runtime "^6.0.0" -babel-plugin-transform-object-rest-spread@6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.8.0.tgz#03d1308e257a9d8e1a815ae1fd3db21bdebf08d9" +babel-plugin-transform-object-rest-spread@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.16.0.tgz#db441d56fffc1999052fdebe2e2f25ebd28e36a9" dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.0.0" -babel-plugin-transform-object-rest-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.22.0.tgz#1d419b55e68d2e4f64a5ff3373bd67d73c8e83bc" +babel-plugin-transform-object-rest-spread@^6.22.0, babel-plugin-transform-object-rest-spread@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-object-rest-spread@^6.8.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.16.0.tgz#db441d56fffc1999052fdebe2e2f25ebd28e36a9" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.0.0" - babel-plugin-transform-react-constant-elements@6.9.1: version "6.9.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-constant-elements/-/babel-plugin-transform-react-constant-elements-6.9.1.tgz#125b86d96cb322e2139b607fd749ad5fbb17f005" @@ -974,21 +1018,15 @@ babel-plugin-transform-react-jsx@^6.3.13: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.0.0" -babel-plugin-transform-regenerator@6.14.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.14.0.tgz#119119b20c8b4283f6c77f0170d404c3c654bec8" +babel-plugin-transform-regenerator@6.16.1: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz#a75de6b048a14154aae14b0122756c5bed392f59" dependencies: - babel-core "^6.14.0" - babel-plugin-syntax-async-functions "^6.8.0" - babel-plugin-transform-es2015-block-scoping "^6.14.0" - babel-plugin-transform-es2015-for-of "^6.8.0" babel-runtime "^6.9.0" - babel-traverse "^6.14.0" - babel-types "^6.14.0" - babylon "^6.9.0" + babel-types "^6.16.0" private "~0.1.5" -babel-plugin-transform-regenerator@^6.22.0: +babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.6.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" dependencies: @@ -1007,15 +1045,48 @@ babel-plugin-transform-strict-mode@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-polyfill@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.22.0.tgz#1ac99ebdcc6ba4db1e2618c387b2084a82154a3b" +babel-polyfill@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" dependencies: babel-runtime "^6.22.0" core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-preset-es2015@^6.14.0, babel-preset-es2015@^6.22.0: +babel-preset-env@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-0.0.6.tgz#cda63a020069098fad12272a7a447a7c5bafb3c8" + dependencies: + babel-plugin-check-es2015-constants "^6.3.13" + babel-plugin-syntax-trailing-function-commas "^6.13.0" + babel-plugin-transform-async-to-generator "^6.8.0" + babel-plugin-transform-es2015-arrow-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoped-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoping "^6.6.0" + babel-plugin-transform-es2015-classes "^6.6.0" + babel-plugin-transform-es2015-computed-properties "^6.3.13" + babel-plugin-transform-es2015-destructuring "^6.6.0" + babel-plugin-transform-es2015-duplicate-keys "^6.6.0" + babel-plugin-transform-es2015-for-of "^6.6.0" + babel-plugin-transform-es2015-function-name "^6.3.13" + babel-plugin-transform-es2015-literals "^6.3.13" + babel-plugin-transform-es2015-modules-amd "^6.8.0" + babel-plugin-transform-es2015-modules-commonjs "^6.6.0" + babel-plugin-transform-es2015-modules-systemjs "^6.12.0" + babel-plugin-transform-es2015-modules-umd "^6.12.0" + babel-plugin-transform-es2015-object-super "^6.3.13" + babel-plugin-transform-es2015-parameters "^6.6.0" + babel-plugin-transform-es2015-shorthand-properties "^6.3.13" + babel-plugin-transform-es2015-spread "^6.3.13" + babel-plugin-transform-es2015-sticky-regex "^6.3.13" + babel-plugin-transform-es2015-template-literals "^6.6.0" + babel-plugin-transform-es2015-typeof-symbol "^6.6.0" + babel-plugin-transform-es2015-unicode-regex "^6.3.13" + babel-plugin-transform-exponentiation-operator "^6.8.0" + babel-plugin-transform-regenerator "^6.6.0" + browserslist "^1.4.0" + +babel-preset-es2015@^6.16.0, babel-preset-es2015@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz#af5a98ecb35eb8af764ad8a5a05eb36dc4386835" dependencies: @@ -1044,55 +1115,46 @@ babel-preset-es2015@^6.14.0, babel-preset-es2015@^6.22.0: babel-plugin-transform-es2015-unicode-regex "^6.22.0" babel-plugin-transform-regenerator "^6.22.0" -babel-preset-es2016@^6.11.3: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.16.0.tgz#c7daf5feedeee99c867813bdf0d573d94ca12812" +babel-preset-es2016@^6.16.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.22.0.tgz#b061aaa3983d40c9fbacfa3743b5df37f336156c" dependencies: - babel-plugin-transform-exponentiation-operator "^6.3.13" + babel-plugin-transform-exponentiation-operator "^6.22.0" -babel-preset-es2017@^6.14.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.16.0.tgz#536c6287778a758948ddd092b466b6ef50b786fa" +babel-preset-es2017@^6.16.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.22.0.tgz#de2f9da5a30c50d293fb54a0ba15d6ddc573f0f2" dependencies: - babel-plugin-syntax-trailing-function-commas "^6.8.0" - babel-plugin-transform-async-to-generator "^6.16.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" -babel-preset-latest@6.14.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.14.0.tgz#1684ace816c998ce72d20e5c5f710329d40f9246" +babel-preset-latest@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.16.0.tgz#5b87e19e250bb1213f13af4ec9dc7a51d53f388d" dependencies: - babel-preset-es2015 "^6.14.0" - babel-preset-es2016 "^6.11.3" - babel-preset-es2017 "^6.14.0" + babel-preset-es2015 "^6.16.0" + babel-preset-es2016 "^6.16.0" + babel-preset-es2017 "^6.16.0" -babel-preset-react-app@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-0.2.1.tgz#bf94623382adc2c4c7e098a66229c6671a79f842" +babel-preset-react-app@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-1.0.0.tgz#e7613500859d96f177ba7a38a3ed0a923ee50da8" dependencies: - babel-plugin-transform-class-properties "6.11.5" - babel-plugin-transform-object-rest-spread "6.8.0" + babel-plugin-transform-class-properties "6.16.0" + babel-plugin-transform-es2015-destructuring "6.16.0" + babel-plugin-transform-es2015-parameters "6.17.0" + babel-plugin-transform-object-rest-spread "6.16.0" babel-plugin-transform-react-constant-elements "6.9.1" babel-plugin-transform-react-jsx-self "6.11.0" babel-plugin-transform-react-jsx-source "6.9.0" - babel-plugin-transform-regenerator "6.14.0" + babel-plugin-transform-regenerator "6.16.1" babel-plugin-transform-runtime "6.15.0" - babel-preset-latest "6.14.0" - babel-preset-react "6.11.1" + babel-preset-env "0.0.6" + babel-preset-latest "6.16.0" + babel-preset-react "6.16.0" babel-runtime "6.11.6" -babel-preset-react@6.11.1: - version "6.11.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.11.1.tgz#98ac2bd3c1b76f3062ae082580eade154a19b590" - dependencies: - babel-plugin-syntax-flow "^6.3.13" - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-flow-strip-types "^6.3.13" - babel-plugin-transform-react-display-name "^6.3.13" - babel-plugin-transform-react-jsx "^6.3.13" - babel-plugin-transform-react-jsx-self "^6.11.0" - babel-plugin-transform-react-jsx-source "^6.3.13" - -babel-preset-react@^6.11.1: +babel-preset-react@6.16.0, babel-preset-react@^6.11.1: version "6.16.0" resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.16.0.tgz#aa117d60de0928607e343c4828906e4661824316" dependencies: @@ -1123,11 +1185,11 @@ babel-preset-stage-3@^6.22.0: babel-plugin-transform-exponentiation-operator "^6.22.0" babel-plugin-transform-object-rest-spread "^6.22.0" -babel-register@^6.16.0, babel-register@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.22.0.tgz#a61dd83975f9ca4a9e7d6eff3059494cd5ea4c63" +babel-register@^6.22.0, babel-register@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.23.0.tgz#c9aa3d4cca94b51da34826c4a0f9e08145d74ff3" dependencies: - babel-core "^6.22.0" + babel-core "^6.23.0" babel-runtime "^6.22.0" core-js "^2.4.0" home-or-tmp "^2.0.0" @@ -1142,27 +1204,20 @@ babel-runtime@6.11.6: core-js "^2.4.0" regenerator-runtime "^0.9.5" -babel-runtime@6.x.x, babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.5.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1: +babel-runtime@6.x.x, babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.5.0, babel-runtime@^6.9.0, babel-runtime@^6.9.1, babel-runtime@^6.9.2: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.22.0.tgz#1cf8b4ac67c77a4ddb0db2ae1f74de52ac4ca611" dependencies: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-runtime@^6.9.2: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.18.0.tgz#0f4177ffd98492ef13b9f823e9994a02584c9078" +babel-template@^6.16.0, babel-template@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.9.5" - -babel-template@^6.16.0, babel-template@^6.3.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.16.0.tgz#e149dd1a9f03a35f817ddbc4d0481988e7ebc8ca" - dependencies: - babel-runtime "^6.9.0" - babel-traverse "^6.16.0" - babel-types "^6.16.0" + babel-runtime "^6.22.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" babylon "^6.11.0" lodash "^4.2.0" @@ -1176,35 +1231,45 @@ babel-template@^6.22.0: babylon "^6.11.0" lodash "^4.2.0" -babel-traverse@^6.14.0, babel-traverse@^6.22.0, babel-traverse@^6.22.1: - version "6.22.1" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.22.1.tgz#3b95cd6b7427d6f1f757704908f2fc9748a5f59f" +babel-template@^6.3.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.16.0.tgz#e149dd1a9f03a35f817ddbc4d0481988e7ebc8ca" + dependencies: + babel-runtime "^6.9.0" + babel-traverse "^6.16.0" + babel-types "^6.16.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.16.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: + version "6.23.1" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" dependencies: babel-code-frame "^6.22.0" - babel-messages "^6.22.0" + babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.23.0" babylon "^6.15.0" debug "^2.2.0" globals "^9.0.0" invariant "^2.2.0" lodash "^4.2.0" -babel-traverse@^6.16.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.16.0.tgz#fba85ae1fd4d107de9ce003149cc57f53bef0c4f" +babel-traverse@^6.22.1: + version "6.22.1" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.22.1.tgz#3b95cd6b7427d6f1f757704908f2fc9748a5f59f" dependencies: - babel-code-frame "^6.16.0" - babel-messages "^6.8.0" - babel-runtime "^6.9.0" - babel-types "^6.16.0" - babylon "^6.11.0" + babel-code-frame "^6.22.0" + babel-messages "^6.22.0" + babel-runtime "^6.22.0" + babel-types "^6.22.0" + babylon "^6.15.0" debug "^2.2.0" - globals "^8.3.0" + globals "^9.0.0" invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.14.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.9.0: +babel-types@^6.16.0, babel-types@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.22.0.tgz#2a447e8d0ea25d2512409e4175479fd78cc8b1db" dependencies: @@ -1213,11 +1278,11 @@ babel-types@^6.14.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.9. lodash "^4.2.0" to-fast-properties "^1.0.1" -babel-types@^6.16.0: - version "6.16.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.16.0.tgz#71cca1dbe5337766225c5c193071e8ebcbcffcfe" +babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.9.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" dependencies: - babel-runtime "^6.9.1" + babel-runtime "^6.22.0" esutils "^2.0.2" lodash "^4.2.0" to-fast-properties "^1.0.1" @@ -1229,7 +1294,7 @@ babelify@^7.3.0: babel-core "^6.0.14" object-assign "^4.0.0" -babylon@^6.11.0, babylon@^6.9.0: +babylon@^6.11.0: version "6.11.4" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.11.4.tgz#75e1f52187efa0cde5a541a7f7fdda38f6eb5bd2" @@ -1237,6 +1302,10 @@ babylon@^6.15.0: version "6.15.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e" +babylon@~5.8.3: + version "5.8.38" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-5.8.38.tgz#ec9b120b11bf6ccd4173a18bf217e60b79859ffd" + backoff@^2.4.1: version "2.5.0" resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" @@ -1273,7 +1342,7 @@ bindings@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" -bl@~1.1.2: +bl@^1.0.0, bl@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" dependencies: @@ -1412,16 +1481,17 @@ browserify-zlib@^0.1.4, browserify-zlib@~0.1.2: dependencies: pako "~0.2.0" -browserify@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-13.1.0.tgz#d81a018e98dd7ca706ec04253d20f8a03b2af8ae" +browserify@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.1.0.tgz#0508cc1e7bf4c152312c2fa523e676c0b0b92311" dependencies: JSONStream "^1.0.3" - assert "~1.3.0" + assert "^1.4.0" browser-pack "^6.0.1" browser-resolve "^1.11.0" browserify-zlib "~0.1.2" - buffer "^4.1.0" + buffer "^5.0.2" + cached-path-relative "^1.0.0" concat-stream "~1.5.1" console-browserify "^1.1.0" constants-browserify "~1.0.0" @@ -1431,14 +1501,14 @@ browserify@^13.1.0: domain-browser "~1.1.0" duplexer2 "~0.1.2" events "~1.1.0" - glob "^5.0.15" + glob "^7.1.0" has "^1.0.0" htmlescape "^1.1.0" https-browserify "~0.0.0" inherits "~2.0.1" insert-module-globals "^7.0.0" labeled-stream-splicer "^2.0.0" - module-deps "^4.0.2" + module-deps "^4.0.8" os-browserify "~0.1.1" parents "^1.0.1" path-browserify "~0.0.0" @@ -1449,7 +1519,7 @@ browserify@^13.1.0: readable-stream "^2.0.2" resolve "^1.1.4" shasum "^1.0.0" - shell-quote "^1.4.3" + shell-quote "^1.6.1" stream-browserify "^2.0.0" stream-http "^2.0.0" string_decoder "~0.10.0" @@ -1463,7 +1533,7 @@ browserify@^13.1.0: vm-browserify "~0.0.1" xtend "^4.0.0" -browserslist@~1.4.0: +browserslist@^1.4.0, browserslist@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.4.0.tgz#9cfdcf5384d9158f5b70da2aa00b30e8ff019049" dependencies: @@ -1481,7 +1551,7 @@ buffer-xor@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" -buffer@^4.1.0, buffer@^4.9.0: +buffer@^4.3.0, buffer@^4.9.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" dependencies: @@ -1489,12 +1559,20 @@ buffer@^4.1.0, buffer@^4.9.0: ieee754 "^1.1.4" isarray "^1.0.0" -bufferutil@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-2.0.0.tgz#6588ed4bafa300798b26dc048494a51abde83507" +buffer@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.5.tgz#35c9393244a90aff83581063d16f0882cecc9418" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +bufferutil@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-2.0.1.tgz#8de37f5a300730c305fc3edd9f93348ee8a46288" dependencies: bindings "~1.2.1" nan "~2.5.0" + prebuild-install "~2.1.0" builtin-modules@^1.0.0: version "1.1.1" @@ -1504,6 +1582,10 @@ builtin-status-codes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz#6f22003baacf003ccd287afe6872151fddc58579" +cached-path-relative@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -1542,12 +1624,12 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chai-enzyme@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/chai-enzyme/-/chai-enzyme-0.5.2.tgz#0ace3e94c3d1b52556ffab50c77478875c633a5b" +chai-enzyme@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/chai-enzyme/-/chai-enzyme-0.6.1.tgz#585c963c6ea1331446efd12ee8391e807d758620" dependencies: - html "1.0.0" - react-element-to-jsx-string "^3.0.0" + html "^1.0.0" + react-element-to-jsx-string "^5.0.0" chai@^3.5.0: version "3.5.0" @@ -1567,19 +1649,28 @@ chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -cheerio@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35" +cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" entities "~1.1.1" - htmlparser2 "~3.8.1" - lodash "^4.1.0" - optionalDependencies: - jsdom "^7.0.2" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" -chokidar@^1.0.0, chokidar@^1.6.1: +chokidar@^1.0.0, chokidar@^1.4.3, chokidar@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" dependencies: @@ -1594,6 +1685,10 @@ chokidar@^1.0.0, chokidar@^1.6.1: optionalDependencies: fsevents "^1.0.0" +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + cipher-base@^1.0.0, cipher-base@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07" @@ -1626,10 +1721,24 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" +clone-deep@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" + dependencies: + for-own "^0.1.3" + is-plain-object "^2.0.1" + kind-of "^3.0.2" + lazy-cache "^1.0.3" + shallow-clone "^0.1.2" + clone@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + coa@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.1.tgz#7f959346cfc8719e3f7233cd6852854a7c67d8a3" @@ -1755,6 +1864,10 @@ content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" +content-type-parser@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94" + content-type@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" @@ -1787,6 +1900,17 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.1.1.tgz#817f2c2039347a1e9bf7d090c0923e53f749ca82" + dependencies: + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.1.0" + os-homedir "^1.0.1" + parse-json "^2.2.0" + require-from-string "^1.1.0" + create-ecdh@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" @@ -1832,7 +1956,7 @@ crypto-browserify@3.3.0: ripemd160 "0.2.0" sha.js "2.2.6" -crypto-browserify@^3.0.0: +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522" dependencies: @@ -1851,31 +1975,14 @@ css-color-names@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" -css-loader@0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.25.0.tgz#c3febc8ce28f4c83576b6b13707f47f90c390223" - dependencies: - babel-code-frame "^6.11.0" - css-selector-tokenizer "^0.6.0" - cssnano ">=2.6.1 <4" - loader-utils "~0.2.2" - lodash.camelcase "^3.0.1" - object-assign "^4.0.1" - postcss "^5.0.6" - postcss-modules-extract-imports "^1.0.0" - postcss-modules-local-by-default "^1.0.1" - postcss-modules-scope "^1.0.0" - postcss-modules-values "^1.1.0" - source-list-map "^0.1.4" - -css-loader@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.26.1.tgz#2ba7f20131b93597496b3e9bb500785a49cd29ea" +css-loader@^0.26.1, css-loader@^0.26.2: + version "0.26.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.26.2.tgz#a9cd4c2b1a559b45d8efc04fc311ab5d2aaccb9d" dependencies: babel-code-frame "^6.11.0" css-selector-tokenizer "^0.7.0" cssnano ">=2.6.1 <4" - loader-utils "~0.2.2" + loader-utils "^1.0.2" lodash.camelcase "^4.3.0" object-assign "^4.0.1" postcss "^5.0.6" @@ -1883,7 +1990,7 @@ css-loader@^0.26.1: postcss-modules-local-by-default "^1.0.1" postcss-modules-scope "^1.0.0" postcss-modules-values "^1.1.0" - source-list-map "^0.1.4" + source-list-map "^0.1.7" css-select@~1.2.0: version "1.2.0" @@ -1962,11 +2069,11 @@ csso@~2.2.1: clap "^1.0.9" source-map "^0.5.3" -cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.1.tgz#c9e37ef2490e64f6d1baa10fda852257082c25d3" +cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" -"cssstyle@>= 0.2.29 < 0.3.0", "cssstyle@>= 0.2.36 < 0.3.0": +"cssstyle@>= 0.2.37 < 0.3.0": version "0.2.37" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" dependencies: @@ -2065,14 +2172,6 @@ destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" -detect-indent@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-3.0.1.tgz#9dc5e5ddbceef8325764b9451b02bc6d54084f75" - dependencies: - get-stdin "^4.0.1" - minimist "^1.1.0" - repeating "^1.1.0" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -2098,6 +2197,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + dom-helpers@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-2.4.0.tgz#9bb4b245f637367b1fa670274272aa28fe06c367" @@ -2113,17 +2219,21 @@ domain-browser@^1.1.1, domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" -domelementtype@1, domelementtype@~1.1.1: +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" -domhandler@2.3: +domhandler@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" dependencies: domelementtype "1" -domutils@1.5, domutils@1.5.1: +domutils@1.5.1, domutils@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" dependencies: @@ -2195,6 +2305,21 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" + dependencies: + once "~1.3.0" + +enhanced-resolve@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + object-assign "^4.0.1" + tapable "^0.2.5" + enhanced-resolve@~0.9.0: version "0.9.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" @@ -2203,24 +2328,23 @@ enhanced-resolve@~0.9.0: memory-fs "^0.2.0" tapable "^0.1.8" -entities@1.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" - -entities@~1.1.1: +entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -enzyme@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-2.4.1.tgz#90fa9861d982d0ceb92a9fd57e38426a2f74d3b1" +enzyme@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-2.7.1.tgz#76370e1d99e91f73091bb8c4314b7c128cc2d621" dependencies: - cheerio "^0.20.0" + cheerio "^0.22.0" + function.prototype.name "^1.0.0" is-subset "^0.1.1" - lodash "^4.13.1" + lodash "^4.17.2" object-is "^1.0.1" - object.assign "^4.0.3" + object.assign "^4.0.4" + object.entries "^1.0.3" object.values "^1.0.3" + uuid "^2.0.3" errno@^0.1.3: version "0.1.4" @@ -2234,12 +2358,6 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -error-stack-parser@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-1.3.6.tgz#e0e73b93e417138d1cd7c0b746b1a4a14854c292" - dependencies: - stackframe "^0.3.1" - es-abstract@^1.3.2, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1: version "1.6.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.6.1.tgz#bb8a2064120abcf928a086ea3d9043114285ec99" @@ -2291,7 +2409,7 @@ es6-symbol@3, es6-symbol@^3.0.2, es6-symbol@~3.1: d "~0.1.1" es5-ext "~0.10.11" -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2314,6 +2432,10 @@ esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +esprima@~3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" @@ -2358,6 +2480,10 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +expand-template@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" + express@^4.13.3, express@^4.14.1: version "4.14.1" resolved "https://registry.yarnpkg.com/express/-/express-4.14.1.tgz#646c237f766f148c2120aff073817b9e4d7e0d33" @@ -2411,7 +2537,7 @@ fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" -fbjs@^0.8.4: +fbjs@^0.8.1, fbjs@^0.8.4: version "0.8.5" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.5.tgz#f69ba8a876096cb1b9bffe4d7c1e71c19d39d008" dependencies: @@ -2472,14 +2598,13 @@ flatten@1.0.2, flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" -follow-redirects@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-0.0.7.tgz#34b90bab2a911aa347571da90f22bd36ecd8a919" +follow-redirects@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37" dependencies: debug "^2.2.0" - stream-consume "^0.1.0" -for-in@^0.1.5: +for-in@^0.1.3, for-in@^0.1.5: version "0.1.6" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" @@ -2505,6 +2630,14 @@ form-data@~2.0.0: combined-stream "^1.0.5" mime-types "^2.1.11" +form-data@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + formatio@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" @@ -2555,6 +2688,14 @@ function-bind@^1.0.2, function-bind@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" +function.prototype.name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.0.0.tgz#5f523ca64e491a5f95aba80cc1e391080a14482e" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.0" + is-callable "^1.1.2" + fuse.js@^2.2.0: version "2.5.0" resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.5.0.tgz#98295c2ac1684edbba22250d7049cb6f033e95ce" @@ -2625,6 +2766,10 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -2638,7 +2783,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.0.5, glob@^7.0.0, glob@^7.0.3: +glob@7.0.5, glob@^7.0.0: version "7.0.5" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" dependencies: @@ -2649,17 +2794,7 @@ glob@7.0.5, glob@^7.0.0, glob@^7.0.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.5, glob@~7.1.1: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@~7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -2670,10 +2805,6 @@ glob@^7.0.5, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^8.3.0: - version "8.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-8.18.0.tgz#93d4a62bdcac38cfafafc47d6b034768cb0ffcb4" - globals@^9.0.0: version "9.14.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034" @@ -2782,11 +2913,17 @@ html-comment-regex@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" +html-encoding-sniffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da" + dependencies: + whatwg-encoding "^1.0.1" + html-entities@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2" -html@1.0.0: +html@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/html/-/html-1.0.0.tgz#a544fa9ea5492bfb3a2cca8210a10be7b5af1f61" dependencies: @@ -2796,15 +2933,16 @@ htmlescape@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" -htmlparser2@~3.8.1: - version "3.8.3" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" +htmlparser2@^3.9.1: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" dependencies: - domelementtype "1" - domhandler "2.3" - domutils "1.5" - entities "1.0" - readable-stream "1.1" + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" http-errors@~1.5.1: version "1.5.1" @@ -2814,7 +2952,7 @@ http-errors@~1.5.1: setprototypeof "1.0.2" statuses ">= 1.3.1 < 2" -http-link-header: +http-link-header@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-0.5.0.tgz#68598d92c55d3dac7d3e6ae405142fecf7bd3303" @@ -2830,7 +2968,7 @@ https-browserify@0.0.1, https-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" -iconv-lite@^0.4.13, iconv-lite@~0.4.13: +iconv-lite@0.4.13, iconv-lite@~0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" @@ -2976,7 +3114,7 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.1, is-callable@^1.1.3: +is-callable@^1.1.1, is-callable@^1.1.2, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" @@ -3099,14 +3237,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -isarray@0.0.1, isarray@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isexe@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" @@ -3154,7 +3292,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@~3.6.1: +js-yaml@^3.4.3, js-yaml@~3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" dependencies: @@ -3165,47 +3303,29 @@ jsbn@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" -jsdom@^7.0.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" +jsdom@^9.11.0: + version "9.11.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.11.0.tgz#a95b0304e521a2ca5a63c6ea47bf7708a7a84591" dependencies: - abab "^1.0.0" - acorn "^2.4.0" - acorn-globals "^1.0.4" - cssom ">= 0.3.0 < 0.4.0" - cssstyle ">= 0.2.29 < 0.3.0" - escodegen "^1.6.1" - nwmatcher ">= 1.3.7 < 2.0.0" - parse5 "^1.5.1" - request "^2.55.0" - sax "^1.1.4" - symbol-tree ">= 3.1.0 < 4.0.0" - tough-cookie "^2.2.0" - webidl-conversions "^2.0.0" - whatwg-url-compat "~0.6.5" - xml-name-validator ">= 2.0.1 < 3.0.0" - -jsdom@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.6.0.tgz#e0e9b15ba07e90b1d9ec083f9bedee0f6800a4fb" - dependencies: - abab "^1.0.0" - acorn "^2.4.0" - acorn-globals "^1.0.4" + abab "^1.0.3" + acorn "^4.0.4" + acorn-globals "^3.1.0" array-equal "^1.0.0" - cssom ">= 0.3.0 < 0.4.0" - cssstyle ">= 0.2.36 < 0.3.0" + content-type-parser "^1.0.1" + cssom ">= 0.3.2 < 0.4.0" + cssstyle ">= 0.2.37 < 0.3.0" escodegen "^1.6.1" - iconv-lite "^0.4.13" - nwmatcher ">= 1.3.7 < 2.0.0" + html-encoding-sniffer "^1.0.1" + nwmatcher ">= 1.3.9 < 2.0.0" parse5 "^1.5.1" - request "^2.55.0" - sax "^1.1.4" - symbol-tree ">= 3.1.0 < 4.0.0" - tough-cookie "^2.3.1" - webidl-conversions "^3.0.1" - whatwg-url "^3.0.0" - xml-name-validator ">= 2.0.1 < 3.0.0" + request "^2.79.0" + sax "^1.2.1" + symbol-tree "^3.2.1" + tough-cookie "^2.3.2" + webidl-conversions "^4.0.0" + whatwg-encoding "^1.0.1" + whatwg-url "^4.3.0" + xml-name-validator "^2.0.1" jsesc@^1.3.0: version "1.3.0" @@ -3223,6 +3343,12 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + json-stable-stringify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" @@ -3237,10 +3363,6 @@ json3@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" -json5@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" - json5@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.0.tgz#9b20715b026cbe3778fd769edccd822d8332a5b2" @@ -3273,6 +3395,12 @@ keycode@^2.1.1: version "2.1.7" resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.7.tgz#7b9255919f6cff562b09a064d222dca70b020f5c" +kind-of@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" + dependencies: + is-buffer "^1.0.2" + kind-of@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74" @@ -3287,6 +3415,10 @@ labeled-stream-splicer@^2.0.0: isarray "~0.0.1" stream-splicer "^2.0.0" +lazy-cache@^0.2.3: + version "0.2.7" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" + lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -3320,7 +3452,11 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.2.7, loader-utils@~0.2.2, loader-utils@~0.2.5: +loader-runner@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" + +loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.7, loader-utils@~0.2.5: version "0.2.16" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d" dependencies: @@ -3329,6 +3465,14 @@ loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0. json5 "^0.5.0" object-assign "^4.0.1" +loader-utils@^1.0.1, loader-utils@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.0.2.tgz#a9f923c865a974623391a8602d031137fad74830" + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + lodash-es@^4.2.0, lodash-es@^4.2.1: version "4.16.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.16.4.tgz#4dc3e2cf33a8c343028aa7f7e06d1c9697042599" @@ -3360,13 +3504,6 @@ lodash._createassigner@^3.0.0: lodash._isiterateecall "^3.0.0" lodash.restparam "^3.0.0" -lodash._createcompounder@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._createcompounder/-/lodash._createcompounder-3.0.0.tgz#5dd2cb55372d6e70e0e2392fb2304d6631091075" - dependencies: - lodash.deburr "^3.0.0" - lodash.words "^3.0.0" - lodash._getnative@^3.0.0: version "3.9.1" resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" @@ -3375,10 +3512,6 @@ lodash._isiterateecall@^3.0.0: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - lodash.assign@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" @@ -3391,11 +3524,13 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" -lodash.camelcase@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-3.0.1.tgz#932c8b87f8a4377897c67197533282f97aeac298" - dependencies: - lodash._createcompounder "^3.0.0" +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" lodash.camelcase@^4.3.0: version "4.3.0" @@ -3413,11 +3548,21 @@ lodash.create@3.1.1: lodash._basecreate "^3.0.0" lodash._isiterateecall "^3.0.0" -lodash.deburr@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.deburr/-/lodash.deburr-3.2.0.tgz#6da8f54334a366a7cf4c4c76ef8d80aa1b365ed5" - dependencies: - lodash._root "^3.0.0" +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" lodash.indexof@^4.0.5: version "4.0.5" @@ -3431,10 +3576,6 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" -lodash.isarray@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403" - lodash.keys@^3.0.0, lodash.keys@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -3443,29 +3584,55 @@ lodash.keys@^3.0.0, lodash.keys@^3.1.2: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +lodash.merge@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" + lodash.mergewith@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" -lodash.pick@^4.2.0, lodash.pick@^4.2.1: +lodash.pick@^4.2.0, lodash.pick@^4.2.1, lodash.pick@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" -lodash.words@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.words/-/lodash.words-3.2.0.tgz#4e2a8649bc08745b17c695b1a3ce8fee596623b3" - dependencies: - lodash._root "^3.0.0" +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + +lodash.tail@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" + +lodash@4.x.x, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.1: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.6.1, lodash@~4.16.4: +lodash@^4.2.0, lodash@^4.6.1, lodash@~4.16.4: version "4.16.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127" @@ -3501,7 +3668,7 @@ macaddress@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" -mantra-core@^1.6.1: +mantra-core@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/mantra-core/-/mantra-core-1.7.0.tgz#a8c83e8cee83ef6a7383131519fe8031ad546386" dependencies: @@ -3527,6 +3694,13 @@ memory-fs@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + memory-fs@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" @@ -3582,26 +3756,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.24.0.tgz#e2d13f939f0016c6e4e9ad25a8652f126c467f0c" - mime-db@~1.26.0: version "1.26.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff" -mime-types@^2.1.11, mime-types@~2.1.13: +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.7: version "2.1.14" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee" dependencies: mime-db "~1.26.0" -mime-types@~2.1.11, mime-types@~2.1.7: - version "2.1.12" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.12.tgz#152ba256777020dd4663f54c2e7bc26381e71729" - dependencies: - mime-db "~1.24.0" - mime@1.2.x: version "1.2.11" resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" @@ -3614,7 +3778,7 @@ minimalistic-assert@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@~3.0.2: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: @@ -3628,6 +3792,13 @@ minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +mixin-object@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" + dependencies: + for-in "^0.1.3" + is-extendable "^0.1.1" + mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -3638,9 +3809,9 @@ mobx@^2.3.4: version "2.6.0" resolved "https://registry.yarnpkg.com/mobx/-/mobx-2.6.0.tgz#0ae83a20488b92d10d4ca326e18fe78a5ab7cb36" -mocha@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.1.2.tgz#51f93b432bf7e1b175ffc22883ccd0be32dba6b5" +mocha@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" dependencies: browser-stdout "1.3.0" commander "2.9.0" @@ -3654,12 +3825,13 @@ mocha@^3.1.1: mkdirp "0.5.1" supports-color "3.1.2" -module-deps@^4.0.2: - version "4.0.7" - resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.0.7.tgz#edfeb3937be7359bc14a6672c22ef124887f6ed2" +module-deps@^4.0.8: + version "4.1.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" dependencies: JSONStream "^1.0.3" browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" concat-stream "~1.5.0" defined "^1.0.0" detective "^4.0.0" @@ -3689,6 +3861,16 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +node-abi@^1.0.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-1.3.3.tgz#0f06f2815deba26107959d2213b36ce97437e6e2" + +node-dir@^0.1.10: + version "0.1.16" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.16.tgz#d2ef583aa50b90d93db8cdd26fcea58353957fe4" + dependencies: + minimatch "^3.0.2" + node-fetch@^1.0.1: version "1.6.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" @@ -3743,6 +3925,34 @@ node-libs-browser@^0.7.0: util "^0.10.3" vm-browserify "0.0.4" +node-libs-browser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.1.4" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "0.0.1" + os-browserify "^0.2.0" + path-browserify "0.0.0" + process "^0.11.0" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.0.5" + stream-browserify "^2.0.1" + stream-http "^2.3.1" + string_decoder "^0.10.25" + timers-browserify "^2.0.2" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + node-pre-gyp@^0.6.29: version "0.6.30" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.30.tgz#64d3073a6f573003717ccfe30c89023297babba1" @@ -3757,9 +3967,9 @@ node-pre-gyp@^0.6.29: tar "~2.2.0" tar-pack "~3.1.0" -node-sass@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.0.0.tgz#3208301ad5a6096de227f3fc4c3ce682b9816afc" +node-sass@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.0.tgz#532e37bad0ce587348c831535dbc98ea4289508b" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -3770,7 +3980,6 @@ node-sass@^4.0.0: in-publish "^2.0.0" lodash.assign "^4.2.0" lodash.clonedeep "^4.3.2" - lodash.isarray "^4.0.0" lodash.mergewith "^4.6.0" meow "^3.7.0" mkdirp "^0.5.1" @@ -3779,11 +3988,16 @@ node-sass@^4.0.0: npmlog "^4.0.0" request "^2.61.0" sass-graph "^2.1.1" + stdout-stream "^1.4.0" node-uuid@~1.4.7: version "1.4.7" resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.7.tgz#6da5a17668c4b3dd59623bda11cf7fa4c1f60a6f" +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + "nopt@2 || 3", nopt@~3.0.1: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -3825,7 +4039,7 @@ normalize-url@^1.4.0: gauge "~2.6.0" set-blocking "~2.0.0" -npmlog@4.x, npmlog@^4.0.0, npmlog@^4.0.2: +npmlog@4.x, npmlog@^4.0.0, npmlog@^4.0.1, npmlog@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" dependencies: @@ -3848,9 +4062,9 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -"nwmatcher@>= 1.3.7 < 2.0.0": - version "1.3.8" - resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.8.tgz#34edb93de1aa6cb4448b573c9f2a059300241157" +"nwmatcher@>= 1.3.9 < 2.0.0": + version "1.3.9" + resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a" oauth-sign@~0.8.1: version "0.8.2" @@ -3872,7 +4086,7 @@ object-keys@^1.0.10, object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" -object.assign@^4.0.3: +object.assign@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.0.4.tgz#b1c9cc044ef1b9fe63606fc141abbb32e14730cc" dependencies: @@ -3918,13 +4132,13 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" -once@~1.3.3: +once@~1.3.0, once@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" dependencies: @@ -3962,7 +4176,7 @@ os-browserify@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -4048,10 +4262,6 @@ path-browserify@0.0.0, path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" -path-exists@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-1.0.0.tgz#d5a8998eb71ef37a74c34eb0d9eba6e878eea081" - path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" @@ -4131,7 +4341,7 @@ pgpass@1.x: dependencies: split "^1.0.0" -pify@^2.0.0: +pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -4151,6 +4361,13 @@ pkg-dir@^1.0.0: dependencies: find-up "^1.0.0" +podda@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/podda/-/podda-1.2.2.tgz#15b0edbd334ade145813343f5ecf9c10a71cf500" + dependencies: + babel-runtime "^6.11.6" + immutable "^3.8.1" + postcss-calc@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" @@ -4213,12 +4430,37 @@ postcss-filter-plugins@^2.0.0: postcss "^5.0.4" uniqid "^4.0.0" -postcss-loader@0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-0.13.0.tgz#72fdaf0d29444df77d3751ce4e69dc40bc99ed85" +postcss-load-config@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + postcss-load-options "^1.2.0" + postcss-load-plugins "^2.3.0" + +postcss-load-options@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + +postcss-load-plugins@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" + dependencies: + cosmiconfig "^2.1.1" + object-assign "^4.1.0" + +postcss-loader@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-1.1.0.tgz#4eb0bcbfc710b8b11406f3ea6650aaaa6e51b84f" dependencies: - loader-utils "^0.2.15" - postcss "^5.2.0" + loader-utils "^0.2.16" + object-assign "^4.1.0" + postcss "^5.2.5" + postcss-load-config "^1.0.0" postcss-merge-idents@^2.1.5: version "2.1.7" @@ -4382,7 +4624,16 @@ postcss-zindex@^2.0.1: postcss "^5.0.4" uniqs "^2.0.0" -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.0, postcss@^5.2.2: +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.5: + version "5.2.15" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.15.tgz#a9e8685e50e06cc5b3fdea5297273246c26f5b30" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^5.0.6, postcss@^5.2.2: version "5.2.4" resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.4.tgz#8eb4bee3e5c4e091585b116df32d8db24a535f21" dependencies: @@ -4409,6 +4660,24 @@ postgres-interval@~1.0.0: dependencies: xtend "^4.0.0" +prebuild-install@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.1.0.tgz#526c7b3ed1e2707a247f7c040719173a321bc14f" + dependencies: + expand-template "^1.0.2" + github-from-package "0.0.0" + minimist "^1.2.0" + node-abi "^1.0.3" + noop-logger "^0.1.1" + npmlog "^4.0.1" + os-homedir "^1.0.1" + pump "^1.0.1" + rc "^1.1.6" + simple-get "^1.4.2" + tar-fs "^1.13.0" + tunnel-agent "^0.4.3" + xtend "4.0.1" + precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -4468,11 +4737,18 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" +pump@^1.0.0, pump@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" -punycode@^1.2.4, punycode@^1.3.2: +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -4480,13 +4756,13 @@ q@^1.1.2: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -qs@6.2.0: +qs@6.2.0, qs@^6.1.0, qs@^6.2.0, qs@~6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" -qs@^6.1.0, qs@^6.2.0, qs@~6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625" +qs@~6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.1.tgz#918c0b3bcd36679772baf135b1acb4c1651ed79d" query-string@^3.0.0: version "3.0.3" @@ -4534,7 +4810,7 @@ range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" -rc@~1.1.0: +rc@^1.1.6, rc@~1.1.0: version "1.1.6" resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" dependencies: @@ -4543,17 +4819,26 @@ rc@~1.1.0: minimist "^1.2.0" strip-json-comments "~1.0.4" -react-addons-perf@^15.3.2: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react-addons-perf/-/react-addons-perf-15.3.2.tgz#bbdbebe8649f936f9636a5750ac145bf5c620213" +react-addons-perf@^15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react-addons-perf/-/react-addons-perf-15.4.2.tgz#110bdcf5c459c4f77cb85ed634bcd3397536383b" + dependencies: + fbjs "^0.8.4" + object-assign "^4.1.0" -react-addons-pure-render-mixin@>=0.14.0, react-addons-pure-render-mixin@^15.3.1: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react-addons-pure-render-mixin/-/react-addons-pure-render-mixin-15.3.2.tgz#c5f54764667ead26e6cdf7178b6c8dbbd8463ec2" +react-addons-pure-render-mixin@>=0.14.0, react-addons-pure-render-mixin@^15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react-addons-pure-render-mixin/-/react-addons-pure-render-mixin-15.4.2.tgz#a8433c71c45e2368503721921dc47bdaf1fbabcd" + dependencies: + fbjs "^0.8.4" + object-assign "^4.1.0" -"react-addons-test-utils@^0.14.8 || ^15.0.1", react-addons-test-utils@^15.3.2: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.3.2.tgz#c09a44f583425a4a9c1b38444d7a6c3e6f0f41f6" +react-addons-test-utils@^15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz#93bcaa718fcae7360d42e8fb1c09756cc36302a2" + dependencies: + fbjs "^0.8.4" + object-assign "^4.1.0" react-autosuggest@^7.0.1: version "7.0.1" @@ -4571,7 +4856,7 @@ react-autowhatever@^7.0.0: react-themeable "^1.1.0" section-iterator "^2.0.0" -react-decoration: +react-decoration@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/react-decoration/-/react-decoration-1.4.0.tgz#54c30aed3aa81d1fe8f844b37db0a536e4190da9" dependencies: @@ -4581,20 +4866,35 @@ react-deep-force-update@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.0.1.tgz#f911b5be1d2a6fe387507dd6e9a767aa2924b4c7" -"react-dom@^0.14.0 || ^15.0.0", react-dom@^15.3.0: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.3.2.tgz#c46b0aa5380d7b838e7a59c4a7beff2ed315531f" +react-docgen@^2.12.1: + version "2.13.0" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-2.13.0.tgz#7fcc4a3104ea8d4fd428383ba38df11166837be9" + dependencies: + async "^1.4.2" + babel-runtime "^6.9.2" + babylon "~5.8.3" + commander "^2.9.0" + doctrine "^2.0.0" + node-dir "^0.1.10" + recast "^0.11.5" -react-element-to-jsx-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-3.2.0.tgz#27ad7869e84f1d32f3d8a7385e44bc693dc8b7bb" +react-dom@^15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f" + dependencies: + fbjs "^0.8.1" + loose-envify "^1.1.0" + object-assign "^4.1.0" + +react-element-to-jsx-string@^5.0.0: + version "5.0.7" + resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-5.0.7.tgz#c663a4800a9c712115c0d8519cb0215a46a1f0f2" dependencies: collapse-white-space "^1.0.0" is-plain-object "^2.0.1" - lodash "^4.13.1" - react-addons-test-utils "^0.14.8 || ^15.0.1" + lodash "^4.17.4" sortobject "^1.0.0" - stringify-object "^2.3.1" + stringify-object "2.4.0" traverse "^0.6.6" react-fuzzy@^0.3.3: @@ -4619,7 +4919,7 @@ react-inspector@^1.1.0: dependencies: is-dom "^1.0.5" -react-intl: +react-intl@^2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.1.5.tgz#f9795ea34b790dcb5d0d8ef7060dddbe85bf8763" dependencies: @@ -4638,6 +4938,16 @@ react-komposer@^1.9.0: mobx "^2.3.4" shallowequal "0.2.x" +react-komposer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-komposer/-/react-komposer-2.0.0.tgz#b964738014a9b4aee494a83c0b5b833d66072a90" + dependencies: + babel-runtime "^6.11.6" + hoist-non-react-statics "^1.2.0" + lodash.pick "^4.4.0" + react-stubber "^1.0.0" + shallowequal "^0.2.2" + react-modal@^1.2.0, react-modal@^1.2.1: version "1.5.2" resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-1.5.2.tgz#acd60f19ed93ebbc7b09ea51624c7566fc615245" @@ -4646,16 +4956,16 @@ react-modal@^1.2.0, react-modal@^1.2.1: exenv "1.2.0" lodash.assign "^3.2.0" -react-motion: +react-motion@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.4.5.tgz#ecc42f692fec9b2de4c92f85e26375071f779b76" dependencies: performance-now "^0.2.0" raf "^3.1.0" -react-notification@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/react-notification/-/react-notification-6.4.0.tgz#7d0c3b2063bc8f57dc0f5707a8da4a7eb3475e70" +react-notification@^6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/react-notification/-/react-notification-6.6.0.tgz#791302e1522b0d2529daaab3b80839bcafd28fad" react-proxy@^1.1.8: version "1.1.8" @@ -4664,7 +4974,7 @@ react-proxy@^1.1.8: lodash "^4.6.1" react-deep-force-update "^1.0.0" -react-redux-loading-bar@^2.4.1: +react-redux-loading-bar@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/react-redux-loading-bar/-/react-redux-loading-bar-2.4.1.tgz#8df64db362f065b5453fbbb7379a5cf62440129a" @@ -4677,9 +4987,9 @@ react-redux@^4.4.5: lodash "^4.2.0" loose-envify "^1.1.0" -react-redux@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.1.tgz#84a41bd4cdd180452bb6922bc79ad25bd5abb7c4" +react-redux@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.3.tgz#86c3b68d56e74294a42e2a740ab66117ef6c019f" dependencies: hoist-non-react-statics "^1.0.3" invariant "^2.0.0" @@ -4687,7 +4997,7 @@ react-redux@^5.0.1: lodash-es "^4.2.0" loose-envify "^1.1.0" -react-router-scroll: +react-router-scroll@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/react-router-scroll/-/react-router-scroll-0.3.2.tgz#ba8b1d01b3681dc5a68d72865d35c10e84065e52" dependencies: @@ -4722,6 +5032,12 @@ react-storybook-addon-intl@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/react-storybook-addon-intl/-/react-storybook-addon-intl-0.1.0.tgz#4d46c9e6c7be0ad4e4f7de72d907ec764743dee8" +react-stubber@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-stubber/-/react-stubber-1.0.0.tgz#41ee2cac72d4d4fd70a63896da98e13739b84628" + dependencies: + babel-runtime "^6.5.0" + react-themeable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e" @@ -4735,9 +5051,9 @@ react-toggle@^2.1.1: classnames "~2.2" react-addons-pure-render-mixin ">=0.14.0" -react@^15.3.2: - version "15.3.2" - resolved "https://registry.yarnpkg.com/react/-/react-15.3.2.tgz#a7bccd2fee8af126b0317e222c28d1d54528d09e" +react@^15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef" dependencies: fbjs "^0.8.4" loose-envify "^1.1.0" @@ -4764,16 +5080,7 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -readable-stream@1.1: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@~2.1.4: +readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@~2.1.4: version "2.1.5" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" dependencies: @@ -4805,20 +5112,21 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" +recast@^0.11.5: + version "0.11.22" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.22.tgz#dedeb18fb001a2bbc6ac34475fda53dfe3d47dfa" + dependencies: + ast-types "0.9.5" + esprima "~3.1.0" + private "~0.1.5" + source-map "~0.5.0" + rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" dependencies: resolve "^1.1.6" -redbox-react@^1.2.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.3.1.tgz#02ea395f93442ac43e5363004d50a9cd1327ce41" - dependencies: - error-stack-parser "^1.3.6" - object-assign "^4.0.1" - react-dom "^0.14.0 || ^15.0.0" - redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -4856,11 +5164,11 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "~0.1.0" -redux-immutable@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/redux-immutable/-/redux-immutable-3.0.8.tgz#df5a5d601c88227ba38f474cf82f7d00e56f8c14" +redux-immutable@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/redux-immutable/-/redux-immutable-3.1.0.tgz#cafbd686e0711261119b9c28960935dc47a49d0a" dependencies: - immutable "^3.7.6" + immutable "^3.8.1" redux-sounds@^1.1.1: version "1.1.1" @@ -4868,9 +5176,9 @@ redux-sounds@^1.1.1: dependencies: howler "^1.1.28" -redux-thunk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.1.0.tgz#c724bfee75dbe352da2e3ba9bc14302badd89a98" +redux-thunk@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" redux@^3.5.2, redux@^3.6.0: version "3.6.0" @@ -4942,19 +5250,38 @@ repeat-string@^1.5.2: version "1.5.4" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.5.4.tgz#64ec0c91e0f4b475f90d5b643651e3e6e5b6c2d5" -repeating@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - dependencies: - is-finite "^1.0.0" - repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: is-finite "^1.0.0" -request@2, request@2.x, request@^2.55.0, request@^2.61.0, request@^2.74.0: +request@2, request@2.x, request@^2.61.0, request@^2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +request@^2.74.0: version "2.75.0" resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" dependencies: @@ -4984,6 +5311,10 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" @@ -5032,15 +5363,17 @@ sass-graph@^2.1.1: lodash "^4.0.0" yargs "^4.7.1" -sass-loader@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-4.0.2.tgz#a616eb770366543e64f547c8630f39c4da75f15d" +sass-loader@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.2.tgz#96343a9f5c585780149321c7bda9e1da633d2c73" dependencies: - async "^2.0.1" - loader-utils "^0.2.15" - object-assign "^4.1.0" + async "^2.1.5" + clone-deep "^0.2.4" + loader-utils "^1.0.1" + lodash.tail "^4.1.1" + pify "^2.3.0" -sax@^1.1.4, sax@~1.2.1: +sax@^1.2.1, sax@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" @@ -5125,11 +5458,20 @@ sha.js@^2.3.6, sha.js@~2.4.4: dependencies: inherits "^2.0.1" +shallow-clone@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" + dependencies: + is-extendable "^0.1.1" + kind-of "^2.0.1" + lazy-cache "^0.2.3" + mixin-object "^2.0.1" + shallow-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.0.0.tgz#508d1838b3de590ab8757b011b25e430900945f7" -shallowequal@0.2.x: +shallowequal@0.2.x, shallowequal@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e" dependencies: @@ -5142,11 +5484,7 @@ shasum@^1.0.0: json-stable-stringify "~0.0.0" sha.js "~2.4.4" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -shell-quote@^1.4.3: +shell-quote@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" dependencies: @@ -5167,6 +5505,14 @@ signal-exit@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.1.tgz#5a4c884992b63a7acd9badb7894c3ee9cfccad81" +simple-get@^1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" + dependencies: + once "^1.3.1" + unzip-response "^1.0.0" + xtend "^4.0.0" + sinon@^1.17.6: version "1.17.6" resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.6.tgz#a43116db59577c8296356afee13fafc2332e58e1" @@ -5202,11 +5548,7 @@ sortobject@^1.0.0: dependencies: editions "^1.1.1" -source-list-map@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.6.tgz#e1e6f94f0b40c4d28dcf8f5b8766e0e45636877f" - -source-list-map@~0.1.7: +source-list-map@^0.1.7, source-list-map@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.7.tgz#d4b5ce2a46535c72c7e8527c71a77d250618172e" @@ -5216,7 +5558,7 @@ source-map-support@^0.4.2: dependencies: source-map "^0.5.3" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -5271,21 +5613,16 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -stack-source-map@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/stack-source-map/-/stack-source-map-1.0.5.tgz#ca95da2ba241bf90fa5757c70d401d10e022b2df" - dependencies: - path-browserify "0.0.0" - source-map "^0.5.3" - -stackframe@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" - "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -5300,10 +5637,6 @@ stream-combiner2@^1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" -stream-consume@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" - stream-http@^2.0.0, stream-http@^2.3.1: version "2.4.0" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.4.0.tgz#9599aa8e263667ce4190e0dc04a1d065d3595a7e" @@ -5325,7 +5658,7 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" -string-width@^1.0.1: +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: @@ -5353,7 +5686,7 @@ string_decoder@^0.10.25, string_decoder@~0.10.0, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -stringify-object@^2.3.1: +stringify-object@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-2.4.0.tgz#c62d11023eb21fe2d9b087be039a26df3b22a09d" dependencies: @@ -5386,12 +5719,18 @@ strip-json-comments@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" -style-loader@0.13.1, style-loader@^0.13.1: +style-loader@0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.13.1.tgz#468280efbc0473023cd3a6cd56e33b5a1d7fc3a9" dependencies: loader-utils "^0.2.7" +style-loader@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.13.2.tgz#74533384cf698c7104c7951150b49717adc2f3bb" + dependencies: + loader-utils "^1.0.2" + subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" @@ -5412,6 +5751,12 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + svgo@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.1.tgz#287320fed972cb097e72c2bb1685f96fe08f8034" @@ -5428,9 +5773,9 @@ symbol-observable@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.3.tgz#0fdb005e84f346a899d492beba23068b32d1525a" -"symbol-tree@>= 3.1.0 < 4.0.0": - version "3.1.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.1.4.tgz#02b279348d337debc39694c5c95f882d448a312a" +symbol-tree@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" syntax-error@^1.1.1: version "1.1.6" @@ -5442,6 +5787,19 @@ tapable@^0.1.8, tapable@~0.1.8: version "0.1.10" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" +tapable@^0.2.5, tapable@~0.2.5: + version "0.2.6" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d" + +tar-fs@^1.13.0: + version "1.15.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.1.tgz#f4622f5d5e250742b3679a9a8463acfc12cdefd1" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.0" + pump "^1.0.0" + tar-stream "^1.1.2" + tar-pack@~3.1.0: version "3.1.4" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.1.4.tgz#bc8cf9a22f5832739f12f3910dac1eb97b49708c" @@ -5455,6 +5813,15 @@ tar-pack@~3.1.0: tar "~2.2.1" uid-number "~0.0.6" +tar-stream@^1.1.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf" + dependencies: + bl "^1.0.0" + end-of-stream "^1.0.0" + readable-stream "^2.0.0" + xtend "^4.0.0" + tar@^2.0.0, tar@~2.2.0, tar@~2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" @@ -5494,11 +5861,13 @@ to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" -tough-cookie@^2.2.0, tough-cookie@^2.3.1, tough-cookie@~2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.1.tgz#99c77dfbb7d804249e8a299d4cb0fd81fef083fd" +tough-cookie@^2.3.2, tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" -tr46@~0.0.1, tr46@~0.0.3: +tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -5510,11 +5879,15 @@ trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + tty-browserify@0.0.0, tty-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" -tunnel-agent@~0.4.1: +tunnel-agent@^0.4.3, tunnel-agent@~0.4.1: version "0.4.3" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" @@ -5551,7 +5924,7 @@ ua-parser-js@^0.7.9: version "0.7.10" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.10.tgz#917559ddcce07cbc09ece7d80495e4c268f4ef9f" -uglify-js@~2.7.3: +uglify-js@^2.7.5, uglify-js@~2.7.3: version "2.7.5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" dependencies: @@ -5594,6 +5967,10 @@ unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unzip-response@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" + url-loader@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.7.tgz#67e8779759f8000da74994906680c943a9b0925d" @@ -5619,12 +5996,13 @@ user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" -utf-8-validate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-3.0.0.tgz#42e54dfbc7cdfbd1d3bbf0a2f5000b4c6aeaa0c9" +utf-8-validate@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-3.0.1.tgz#5d2b8656b4ddcfded47217b647a98941b63cf213" dependencies: bindings "~1.2.1" nan "~2.5.0" + prebuild-install "~2.1.0" util-deprecate@~1.0.1: version "1.0.2" @@ -5640,11 +6018,11 @@ utils-merge@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" -uuid@^2.0.1, uuid@^2.0.2: +uuid@^2.0.1, uuid@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.0.1: +uuid@^3.0.0, uuid@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" @@ -5701,14 +6079,22 @@ watchpack@^0.2.1: chokidar "^1.0.0" graceful-fs "^4.1.2" -webidl-conversions@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" +watchpack@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87" + dependencies: + async "^2.1.2" + chokidar "^1.4.3" + graceful-fs "^4.1.2" -webidl-conversions@^3.0.0, webidl-conversions@^3.0.1: +webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" +webidl-conversions@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.1.tgz#8015a17ab83e7e1b311638486ace81da6ce206a0" + webpack-core@~0.6.9: version "0.6.9" resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" @@ -5725,16 +6111,23 @@ webpack-dev-middleware@^1.6.0: path-is-absolute "^1.0.0" range-parser "^1.0.3" -webpack-hot-middleware@^2.10.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.13.0.tgz#aee39c058ff130a5916e2c5a762513241c87064f" +webpack-hot-middleware@^2.13.2: + version "2.17.1" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.17.1.tgz#0c8fbf6f93ff29c095d684b07ab6d6c0f2f951d7" dependencies: - ansi-html "0.0.5" + ansi-html "0.0.7" html-entities "^1.2.0" querystring "^0.2.0" strip-ansi "^3.0.0" -webpack@^1.13.1, webpack@^1.14.0: +webpack-sources@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.4.tgz#ccc2c817e08e5fa393239412690bb481821393cd" + dependencies: + source-list-map "~0.1.7" + source-map "~0.5.3" + +webpack@^1.13.1: version "1.14.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.14.0.tgz#54f1ffb92051a328a5b2057d6ae33c289462c823" dependencies: @@ -5754,25 +6147,50 @@ webpack@^1.13.1, webpack@^1.14.0: watchpack "^0.2.1" webpack-core "~0.6.9" +webpack@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.2.1.tgz#7bb1d72ae2087dd1a4af526afec15eed17dda475" + dependencies: + acorn "^4.0.4" + acorn-dynamic-import "^2.0.0" + ajv "^4.7.0" + ajv-keywords "^1.1.1" + async "^2.1.2" + enhanced-resolve "^3.0.0" + interpret "^1.0.0" + json-loader "^0.5.4" + loader-runner "^2.3.0" + loader-utils "^0.2.16" + memory-fs "~0.4.1" + mkdirp "~0.5.0" + node-libs-browser "^2.0.0" + source-map "^0.5.3" + supports-color "^3.1.0" + tapable "~0.2.5" + uglify-js "^2.7.5" + watchpack "^1.2.0" + webpack-sources "^0.1.4" + yargs "^6.0.0" + websocket.js@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/websocket.js/-/websocket.js-0.1.7.tgz#8d24cefb1a080c259e7e4740c02cab8f142df2b0" dependencies: backoff "^2.4.1" +whatwg-encoding@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4" + dependencies: + iconv-lite "0.4.13" + whatwg-fetch@>=0.10.0: version "1.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.0.0.tgz#01c2ac4df40e236aaa18480e3be74bd5c8eb798e" -whatwg-url-compat@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf" - dependencies: - tr46 "~0.0.1" - -whatwg-url@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-3.0.0.tgz#b9033c50c7ce763e91d78777ce825a6d7f56dac5" +whatwg-url@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.5.0.tgz#79bb6f0e370a4dda1cbc8f3062a490cf8bbb09ea" dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -5836,9 +6254,9 @@ write-file-atomic@^1.1.2: imurmurhash "^0.1.4" slide "^1.1.5" -ws@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-2.0.2.tgz#6257d1a679f0cb23658cba3dcad1316e2b1000c5" +ws@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-2.1.0.tgz#b24eaed9609f8632dd51e3f7698619a90fddcc92" dependencies: ultron "~1.1.0" @@ -5848,11 +6266,11 @@ xdg-basedir@^2.0.0: dependencies: os-homedir "^1.0.0" -"xml-name-validator@>= 2.0.1 < 3.0.0": +xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" -xtend@^4.0.0, xtend@~4.0.0: +xtend@4.0.1, xtend@^4.0.0, xtend@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -5871,6 +6289,12 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + dependencies: + camelcase "^3.0.0" + yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" @@ -5890,6 +6314,24 @@ yargs@^4.7.1: y18n "^3.2.1" yargs-parser "^2.4.1" +yargs@^6.0.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" |