about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md33
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock9
-rw-r--r--app/javascript/flavours/glitch/actions/notifications.js2
-rw-r--r--app/javascript/flavours/glitch/actions/timelines.js21
-rw-r--r--app/javascript/flavours/glitch/features/status/index.js63
-rw-r--r--app/javascript/flavours/glitch/reducers/contexts.js95
-rw-r--r--app/javascript/locales/locale-data/oc.js24
-rw-r--r--app/javascript/mastodon/actions/conversations.js2
-rw-r--r--app/javascript/mastodon/actions/notifications.js2
-rw-r--r--app/javascript/mastodon/actions/timelines.js2
-rw-r--r--app/javascript/mastodon/features/account/components/header.js3
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js4
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js6
-rw-r--r--app/javascript/mastodon/locales/en.json7
-rw-r--r--app/javascript/mastodon/locales/ja.json6
-rw-r--r--app/javascript/mastodon/locales/oc.json25
-rw-r--r--app/javascript/mastodon/locales/pl.json1
-rw-r--r--config/initializers/json_ld.rb3
-rw-r--r--config/locales/devise.oc.yml4
-rw-r--r--config/locales/oc.yml14
-rw-r--r--lib/json_ld/security.rb50
-rw-r--r--lib/mastodon/version.rb2
-rw-r--r--package.json3
-rw-r--r--yarn.lock141
25 files changed, 269 insertions, 254 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5eba30d5..1e24df451 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,39 @@ Changelog
 
 All notable changes to this project will be documented in this file.
 
+## [2.6.5] - 2018-12-01
+### Changed
+
+- Change lists to display replies to others on the list and list owner (#9324)
+
+### Fixed
+
+- Fix failures caused by commonly-used JSON-LD contexts being unavailable (#9412)
+
+## [2.6.4] - 2018-11-30
+### Fixed
+
+- Fix yarn dependencies not installing due to yanked event-stream package (#9401)
+
+## [2.6.3] - 2018-11-30
+### Added
+
+- Add hyphen to characters allowed in remote usernames (#9345)
+
+### Changed
+
+- Change server user count to exclude suspended accounts (#9380)
+
+### Fixed
+
+- Fix ffmpeg processing sometimes stalling due to overfilled stdout buffer (#9368)
+- Fix missing DNS records raising the wrong kind of exception (#9379)
+- Fix already queued deliveries still trying to reach inboxes marked as unavailable (#9358)
+
+### Security
+
+- Fix TLS handshake timeout not being enforced (#9381)
+
 ## [2.6.2] - 2018-11-23
 ### Added
 
diff --git a/Gemfile b/Gemfile
index b31826ede..8bb9ab326 100644
--- a/Gemfile
+++ b/Gemfile
@@ -91,6 +91,7 @@ gem 'webpacker', '~> 3.5'
 gem 'webpush'
 
 gem 'json-ld', '~> 2.2'
+gem 'json-ld-preloaded', '~> 2.2'
 gem 'rdf-normalize', '~> 0.3'
 
 group :development, :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index b6be4de68..56522496a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -210,7 +210,7 @@ GEM
     faraday (0.15.0)
       multipart-post (>= 1.2, < 3)
     fast_blank (1.0.0)
-    fastimage (2.1.4)
+    fastimage (2.1.5)
     ffi (1.9.25)
     fog-core (2.1.0)
       builder
@@ -292,6 +292,10 @@ GEM
     json-ld (2.2.1)
       multi_json (~> 1.12)
       rdf (>= 2.2.8, < 4.0)
+    json-ld-preloaded (2.2.3)
+      json-ld (>= 2.2, < 4.0)
+      multi_json (~> 1.12)
+      rdf (>= 2.2, < 4.0)
     jsonapi-renderer (0.2.0)
     jwt (2.1.0)
     kaminari (1.1.1)
@@ -361,7 +365,7 @@ GEM
       concurrent-ruby (~> 1.0.0)
       sidekiq (>= 3.5.0)
       statsd-ruby (~> 1.2.0)
-    oj (3.7.1)
+    oj (3.7.4)
     omniauth (1.8.1)
       hashie (>= 3.4.6, < 3.6.0)
       rack (>= 1.6.2, < 3)
@@ -696,6 +700,7 @@ DEPENDENCIES
   idn-ruby
   iso-639
   json-ld (~> 2.2)
+  json-ld-preloaded (~> 2.2)
   kaminari (~> 1.1)
   letter_opener (~> 1.4)
   letter_opener_web (~> 1.3)
diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js
index ddf14f78f..0184d9c80 100644
--- a/app/javascript/flavours/glitch/actions/notifications.js
+++ b/app/javascript/flavours/glitch/actions/notifications.js
@@ -102,7 +102,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
     };
 
     if (!maxId && notifications.get('items').size > 0) {
-      params.since_id = notifications.getIn(['items', 0]);
+      params.since_id = notifications.getIn(['items', 0, 'id']);
     }
 
     dispatch(expandNotificationsRequest(isLoadingMore));
diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js
index 27ca66e51..ffd259d5f 100644
--- a/app/javascript/flavours/glitch/actions/timelines.js
+++ b/app/javascript/flavours/glitch/actions/timelines.js
@@ -12,34 +12,13 @@ export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
 
 export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
 
-export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE';
-
 export function updateTimeline(timeline, status) {
   return (dispatch, getState) => {
-    const parents = [];
-
-    if (status.in_reply_to_id) {
-      let parent = getState().getIn(['statuses', status.in_reply_to_id]);
-
-      while (parent && parent.get('in_reply_to_id')) {
-        parents.push(parent.get('id'));
-        parent = getState().getIn(['statuses', parent.get('in_reply_to_id')]);
-      }
-    }
-
     dispatch({
       type: TIMELINE_UPDATE,
       timeline,
       status,
     });
-
-    if (parents.length > 0) {
-      dispatch({
-        type: TIMELINE_CONTEXT_UPDATE,
-        status,
-        references: parents,
-      });
-    }
   };
 };
 
diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js
index 61de148e1..d2d5a05c8 100644
--- a/app/javascript/flavours/glitch/features/status/index.js
+++ b/app/javascript/flavours/glitch/features/status/index.js
@@ -1,3 +1,4 @@
+import Immutable from 'immutable';
 import React from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
@@ -57,13 +58,49 @@ const messages = defineMessages({
 const makeMapStateToProps = () => {
   const getStatus = makeGetStatus();
 
-  const mapStateToProps = (state, props) => ({
-    status: getStatus(state, { id: props.params.statusId }),
-    settings: state.get('local_settings'),
-    ancestorsIds: state.getIn(['contexts', 'ancestors', props.params.statusId]),
-    descendantsIds: state.getIn(['contexts', 'descendants', props.params.statusId]),
-    askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
-  });
+  const mapStateToProps = (state, props) => {
+    const status = getStatus(state, { id: props.params.statusId });
+    let ancestorsIds = Immutable.List();
+    let descendantsIds = Immutable.List();
+
+    if (status) {
+      ancestorsIds = ancestorsIds.withMutations(mutable => {
+        let id = status.get('in_reply_to_id');
+
+        while (id) {
+          mutable.unshift(id);
+          id = state.getIn(['contexts', 'inReplyTos', id]);
+        }
+      });
+
+      descendantsIds = descendantsIds.withMutations(mutable => {
+        const ids = [status.get('id')];
+
+        while (ids.length > 0) {
+          let id        = ids.shift();
+          const replies = state.getIn(['contexts', 'replies', id]);
+
+          if (status.get('id') !== id) {
+            mutable.push(id);
+          }
+
+          if (replies) {
+            replies.reverse().forEach(reply => {
+              ids.unshift(reply);
+            });
+          }
+        }
+      });
+    }
+
+    return {
+      status,
+      ancestorsIds,
+      descendantsIds,
+      settings: state.get('local_settings'),
+      askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
+    };
+  };
 
   return mapStateToProps;
 };
@@ -97,6 +134,16 @@ export default class Status extends ImmutablePureComponent {
   componentDidMount () {
     attachFullscreenListener(this.onFullScreenChange);
     this.props.dispatch(fetchStatus(this.props.params.statusId));
+
+    const { status, ancestorsIds } = this.props;
+
+    if (status && ancestorsIds && ancestorsIds.size > 0) {
+      const element = this.node.querySelectorAll('.focusable')[ancestorsIds.size - 1];
+
+      window.requestAnimationFrame(() => {
+        element.scrollIntoView(true);
+      });
+    }
   }
 
   static getDerivedStateFromProps(props, state) {
@@ -339,7 +386,7 @@ export default class Status extends ImmutablePureComponent {
   }
 
   componentDidUpdate (prevProps) {
-    if (this.props.params.statusId !== prevProps.params.statusId && this.props.params.statusId) {
+    if (this.props.params.statusId && (this.props.params.statusId !== prevProps.params.statusId || prevProps.ancestorsIds.size < this.props.ancestorsIds.size)) {
       const { status, ancestorsIds } = this.props;
 
       if (status && ancestorsIds && ancestorsIds.size > 0) {
diff --git a/app/javascript/flavours/glitch/reducers/contexts.js b/app/javascript/flavours/glitch/reducers/contexts.js
index effd70756..73b25fe3f 100644
--- a/app/javascript/flavours/glitch/reducers/contexts.js
+++ b/app/javascript/flavours/glitch/reducers/contexts.js
@@ -3,38 +3,63 @@ import {
   ACCOUNT_MUTE_SUCCESS,
 } from 'flavours/glitch/actions/accounts';
 import { CONTEXT_FETCH_SUCCESS } from 'flavours/glitch/actions/statuses';
-import { TIMELINE_DELETE, TIMELINE_CONTEXT_UPDATE } from 'flavours/glitch/actions/timelines';
+import { TIMELINE_DELETE, TIMELINE_UPDATE } from 'flavours/glitch/actions/timelines';
 import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
+import compareId from 'flavours/glitch/util/compare_id';
 
 const initialState = ImmutableMap({
-  ancestors: ImmutableMap(),
-  descendants: ImmutableMap(),
+  inReplyTos: ImmutableMap(),
+  replies: ImmutableMap(),
 });
 
-const normalizeContext = (state, id, ancestors, descendants) => {
-  const ancestorsIds   = ImmutableList(ancestors.map(ancestor => ancestor.id));
-  const descendantsIds = ImmutableList(descendants.map(descendant => descendant.id));
+const normalizeContext = (immutableState, id, ancestors, descendants) => immutableState.withMutations(state => {
+  state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
+    state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
+      function addReply({ id, in_reply_to_id }) {
+        if (in_reply_to_id && !inReplyTos.has(id)) {
 
-  return state.withMutations(map => {
-    map.setIn(['ancestors', id], ancestorsIds);
-    map.setIn(['descendants', id], descendantsIds);
-  });
-};
+          replies.update(in_reply_to_id, ImmutableList(), siblings => {
+            const index = siblings.findLastIndex(sibling => compareId(sibling, id) < 0);
+            return siblings.insert(index + 1, id);
+          });
+
+          inReplyTos.set(id, in_reply_to_id);
+        }
+      }
+
+      // We know in_reply_to_id of statuses but `id` itself.
+      // So we assume that the status of the id replies to last ancestors.
+
+      ancestors.forEach(addReply);
+
+      if (ancestors[0]) {
+        addReply({ id, in_reply_to_id: ancestors[ancestors.length - 1].id });
+      }
+
+      descendants.forEach(addReply);
+    }));
+  }));
+});
 
 const deleteFromContexts = (immutableState, ids) => immutableState.withMutations(state => {
-  state.update('ancestors', immutableAncestors => immutableAncestors.withMutations(ancestors => {
-    state.update('descendants', immutableDescendants => immutableDescendants.withMutations(descendants => {
+  state.update('inReplyTos', immutableAncestors => immutableAncestors.withMutations(inReplyTos => {
+    state.update('replies', immutableDescendants => immutableDescendants.withMutations(replies => {
       ids.forEach(id => {
-        descendants.get(id, ImmutableList()).forEach(descendantId => {
-          ancestors.update(descendantId, ImmutableList(), list => list.filterNot(itemId => itemId === id));
-        });
+        const inReplyToIdOfId = inReplyTos.get(id);
+        const repliesOfId = replies.get(id);
+        const siblings = replies.get(inReplyToIdOfId);
+
+        if (siblings) {
+          replies.set(inReplyToIdOfId, siblings.filterNot(sibling => sibling === id));
+        }
 
-        ancestors.get(id, ImmutableList()).forEach(ancestorId => {
-          descendants.update(ancestorId, ImmutableList(), list => list.filterNot(itemId => itemId === id));
-        });
 
-        descendants.delete(id);
-        ancestors.delete(id);
+        if (repliesOfId) {
+          repliesOfId.forEach(reply => inReplyTos.delete(reply));
+        }
+
+        inReplyTos.delete(id);
+        replies.delete(id);
       });
     }));
   }));
@@ -47,23 +72,23 @@ const filterContexts = (state, relationship, statuses) => {
   return deleteFromContexts(state, ownedStatusIds);
 };
 
-const updateContext = (state, status, references) => {
-  return state.update('descendants', map => {
-    references.forEach(parentId => {
-      map = map.update(parentId, ImmutableList(), list => {
-        if (list.includes(status.id)) {
-          return list;
-        }
+const updateContext = (state, status) => {
+  if (status.in_reply_to_id) {
+    return state.withMutations(mutable => {
+      const replies = mutable.getIn(['replies', status.in_reply_to_id], ImmutableList());
 
-        return list.push(status.id);
-      });
+      mutable.setIn(['inReplyTos', status.id], status.in_reply_to_id);
+
+      if (!replies.includes(status.id)) {
+        mutable.setIn(['replies', status.in_reply_to_id], replies.push(status.id));
+      }
     });
+  }
 
-    return map;
-  });
+  return state;
 };
 
-export default function contexts(state = initialState, action) {
+export default function replies(state = initialState, action) {
   switch(action.type) {
   case ACCOUNT_BLOCK_SUCCESS:
   case ACCOUNT_MUTE_SUCCESS:
@@ -72,8 +97,8 @@ export default function contexts(state = initialState, action) {
     return normalizeContext(state, action.id, action.ancestors, action.descendants);
   case TIMELINE_DELETE:
     return deleteFromContexts(state, [action.id]);
-  case TIMELINE_CONTEXT_UPDATE:
-    return updateContext(state, action.status, action.references);
+  case TIMELINE_UPDATE:
+    return updateContext(state, action.status);
   default:
     return state;
   }
diff --git a/app/javascript/locales/locale-data/oc.js b/app/javascript/locales/locale-data/oc.js
index c4b56350b..d4adc42eb 100644
--- a/app/javascript/locales/locale-data/oc.js
+++ b/app/javascript/locales/locale-data/oc.js
@@ -17,8 +17,8 @@ export default [{
       },
       relativeTime: {
         future: {
-          one: "dins {0} an",
-          other: "dins {0} ans",
+          one: "d’aquí {0} an",
+          other: "d’aquí {0} ans",
         },
         past: {
           one: "fa {0} an",
@@ -35,8 +35,8 @@ export default [{
       },
       relativeTime: {
         future: {
-          one: "dins {0} mes",
-          other: "dins {0} meses",
+          one: "d’aquí {0} mes",
+          other: "d’aquí {0} meses",
         },
         past: {
           one: "fa {0} mes",
@@ -53,8 +53,8 @@ export default [{
       },
       relativeTime: {
         future: {
-          one: "dins {0} jorn",
-          other: "dins {0} jorns",
+          one: "d’aquí {0} jorn",
+          other: "d’aquí {0} jorns",
         },
         past: {
           one: "fa {0} jorn",
@@ -66,8 +66,8 @@ export default [{
       displayName: "ora",
       relativeTime: {
         future: {
-          one: "dins {0} ora",
-          other: "dins {0} oras",
+          one: "d’aquí {0} ora",
+          other: "d’aquí {0} oras",
         },
         past: {
           one: "fa {0} ora",
@@ -79,8 +79,8 @@ export default [{
       displayName: "minuta",
       relativeTime: {
         future: {
-          one: "dins {0} minuta",
-          other: "dins {0} minutas",
+          one: "d’aquí {0} minuta",
+          other: "d’aquí {0} minutas",
         },
         past: {
           one: "fa {0} minuta",
@@ -95,8 +95,8 @@ export default [{
       },
       relativeTime: {
         future: {
-          one: "dins {0} segonda",
-          other: "dins {0} segondas",
+          one: "d’aquí {0} segonda",
+          other: "d’aquí {0} segondas",
         },
         past: {
           one: "fa {0} segonda",
diff --git a/app/javascript/mastodon/actions/conversations.js b/app/javascript/mastodon/actions/conversations.js
index aefd2fef7..3c2ea9680 100644
--- a/app/javascript/mastodon/actions/conversations.js
+++ b/app/javascript/mastodon/actions/conversations.js
@@ -38,7 +38,7 @@ export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
   const params = { max_id: maxId };
 
   if (!maxId) {
-    params.since_id = getState().getIn(['conversations', 0, 'last_status']);
+    params.since_id = getState().getIn(['conversations', 'items', 0, 'last_status']);
   }
 
   api(getState).get('/api/v1/conversations', { params })
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 92c70e155..d24f39ad2 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -106,7 +106,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
     };
 
     if (!maxId && notifications.get('items').size > 0) {
-      params.since_id = notifications.getIn(['items', 0]);
+      params.since_id = notifications.getIn(['items', 0, 'id']);
     }
 
     dispatch(expandNotificationsRequest(isLoadingMore));
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 81c4c8425..215adc4ea 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -15,7 +15,7 @@ export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
 export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
 
 export function updateTimeline(timeline, status, accept) {
-  return (dispatch, getState) => {
+  return dispatch => {
     if (typeof accept === 'function' && !accept(status)) {
       return;
     }
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index 11ae58905..8604e7167 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -16,6 +16,7 @@ const messages = defineMessages({
   unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
   linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
+  account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
 });
 
 const dateFormatOptions = {
@@ -148,7 +149,7 @@ class Header extends ImmutablePureComponent {
     }
 
     if (account.get('locked')) {
-      lockedIcon = <i className='fa fa-lock' />;
+      lockedIcon = <i className='fa fa-lock' title={intl.formatMessage(messages.account_locked)} />;
     }
 
     const content         = { __html: account.get('note_emojified') };
diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
index 82936c838..9c9f62d82 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
@@ -5,8 +5,8 @@ import { injectIntl, FormattedMessage } from 'react-intl';
 import Toggle from 'react-toggle';
 import AsyncSelect from 'react-select/lib/Async';
 
-@injectIntl
-export default class ColumnSettings extends React.PureComponent {
+export default @injectIntl
+class ColumnSettings extends React.PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index d7722dcce..c2e026d13 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -42,13 +42,13 @@ class HashtagTimeline extends React.PureComponent {
   title = () => {
     let title = [this.props.params.id];
     if (this.additionalFor('any')) {
-      title.push(<FormattedMessage id='hashtag.column_header.tag_mode.any'  values={{ additional: this.additionalFor('any') }} defaultMessage=' or {additional}' />);
+      title.push(' ', <FormattedMessage id='hashtag.column_header.tag_mode.any'  values={{ additional: this.additionalFor('any') }} defaultMessage='or {additional}' />);
     }
     if (this.additionalFor('all')) {
-      title.push(<FormattedMessage id='hashtag.column_header.tag_mode.all'  values={{ additional: this.additionalFor('all') }} defaultMessage=' and {additional}' />);
+      title.push(' ', <FormattedMessage id='hashtag.column_header.tag_mode.all'  values={{ additional: this.additionalFor('all') }} defaultMessage='and {additional}' />);
     }
     if (this.additionalFor('none')) {
-      title.push(<FormattedMessage id='hashtag.column_header.tag_mode.none' values={{ additional: this.additionalFor('none') }} defaultMessage=' without {additional}' />);
+      title.push(' ', <FormattedMessage id='hashtag.column_header.tag_mode.none' values={{ additional: this.additionalFor('none') }} defaultMessage='without {additional}' />);
     }
     return title;
   }
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 16f680fa3..ca5abcb05 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -17,6 +17,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
+  "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
   "account.mention": "Mention @{name}",
   "account.moved_to": "{name} has moved to:",
@@ -142,9 +143,9 @@
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
   "getting_started.security": "Security",
   "getting_started.terms": "Terms of service",
-  "hashtag.column_header.tag_mode.all": "{tag} and {additional}",
-  "hashtag.column_header.tag_mode.any": "{tag} or {additional}",
-  "hashtag.column_header.tag_mode.none": "{tag} without {additional}",
+  "hashtag.column_header.tag_mode.all": "and {additional}",
+  "hashtag.column_header.tag_mode.any": "or {additional}",
+  "hashtag.column_header.tag_mode.none": "without {additional}",
   "hashtag.column_settings.tag_mode.all": "All of these",
   "hashtag.column_settings.tag_mode.any": "Any of these",
   "hashtag.column_settings.tag_mode.none": "None of these",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index e774bb70b..06fe71e6b 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -142,9 +142,9 @@
   "getting_started.open_source_notice": "Mastodonはオープンソースソフトウェアです。誰でもGitHub({github})から開発に参加したり、問題を報告したりできます。",
   "getting_started.security": "セキュリティ",
   "getting_started.terms": "プライバシーポリシー",
-  "hashtag.column_header.tag_mode.all": " と {additional}",
-  "hashtag.column_header.tag_mode.any": " か {additional}",
-  "hashtag.column_header.tag_mode.none": " ({additional} を除く)",
+  "hashtag.column_header.tag_mode.all": "と {additional}",
+  "hashtag.column_header.tag_mode.any": "か {additional}",
+  "hashtag.column_header.tag_mode.none": "({additional} を除く)",
   "hashtag.column_settings.tag_mode.all": "すべてを含む",
   "hashtag.column_settings.tag_mode.any": "いずれかを含む",
   "hashtag.column_settings.tag_mode.none": "これらを除く",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index ec0507e15..a94e0336d 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -1,5 +1,5 @@
 {
-  "account.add_or_remove_from_list": "Add or Remove from lists",
+  "account.add_or_remove_from_list": "Ajustar o tirar de las listas",
   "account.badges.bot": "Robòt",
   "account.block": "Blocar @{name}",
   "account.block_domain": "Tot amagar del domeni {domain}",
@@ -17,6 +17,7 @@
   "account.follows_you": "Vos sèc",
   "account.hide_reblogs": "Rescondre los partatges de @{name}",
   "account.link_verified_on": "La proprietat d’aqueste ligam foguèt verificada lo {date}",
+  "account.locked_info": "L’estatut de privacitat del compte es configurat sus clavat. Lo proprietari causís qual pòt sègre son compte.",
   "account.media": "Mèdias",
   "account.mention": "Mencionar @{name}",
   "account.moved_to": "{name} a mudat los catons a :",
@@ -68,7 +69,7 @@
   "community.column_settings.media_only": "Solament los mèdias",
   "compose_form.direct_message_warning": "Sols los mencionats poiràn veire aqueste tut.",
   "compose_form.direct_message_warning_learn_more": "Ne saber mai",
-  "compose_form.hashtag_warning": "Aqueste tut serà pas ligat a cap d’etiqueta estant qu’es pas listat. Òm pas cercar que los tuts publics per etiqueta.",
+  "compose_form.hashtag_warning": "Aqueste tut serà pas ligat a cap d’etiqueta estant qu’es pas listat. Òm pòt pas cercar que los tuts publics per etiqueta.",
   "compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo monde pòt vos sègre e veire los estatuts reservats als seguidors.",
   "compose_form.lock_disclaimer.lock": "clavat",
   "compose_form.placeholder": "A de qué pensatz ?",
@@ -112,7 +113,7 @@
   "emoji_button.search_results": "Resultats de recèrca",
   "emoji_button.symbols": "Simbòls",
   "emoji_button.travel": "Viatges & lòcs",
-  "empty_column.account_timeline": "No toots here!",
+  "empty_column.account_timeline": "Cap de tuts aquí !",
   "empty_column.blocks": "Avètz pas blocat degun pel moment.",
   "empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir !",
   "empty_column.direct": "Avètz pas encara cap de messatges. Quand ne mandatz un o que ne recebètz un, serà mostrat aquí.",
@@ -138,13 +139,13 @@
   "getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {github} sus GitHub.",
   "getting_started.security": "Seguretat",
   "getting_started.terms": "Condicions d’utilizacion",
-  "hashtag.column_header.tag_mode.all": "and {additional}",
-  "hashtag.column_header.tag_mode.any": "or {additional}",
-  "hashtag.column_header.tag_mode.none": "without {additional}",
-  "hashtag.column_settings.tag_mode.all": "All of these",
-  "hashtag.column_settings.tag_mode.any": "Any of these",
-  "hashtag.column_settings.tag_mode.none": "None of these",
-  "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
+  "hashtag.column_header.tag_mode.all": "e {additional}",
+  "hashtag.column_header.tag_mode.any": "o {additional}",
+  "hashtag.column_header.tag_mode.none": "sens {additional}",
+  "hashtag.column_settings.tag_mode.all": "Totes aquestes",
+  "hashtag.column_settings.tag_mode.any": "Un d’aquestes",
+  "hashtag.column_settings.tag_mode.none": "Cap d’aquestesNone of these",
+  "hashtag.column_settings.tag_toggle": "Inclure las etiquetas suplementàrias dins aquesta colomna",
   "home.column_settings.basic": "Basic",
   "home.column_settings.show_reblogs": "Mostrar los partatges",
   "home.column_settings.show_replies": "Mostrar las responsas",
@@ -174,7 +175,7 @@
   "keyboard_shortcuts.reply": "respondre",
   "keyboard_shortcuts.requests": "per dorbir la lista de demanda d’abonament",
   "keyboard_shortcuts.search": "anar a la recèrca",
-  "keyboard_shortcuts.start": "per dobrir la columna «Per començar»",
+  "keyboard_shortcuts.start": "per dobrir la colomna «Per començar»",
   "keyboard_shortcuts.toggle_hidden": "mostrar/amagar lo tèxte dels avertiments",
   "keyboard_shortcuts.toot": "començar un estatut tot novèl",
   "keyboard_shortcuts.unfocus": "quitar lo camp tèxte/de recèrca",
@@ -321,7 +322,7 @@
   "status.show_less_all": "Los tornar plegar totes",
   "status.show_more": "Desplegar",
   "status.show_more_all": "Los desplegar totes",
-  "status.show_thread": "Show thread",
+  "status.show_thread": "Mostrar lo fil",
   "status.unmute_conversation": "Tornar mostrar la conversacion",
   "status.unpin": "Tirar del perfil",
   "suggestions.dismiss": "Regetar la suggestion",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 1fb8df0ad..237ffd33a 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -17,6 +17,7 @@
   "account.follows_you": "Śledzi Cię",
   "account.hide_reblogs": "Ukryj podbicia od @{name}",
   "account.link_verified_on": "Własność tego odnośnika została potwierdzona {date}",
+  "account.locked_info": "To konto jest prywatne. Właściciel ręcznie wybiera kto może go śledzić.",
   "account.media": "Zawartość multimedialna",
   "account.mention": "Wspomnij o @{name}",
   "account.moved_to": "{name} przeniósł(-osła) się do:",
diff --git a/config/initializers/json_ld.rb b/config/initializers/json_ld.rb
new file mode 100644
index 000000000..d5575d135
--- /dev/null
+++ b/config/initializers/json_ld.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require_relative '../../lib/json_ld/security'
diff --git a/config/locales/devise.oc.yml b/config/locales/devise.oc.yml
index 16633e233..20a373462 100644
--- a/config/locales/devise.oc.yml
+++ b/config/locales/devise.oc.yml
@@ -50,8 +50,8 @@ oc:
       success: Sètz ben autentificat dempuèi lo compte %{kind}.
     passwords:
       no_token: Podètz pas accedir a aquesta pagina sens venir d’un corriel de reïnicializacion de senhal. S’es lo cas, mercés de verificar qu’avètz ben utilizat l’URL donada de manièra complèta.
-      send_instructions: Recebretz un corrièl amb las consignas per reĩnicializar vòstre senhal dins una estona. Mercés de verificar tanben vòstre dorsièr de corrièls indesirables.
-      send_paranoid_instructions: Se vòstra adreça de corrièl existís dins nòstra basa de donadas, recebretz un ligam per reĩnicializar vòstre senhal dins una estona. Mercés de verificar tanben vòstre dorsièr de corrièls indesirables.
+      send_instructions: Recebretz un corrièl amb las consignas per reïnicializar vòstre senhal dins una estona. Mercés de verificar tanben vòstre dorsièr de corrièls indesirables.
+      send_paranoid_instructions: Se vòstra adreça de corrièl existís dins nòstra basa de donadas, recebretz un ligam per reïnicializar vòstre senhal dins una estona. Mercés de verificar tanben vòstre dorsièr de corrièls indesirables.
       updated: Vòstre senhal es ben estat cambiat. Sètz ara connectat.
       updated_not_active: Vòstre senhal es ben estat cambiat.
     registrations:
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index f9cf623f0..1d5325876 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -111,7 +111,7 @@ oc:
         remote: Alonhats
         title: Emplaçament
       login_status: Estat formulari de connexion
-      media_attachments: Mèdias ajustats
+      media_attachments: Mèdias enviats
       memorialize: Passar en memorial
       moderation:
         all: Tot
@@ -260,7 +260,7 @@ oc:
       reject_media: Regetar los fichièrs mèdias
       reject_media_hint: Lèva los fichièrs gardats localament e regèta las demandas de telecargament dins lo futur. Servís pas a res per las suspensions
       reject_reports: Regetar los senhalaments
-      reject_reports_hint: Ignorer totes los senhalaments que venon d’aqueste domeni. Pas pertiment per las suspensions
+      reject_reports_hint: Ignorar totes los senhalaments que venon d’aqueste domeni. Pas pertiment per las suspensions
       severities:
         noop: Cap
         silence: Silenci
@@ -343,7 +343,7 @@ oc:
       reported_account: Compte senhalat
       reported_by: Senhalat per
       resolved: Resolgut
-      resolved_msg: Rapòrt corrèctament resolgut  !
+      resolved_msg: Rapòrt corrèctament resolgut !
       status: Estatut
       title: Senhalament
       unassign: Levar
@@ -352,7 +352,7 @@ oc:
     settings:
       activity_api_enabled:
         desc_html: Nombre d’estatuts publicats, d’utilizaires actius e de novèlas inscripcions en rapòrt setmanièr
-        title: Publica las estatisticas totalas de l’activitat dels utilizaires
+        title: Publicar las estatisticas totalas de l’activitat dels utilizaires
       bootstrap_timeline_accounts:
         desc_html: Separatz los noms d’utilizaire amb de virgula. Pas que los comptes locals e pas clavats foncionaràn. Se lo camp es void los admins seràn selecionats.
         title: Per defaut los nòuvenguts sègon
@@ -370,13 +370,13 @@ oc:
         title: Imatge de la mascòta
       peers_api_enabled:
         desc_html: Noms de domeni qu’aquesta instància a trobats pel fediverse
-        title: Publica la lista de las instàncias conegudas
+        title: Publicar la lista de las instàncias conegudas
       preview_sensitive_media:
         desc_html: Los apercebuts dels ligams sus los autres sites mostraràn una vinheta encara que lo mèdia siá marcat coma sensible
         title: Mostrar los mèdias sensibles dins los apercebuts OpenGraph
       registrations:
         closed_message:
-          desc_html: Afichat sus las pagina d’acuèlh quand las inscripcions son tampadas.<br>Podètz utilizar de balisas HTML
+          desc_html: Mostrat sus las pagina d’acuèlh quand las inscripcions son tampadas.<br>Podètz utilizar de balisas HTML
           title: Messatge de barradura de las inscripcions
         deletion:
           desc_html: Autorizar lo monde a suprimir lor compte
@@ -663,7 +663,7 @@ oc:
       one: 1 persona
       other: "%{count} personas"
     max_uses_prompt: Cap de limit
-    prompt: Generatz e partejatz los ligams per donar accès a aquesta instància
+    prompt: Generar e partejar los ligams per donar accès a aquesta instància
     table:
       expires_at: Expirats
       uses: Usatges
diff --git a/lib/json_ld/security.rb b/lib/json_ld/security.rb
new file mode 100644
index 000000000..1230206f0
--- /dev/null
+++ b/lib/json_ld/security.rb
@@ -0,0 +1,50 @@
+# -*- encoding: utf-8 -*-
+# frozen_string_literal: true
+# This file generated automatically from https://w3id.org/security/v1
+require 'json/ld'
+class JSON::LD::Context
+  add_preloaded("https://w3id.org/security/v1") do
+    new(processingMode: "json-ld-1.0", term_definitions: {
+      "CryptographicKey" => TermDefinition.new("CryptographicKey", id: "https://w3id.org/security#Key", simple: true),
+      "EcdsaKoblitzSignature2016" => TermDefinition.new("EcdsaKoblitzSignature2016", id: "https://w3id.org/security#EcdsaKoblitzSignature2016", simple: true),
+      "EncryptedMessage" => TermDefinition.new("EncryptedMessage", id: "https://w3id.org/security#EncryptedMessage", simple: true),
+      "GraphSignature2012" => TermDefinition.new("GraphSignature2012", id: "https://w3id.org/security#GraphSignature2012", simple: true),
+      "LinkedDataSignature2015" => TermDefinition.new("LinkedDataSignature2015", id: "https://w3id.org/security#LinkedDataSignature2015", simple: true),
+      "LinkedDataSignature2016" => TermDefinition.new("LinkedDataSignature2016", id: "https://w3id.org/security#LinkedDataSignature2016", simple: true),
+      "authenticationTag" => TermDefinition.new("authenticationTag", id: "https://w3id.org/security#authenticationTag", simple: true),
+      "canonicalizationAlgorithm" => TermDefinition.new("canonicalizationAlgorithm", id: "https://w3id.org/security#canonicalizationAlgorithm", simple: true),
+      "cipherAlgorithm" => TermDefinition.new("cipherAlgorithm", id: "https://w3id.org/security#cipherAlgorithm", simple: true),
+      "cipherData" => TermDefinition.new("cipherData", id: "https://w3id.org/security#cipherData", simple: true),
+      "cipherKey" => TermDefinition.new("cipherKey", id: "https://w3id.org/security#cipherKey", simple: true),
+      "created" => TermDefinition.new("created", id: "http://purl.org/dc/terms/created", type_mapping: "http://www.w3.org/2001/XMLSchema#dateTime"),
+      "creator" => TermDefinition.new("creator", id: "http://purl.org/dc/terms/creator", type_mapping: "@id"),
+      "dc" => TermDefinition.new("dc", id: "http://purl.org/dc/terms/", simple: true, prefix: true),
+      "digestAlgorithm" => TermDefinition.new("digestAlgorithm", id: "https://w3id.org/security#digestAlgorithm", simple: true),
+      "digestValue" => TermDefinition.new("digestValue", id: "https://w3id.org/security#digestValue", simple: true),
+      "domain" => TermDefinition.new("domain", id: "https://w3id.org/security#domain", simple: true),
+      "encryptionKey" => TermDefinition.new("encryptionKey", id: "https://w3id.org/security#encryptionKey", simple: true),
+      "expiration" => TermDefinition.new("expiration", id: "https://w3id.org/security#expiration", type_mapping: "http://www.w3.org/2001/XMLSchema#dateTime"),
+      "expires" => TermDefinition.new("expires", id: "https://w3id.org/security#expiration", type_mapping: "http://www.w3.org/2001/XMLSchema#dateTime"),
+      "id" => TermDefinition.new("id", id: "@id", simple: true),
+      "initializationVector" => TermDefinition.new("initializationVector", id: "https://w3id.org/security#initializationVector", simple: true),
+      "iterationCount" => TermDefinition.new("iterationCount", id: "https://w3id.org/security#iterationCount", simple: true),
+      "nonce" => TermDefinition.new("nonce", id: "https://w3id.org/security#nonce", simple: true),
+      "normalizationAlgorithm" => TermDefinition.new("normalizationAlgorithm", id: "https://w3id.org/security#normalizationAlgorithm", simple: true),
+      "owner" => TermDefinition.new("owner", id: "https://w3id.org/security#owner", type_mapping: "@id"),
+      "password" => TermDefinition.new("password", id: "https://w3id.org/security#password", simple: true),
+      "privateKey" => TermDefinition.new("privateKey", id: "https://w3id.org/security#privateKey", type_mapping: "@id"),
+      "privateKeyPem" => TermDefinition.new("privateKeyPem", id: "https://w3id.org/security#privateKeyPem", simple: true),
+      "publicKey" => TermDefinition.new("publicKey", id: "https://w3id.org/security#publicKey", type_mapping: "@id"),
+      "publicKeyPem" => TermDefinition.new("publicKeyPem", id: "https://w3id.org/security#publicKeyPem", simple: true),
+      "publicKeyService" => TermDefinition.new("publicKeyService", id: "https://w3id.org/security#publicKeyService", type_mapping: "@id"),
+      "revoked" => TermDefinition.new("revoked", id: "https://w3id.org/security#revoked", type_mapping: "http://www.w3.org/2001/XMLSchema#dateTime"),
+      "salt" => TermDefinition.new("salt", id: "https://w3id.org/security#salt", simple: true),
+      "sec" => TermDefinition.new("sec", id: "https://w3id.org/security#", simple: true, prefix: true),
+      "signature" => TermDefinition.new("signature", id: "https://w3id.org/security#signature", simple: true),
+      "signatureAlgorithm" => TermDefinition.new("signatureAlgorithm", id: "https://w3id.org/security#signingAlgorithm", simple: true),
+      "signatureValue" => TermDefinition.new("signatureValue", id: "https://w3id.org/security#signatureValue", simple: true),
+      "type" => TermDefinition.new("type", id: "@type", simple: true),
+      "xsd" => TermDefinition.new("xsd", id: "http://www.w3.org/2001/XMLSchema#", simple: true, prefix: true)
+    })
+  end
+end
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index bc4712d9a..56e02cf6c 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -13,7 +13,7 @@ module Mastodon
     end
 
     def patch
-      2
+      5
     end
 
     def pre
diff --git a/package.json b/package.json
index 68ff199f2..05dc489fe 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
     "build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
     "manage:translations": "node ./config/webpack/translationRunner.js",
     "start": "node ./streaming/index.js",
-    "test": "npm-run-all test:lint test:jest",
+    "test": "npm run test:lint && npm run test:jest",
     "test:lint": "eslint -c .eslintrc.yml --ext=js app/javascript/ config/webpack/ streaming/",
     "test:jest": "cross-env NODE_ENV=test jest --coverage"
   },
@@ -78,7 +78,6 @@
     "mini-css-extract-plugin": "^0.4.2",
     "mkdirp": "^0.5.1",
     "node-sass": "^4.9.2",
-    "npm-run-all": "^4.1.2",
     "npmlog": "^4.1.2",
     "object-assign": "^4.1.1",
     "object-fit-images": "^3.2.3",
diff --git a/yarn.lock b/yarn.lock
index 39052a49b..f055be0bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1153,11 +1153,6 @@ array-equal@^1.0.0:
   resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
   integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
 
-array-filter@~0.0.0:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
-  integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw=
-
 array-find-index@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
@@ -1181,16 +1176,6 @@ array-includes@^3.0.3:
     define-properties "^1.1.2"
     es-abstract "^1.7.0"
 
-array-map@~0.0.0:
-  version "0.0.0"
-  resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
-  integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=
-
-array-reduce@~0.0.0:
-  version "0.0.0"
-  resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
-  integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=
-
 array-union@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@@ -2493,7 +2478,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0:
     shebang-command "^1.2.0"
     which "^1.2.9"
 
-cross-spawn@^6.0.0, cross-spawn@^6.0.4, cross-spawn@^6.0.5:
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
   version "6.0.5"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
   integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -3006,7 +2991,7 @@ double-ended-queue@^2.1.0-0:
   resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
   integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=
 
-duplexer@^0.1.1, duplexer@~0.1.1:
+duplexer@^0.1.1:
   version "0.1.1"
   resolved "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
   integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
@@ -3172,7 +3157,7 @@ error-ex@^1.2.0, error-ex@^1.3.1:
   dependencies:
     is-arrayish "^0.2.1"
 
-es-abstract@^1.10.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0:
+es-abstract@^1.10.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0:
   version "1.12.0"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
   integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==
@@ -3422,20 +3407,6 @@ etag@~1.8.1:
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
   integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
 
-event-stream@~3.3.0:
-  version "3.3.6"
-  resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.6.tgz#cac1230890e07e73ec9cacd038f60a5b66173eef"
-  integrity sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==
-  dependencies:
-    duplexer "^0.1.1"
-    flatmap-stream "^0.1.0"
-    from "^0.1.7"
-    map-stream "0.0.7"
-    pause-stream "^0.0.11"
-    split "^1.0.1"
-    stream-combiner "^0.2.2"
-    through "^2.3.8"
-
 eventemitter3@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
@@ -3845,11 +3816,6 @@ flat-cache@^1.2.1:
     graceful-fs "^4.1.2"
     write "^0.2.1"
 
-flatmap-stream@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/flatmap-stream/-/flatmap-stream-0.1.0.tgz#ed54e01422cd29281800914fcb968d58b685d5f1"
-  integrity sha512-Nlic4ZRYxikqnK5rj3YoxDVKGGtUjcNDUtvQ7XsdGLZmMwdUYnXf10o1zcXtzEZTBgc6GxeRpQxV/Wu3WPIIHA==
-
 flatten@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
@@ -3947,11 +3913,6 @@ from2@^2.1.0:
     inherits "^2.0.1"
     readable-stream "^2.0.0"
 
-from@^0.1.7:
-  version "0.1.7"
-  resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
-  integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=
-
 fs-extra@^7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6"
@@ -5747,16 +5708,6 @@ load-json-file@^2.0.0:
     pify "^2.0.0"
     strip-bom "^3.0.0"
 
-load-json-file@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
-  integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
-  dependencies:
-    graceful-fs "^4.1.2"
-    parse-json "^4.0.0"
-    pify "^3.0.0"
-    strip-bom "^3.0.0"
-
 loader-runner@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
@@ -5946,11 +5897,6 @@ map-obj@^1.0.0, map-obj@^1.0.1:
   resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
   integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
 
-map-stream@0.0.7:
-  version "0.0.7"
-  resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
-  integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=
-
 map-visit@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
@@ -6014,11 +5960,6 @@ memory-fs@^0.4.0, memory-fs@~0.4.1:
     errno "^0.1.3"
     readable-stream "^2.0.1"
 
-memorystream@^0.3.1:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
-  integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
-
 meow@^3.7.0:
   version "3.7.0"
   resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
@@ -6577,21 +6518,6 @@ npm-packlist@^1.1.6:
     ignore-walk "^3.0.1"
     npm-bundled "^1.0.1"
 
-npm-run-all@^4.1.2:
-  version "4.1.3"
-  resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.3.tgz#49f15b55a66bb4101664ce270cb18e7103f8f185"
-  integrity sha512-aOG0N3Eo/WW+q6sUIdzcV2COS8VnTZCmdji0VQIAZF3b+a3YWb0AD0vFIyjKec18A7beLGbaQ5jFTNI2bPt9Cg==
-  dependencies:
-    ansi-styles "^3.2.0"
-    chalk "^2.1.0"
-    cross-spawn "^6.0.4"
-    memorystream "^0.3.1"
-    minimatch "^3.0.4"
-    ps-tree "^1.1.0"
-    read-pkg "^3.0.0"
-    shell-quote "^1.6.1"
-    string.prototype.padend "^3.0.0"
-
 npm-run-path@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -7094,20 +7020,6 @@ path-type@^2.0.0:
   dependencies:
     pify "^2.0.0"
 
-path-type@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
-  integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
-  dependencies:
-    pify "^3.0.0"
-
-pause-stream@^0.0.11:
-  version "0.0.11"
-  resolved "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
-  integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=
-  dependencies:
-    through "~2.3"
-
 pbkdf2@^3.0.3:
   version "3.0.16"
   resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c"
@@ -7778,13 +7690,6 @@ prr@~1.0.1:
   resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
   integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
 
-ps-tree@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
-  integrity sha1-tCGyQUDWID8e08dplrRCewjowBQ=
-  dependencies:
-    event-stream "~3.3.0"
-
 pseudomap@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -8248,15 +8153,6 @@ read-pkg@^2.0.0:
     normalize-package-data "^2.3.2"
     path-type "^2.0.0"
 
-read-pkg@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
-  integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
-  dependencies:
-    load-json-file "^4.0.0"
-    normalize-package-data "^2.3.2"
-    path-type "^3.0.0"
-
 "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.6:
   version "2.3.6"
   resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
@@ -8960,16 +8856,6 @@ shebang-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
   integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
 
-shell-quote@^1.6.1:
-  version "1.6.1"
-  resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767"
-  integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=
-  dependencies:
-    array-filter "~0.0.0"
-    array-map "~0.0.0"
-    array-reduce "~0.0.0"
-    jsonify "~0.0.0"
-
 shellwords@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
@@ -9176,7 +9062,7 @@ split-string@^3.0.1, split-string@^3.0.2:
   dependencies:
     extend-shallow "^3.0.0"
 
-split@^1.0.0, split@^1.0.1:
+split@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
   integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
@@ -9261,14 +9147,6 @@ stream-browserify@^2.0.1:
     inherits "~2.0.1"
     readable-stream "^2.0.2"
 
-stream-combiner@^0.2.2:
-  version "0.2.2"
-  resolved "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858"
-  integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=
-  dependencies:
-    duplexer "~0.1.1"
-    through "~2.3.4"
-
 stream-each@^1.1.0:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
@@ -9318,15 +9196,6 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^4.0.0"
 
-string.prototype.padend@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0"
-  integrity sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=
-  dependencies:
-    define-properties "^1.1.2"
-    es-abstract "^1.4.3"
-    function-bind "^1.0.2"
-
 string.prototype.trim@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
@@ -9552,7 +9421,7 @@ through2@^2.0.0:
     readable-stream "^2.1.5"
     xtend "~4.0.1"
 
-through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.4:
+through@2, through@^2.3.6:
   version "2.3.8"
   resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
   integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=