diff --git a/.eslintrc.js b/.eslintrc.js
index 8394d98b9c..2bbe301f04 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -4,6 +4,7 @@ module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
+ 'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:promise/recommended',
@@ -102,6 +103,7 @@ module.exports = {
{
vars: 'all',
args: 'after-used',
+ destructuredArrayIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
@@ -208,6 +210,9 @@ module.exports = {
],
},
],
+ 'import/no-amd': 'error',
+ 'import/no-commonjs': 'error',
+ 'import/no-import-module-exports': 'error',
'import/no-webpack-loader-syntax': 'error',
'promise/always-return': 'off',
@@ -255,6 +260,7 @@ module.exports = {
'*.config.js',
'.*rc.js',
'ide-helper.js',
+ 'config/webpack/**/*',
],
env: {
@@ -264,6 +270,10 @@ module.exports = {
parserOptions: {
sourceType: 'script',
},
+
+ rules: {
+ 'import/no-commonjs': 'off',
+ },
},
{
files: [
@@ -275,6 +285,7 @@ module.exports = {
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
+ 'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
@@ -286,6 +297,12 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off',
'jsdoc/require-jsdoc': 'off',
+
+ // Those rules set stricter rules for TS files
+ // to enforce better practices when converting from JS
+ 'import/no-default-export': 'warn',
+ 'react/prefer-stateless-function': 'warn',
+ 'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
},
},
{
@@ -298,5 +315,13 @@ module.exports = {
jest: true,
},
},
+ {
+ files: [
+ 'streaming/**/*',
+ ],
+ rules: {
+ 'import/no-commonjs': 'off',
+ },
+ },
],
};
diff --git a/app/javascript/core/mailer.js b/app/javascript/core/mailer.js
index a4b6d54464..a2ad5e73ac 100644
--- a/app/javascript/core/mailer.js
+++ b/app/javascript/core/mailer.js
@@ -1,3 +1,3 @@
-require('../styles/mailer.scss');
+import '../styles/mailer.scss';
require.context('../icons');
diff --git a/app/javascript/mastodon/actions/markers.js b/app/javascript/mastodon/actions/markers.js
index ca246dce78..b23ecccc39 100644
--- a/app/javascript/mastodon/actions/markers.js
+++ b/app/javascript/mastodon/actions/markers.js
@@ -1,6 +1,6 @@
import api from '../api';
import { debounce } from 'lodash';
-import compareId from '../compare_id';
+import { compareId } from '../compare_id';
import { List as ImmutableList } from 'immutable';
export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST';
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 93588d3c0c..0c58f8d159 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -13,7 +13,7 @@ import { defineMessages } from 'react-intl';
import { List as ImmutableList } from 'immutable';
import { unescapeHTML } from '../utils/html';
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
-import compareId from 'mastodon/compare_id';
+import { compareId } from 'mastodon/compare_id';
import { requestNotificationPermission } from '../utils/notifications';
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js
index 41cb99e2dd..7831f261e6 100644
--- a/app/javascript/mastodon/actions/streaming.js
+++ b/app/javascript/mastodon/actions/streaming.js
@@ -52,8 +52,10 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
/**
* @param {function(Function, Function): void} fallback
*/
+
const useFallback = fallback => {
fallback(dispatch, () => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
});
};
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 4f772a55f0..e9e3a8e240 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -2,7 +2,7 @@ import { importFetchedStatus, importFetchedStatuses } from './importer';
import { submitMarkers } from './markers';
import api, { getLinks } from 'mastodon/api';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import compareId from 'mastodon/compare_id';
+import { compareId } from 'mastodon/compare_id';
import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
diff --git a/app/javascript/mastodon/common.js b/app/javascript/mastodon/common.js
index 8f35053036..0ec8449343 100644
--- a/app/javascript/mastodon/common.js
+++ b/app/javascript/mastodon/common.js
@@ -1,7 +1,7 @@
import Rails from '@rails/ujs';
+import 'font-awesome/css/font-awesome.css';
export function start() {
- require('font-awesome/css/font-awesome.css');
require.context('../images/', true);
try {
diff --git a/app/javascript/mastodon/compare_id.ts b/app/javascript/mastodon/compare_id.ts
index ae4ac6f897..3ddfb76351 100644
--- a/app/javascript/mastodon/compare_id.ts
+++ b/app/javascript/mastodon/compare_id.ts
@@ -1,4 +1,4 @@
-export default function compareId (id1: string, id2: string) {
+export function compareId (id1: string, id2: string) {
if (id1 === id2) {
return 0;
}
diff --git a/app/javascript/mastodon/components/__tests__/avatar-test.jsx b/app/javascript/mastodon/components/__tests__/avatar-test.jsx
index dd3f7b7d21..5a72fc19a1 100644
--- a/app/javascript/mastodon/components/__tests__/avatar-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/avatar-test.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { fromJS } from 'immutable';
-import Avatar from '../avatar';
+import { Avatar } from '../avatar';
describe('', () => {
const account = fromJS({
diff --git a/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx b/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
index 44addea832..ea75dab574 100644
--- a/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { fromJS } from 'immutable';
-import AvatarOverlay from '../avatar_overlay';
+import { AvatarOverlay } from '../avatar_overlay';
describe(' {
const account = fromJS({
diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx
index 6a0682e9c1..b0bbea7ce4 100644
--- a/app/javascript/mastodon/components/account.jsx
+++ b/app/javascript/mastodon/components/account.jsx
@@ -1,19 +1,19 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import Avatar from './avatar';
+import { Avatar } from './avatar';
import DisplayName from './display_name';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from '../initial_state';
-import RelativeTimestamp from './relative_timestamp';
+import { RelativeTimestamp } from './relative_timestamp';
import Skeleton from 'mastodon/components/skeleton';
import { Link } from 'react-router-dom';
import { counterRenderer } from 'mastodon/components/common_counter';
import ShortNumber from 'mastodon/components/short_number';
import classNames from 'classnames';
-import VerifiedBadge from 'mastodon/components/verified_badge';
+import { VerifiedBadge } from 'mastodon/components/verified_badge';
const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' },
diff --git a/app/javascript/mastodon/components/animated_number.tsx b/app/javascript/mastodon/components/animated_number.tsx
index 1673ff41bb..20ffa1a4d0 100644
--- a/app/javascript/mastodon/components/animated_number.tsx
+++ b/app/javascript/mastodon/components/animated_number.tsx
@@ -54,5 +54,3 @@ export const AnimatedNumber: React.FC = ({
);
};
-
-export default AnimatedNumber;
diff --git a/app/javascript/mastodon/components/attachment_list.jsx b/app/javascript/mastodon/components/attachment_list.jsx
index 0e23889ded..3354025c4a 100644
--- a/app/javascript/mastodon/components/attachment_list.jsx
+++ b/app/javascript/mastodon/components/attachment_list.jsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
diff --git a/app/javascript/mastodon/components/avatar.tsx b/app/javascript/mastodon/components/avatar.tsx
index e64a8af742..8be94d3f53 100644
--- a/app/javascript/mastodon/components/avatar.tsx
+++ b/app/javascript/mastodon/components/avatar.tsx
@@ -45,5 +45,3 @@ export const Avatar: React.FC = ({
);
};
-
-export default Avatar;
diff --git a/app/javascript/mastodon/components/avatar_composite.jsx b/app/javascript/mastodon/components/avatar_composite.jsx
index 220bf5b4f8..e1fae95dc0 100644
--- a/app/javascript/mastodon/components/avatar_composite.jsx
+++ b/app/javascript/mastodon/components/avatar_composite.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { autoPlayGif } from '../initial_state';
-import Avatar from './avatar';
+import { Avatar } from './avatar';
export default class AvatarComposite extends React.PureComponent {
diff --git a/app/javascript/mastodon/components/avatar_overlay.tsx b/app/javascript/mastodon/components/avatar_overlay.tsx
index 5c65a928c5..e8dc88896f 100644
--- a/app/javascript/mastodon/components/avatar_overlay.tsx
+++ b/app/javascript/mastodon/components/avatar_overlay.tsx
@@ -47,5 +47,3 @@ export const AvatarOverlay: React.FC = ({
);
};
-
-export default AvatarOverlay;
diff --git a/app/javascript/mastodon/components/blurhash.tsx b/app/javascript/mastodon/components/blurhash.tsx
index 6fec6e1ef7..181e2183d0 100644
--- a/app/javascript/mastodon/components/blurhash.tsx
+++ b/app/javascript/mastodon/components/blurhash.tsx
@@ -9,13 +9,13 @@ type Props = {
children?: never;
[key: string]: any;
}
-function Blurhash({
+const Blurhash: React.FC = ({
hash,
width = 32,
height = width,
dummy = false,
...canvasProps
-}: Props) {
+}) => {
const canvasRef = useRef(null);
useEffect(() => {
@@ -40,6 +40,8 @@ function Blurhash({
return (
);
-}
+};
-export default React.memo(Blurhash);
+const MemoizedBlurhash = React.memo(Blurhash);
+
+export { MemoizedBlurhash as Blurhash };
diff --git a/app/javascript/mastodon/components/check.tsx b/app/javascript/mastodon/components/check.tsx
index 3a4a113205..57b810a0e5 100644
--- a/app/javascript/mastodon/components/check.tsx
+++ b/app/javascript/mastodon/components/check.tsx
@@ -5,5 +5,3 @@ export const Check: React.FC = () => (
);
-
-export default Check;
diff --git a/app/javascript/mastodon/components/column_back_button.jsx b/app/javascript/mastodon/components/column_back_button.jsx
index faa800b2ad..19e2cb3637 100644
--- a/app/javascript/mastodon/components/column_back_button.jsx
+++ b/app/javascript/mastodon/components/column_back_button.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { createPortal } from 'react-dom';
export default class ColumnBackButton extends React.PureComponent {
diff --git a/app/javascript/mastodon/components/column_back_button_slim.jsx b/app/javascript/mastodon/components/column_back_button_slim.jsx
index 46ac23736b..f2c8642eae 100644
--- a/app/javascript/mastodon/components/column_back_button_slim.jsx
+++ b/app/javascript/mastodon/components/column_back_button_slim.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import ColumnBackButton from './column_back_button';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
export default class ColumnBackButtonSlim extends ColumnBackButton {
diff --git a/app/javascript/mastodon/components/column_header.jsx b/app/javascript/mastodon/components/column_header.jsx
index afc526f27f..794ea9738a 100644
--- a/app/javascript/mastodon/components/column_header.jsx
+++ b/app/javascript/mastodon/components/column_header.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { createPortal } from 'react-dom';
import classNames from 'classnames';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
diff --git a/app/javascript/mastodon/components/dismissable_banner.jsx b/app/javascript/mastodon/components/dismissable_banner.jsx
index 242021e764..c433d95324 100644
--- a/app/javascript/mastodon/components/dismissable_banner.jsx
+++ b/app/javascript/mastodon/components/dismissable_banner.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
import { bannerSettings } from 'mastodon/settings';
diff --git a/app/javascript/mastodon/components/domain.tsx b/app/javascript/mastodon/components/domain.tsx
index 6cb8f7b8ff..af0fec35af 100644
--- a/app/javascript/mastodon/components/domain.tsx
+++ b/app/javascript/mastodon/components/domain.tsx
@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import { InjectedIntl, defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx
index eaaa72fd83..0ed3e904f5 100644
--- a/app/javascript/mastodon/components/dropdown_menu.jsx
+++ b/app/javascript/mastodon/components/dropdown_menu.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import Overlay from 'react-overlays/Overlay';
import { supportsPassiveEvents } from 'detect-passive-events';
import classNames from 'classnames';
diff --git a/app/javascript/mastodon/components/edited_timestamp/index.jsx b/app/javascript/mastodon/components/edited_timestamp/index.jsx
index 8a5417a7d9..745d8a4b6f 100644
--- a/app/javascript/mastodon/components/edited_timestamp/index.jsx
+++ b/app/javascript/mastodon/components/edited_timestamp/index.jsx
@@ -1,11 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import DropdownMenu from './containers/dropdown_menu_container';
import { connect } from 'react-redux';
import { openModal } from 'mastodon/actions/modal';
-import RelativeTimestamp from 'mastodon/components/relative_timestamp';
+import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import InlineAccount from 'mastodon/components/inline_account';
const mapDispatchToProps = (dispatch, { statusId }) => ({
diff --git a/app/javascript/mastodon/components/gifv.tsx b/app/javascript/mastodon/components/gifv.tsx
index 8968170c5f..5d9f235e11 100644
--- a/app/javascript/mastodon/components/gifv.tsx
+++ b/app/javascript/mastodon/components/gifv.tsx
@@ -64,5 +64,3 @@ export const GIFV: React.FC = ({
);
};
-
-export default GIFV;
diff --git a/app/javascript/mastodon/components/icon.tsx b/app/javascript/mastodon/components/icon.tsx
index d85fff6ef6..f74437b555 100644
--- a/app/javascript/mastodon/components/icon.tsx
+++ b/app/javascript/mastodon/components/icon.tsx
@@ -10,5 +10,3 @@ type Props = {
}
export const Icon: React.FC = ({ id, className, fixedWidth, ...other }) =>
;
-
-export default Icon;
diff --git a/app/javascript/mastodon/components/icon_button.tsx b/app/javascript/mastodon/components/icon_button.tsx
index ec11ab7011..f9db287bb9 100644
--- a/app/javascript/mastodon/components/icon_button.tsx
+++ b/app/javascript/mastodon/components/icon_button.tsx
@@ -30,7 +30,7 @@ type States = {
activate: boolean,
deactivate: boolean,
}
-export default class IconButton extends React.PureComponent {
+export class IconButton extends React.PureComponent {
static defaultProps = {
size: 18,
diff --git a/app/javascript/mastodon/components/icon_with_badge.tsx b/app/javascript/mastodon/components/icon_with_badge.tsx
index 487bf326ad..a4af86ca9b 100644
--- a/app/javascript/mastodon/components/icon_with_badge.tsx
+++ b/app/javascript/mastodon/components/icon_with_badge.tsx
@@ -9,12 +9,10 @@ type Props = {
issueBadge: boolean;
className: string;
}
-const IconWithBadge: React.FC = ({ id, count, issueBadge, className }) => (
+export const IconWithBadge: React.FC = ({ id, count, issueBadge, className }) => (
{count > 0 && {formatNumber(count)}}
{issueBadge && }
);
-
-export default IconWithBadge;
diff --git a/app/javascript/mastodon/components/image.tsx b/app/javascript/mastodon/components/image.tsx
index 9b4d602255..b332d4115b 100644
--- a/app/javascript/mastodon/components/image.tsx
+++ b/app/javascript/mastodon/components/image.tsx
@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react';
-import Blurhash from './blurhash';
+import { Blurhash } from './blurhash';
import classNames from 'classnames';
type Props = {
@@ -23,5 +23,3 @@ export const Image: React.FC = ({ src, srcSet, blurhash, className }) =>
);
};
-
-export default Image;
diff --git a/app/javascript/mastodon/components/inline_account.jsx b/app/javascript/mastodon/components/inline_account.jsx
index 31dc63f93f..ca11f8b1bc 100644
--- a/app/javascript/mastodon/components/inline_account.jsx
+++ b/app/javascript/mastodon/components/inline_account.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { makeGetAccount } from 'mastodon/selectors';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
const makeMapStateToProps = () => {
const getAccount = makeGetAccount();
diff --git a/app/javascript/mastodon/components/load_gap.jsx b/app/javascript/mastodon/components/load_gap.jsx
index 2c91d37be7..2637bdbbc4 100644
--- a/app/javascript/mastodon/components/load_gap.jsx
+++ b/app/javascript/mastodon/components/load_gap.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx
index 54470f9402..54b414de20 100644
--- a/app/javascript/mastodon/components/media_gallery.jsx
+++ b/app/javascript/mastodon/components/media_gallery.jsx
@@ -2,12 +2,12 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { is } from 'immutable';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
import { debounce } from 'lodash';
-import Blurhash from 'mastodon/components/blurhash';
+import { Blurhash } from 'mastodon/components/blurhash';
const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: '{number, plural, one {Hide image} other {Hide images}}' },
diff --git a/app/javascript/mastodon/components/not_signed_in_indicator.tsx b/app/javascript/mastodon/components/not_signed_in_indicator.tsx
index 0df90ddbf3..3bfee6ae91 100644
--- a/app/javascript/mastodon/components/not_signed_in_indicator.tsx
+++ b/app/javascript/mastodon/components/not_signed_in_indicator.tsx
@@ -8,5 +8,3 @@ export const NotSignedInIndicator: React.FC = () => (
);
-
-export default NotSignedInIndicator;
diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
index a51c974017..4763a28d10 100644
--- a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
+++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { removePictureInPicture } from 'mastodon/actions/picture_in_picture';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx
index b9b96a7005..0ccdf472eb 100644
--- a/app/javascript/mastodon/components/poll.jsx
+++ b/app/javascript/mastodon/components/poll.jsx
@@ -8,8 +8,8 @@ import Motion from 'mastodon/features/ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import escapeTextContentForBrowser from 'escape-html';
import emojify from 'mastodon/features/emoji/emoji';
-import RelativeTimestamp from './relative_timestamp';
-import Icon from 'mastodon/components/icon';
+import { RelativeTimestamp } from './relative_timestamp';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
closed: {
diff --git a/app/javascript/mastodon/components/radio_button.tsx b/app/javascript/mastodon/components/radio_button.tsx
index 9ba098f78d..194b67afe1 100644
--- a/app/javascript/mastodon/components/radio_button.tsx
+++ b/app/javascript/mastodon/components/radio_button.tsx
@@ -26,5 +26,3 @@ export const RadioButton: React.FC = ({ name, value, checked, onChange, l
);
};
-
-export default RadioButton;
diff --git a/app/javascript/mastodon/components/relative_timestamp.tsx b/app/javascript/mastodon/components/relative_timestamp.tsx
index 89cad06658..4f1a76e54b 100644
--- a/app/javascript/mastodon/components/relative_timestamp.tsx
+++ b/app/javascript/mastodon/components/relative_timestamp.tsx
@@ -200,4 +200,6 @@ class RelativeTimestamp extends React.Component {
}
-export default injectIntl(RelativeTimestamp);
+const RelativeTimestampWithIntl = injectIntl(RelativeTimestamp);
+
+export { RelativeTimestampWithIntl as RelativeTimestamp };
diff --git a/app/javascript/mastodon/components/server_banner.jsx b/app/javascript/mastodon/components/server_banner.jsx
index e5f5aa8ee2..991907a3f0 100644
--- a/app/javascript/mastodon/components/server_banner.jsx
+++ b/app/javascript/mastodon/components/server_banner.jsx
@@ -7,7 +7,7 @@ import ShortNumber from 'mastodon/components/short_number';
import Skeleton from 'mastodon/components/skeleton';
import Account from 'mastodon/containers/account_container';
import { domain } from 'mastodon/initial_state';
-import Image from 'mastodon/components/image';
+import { Image } from 'mastodon/components/image';
import { Link } from 'react-router-dom';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index b5242e7691..3ca840b720 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import Avatar from './avatar';
-import AvatarOverlay from './avatar_overlay';
-import RelativeTimestamp from './relative_timestamp';
+import { Avatar } from './avatar';
+import { AvatarOverlay } from './avatar_overlay';
+import { RelativeTimestamp } from './relative_timestamp';
import DisplayName from './display_name';
import StatusContent from './status_content';
import StatusActionBar from './status_action_bar';
@@ -14,7 +14,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { MediaGallery, Video, Audio } from '../features/ui/util/async-components';
import { HotKeys } from 'react-hotkeys';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { displayMedia } from '../initial_state';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx
index 7b4031b68e..aee9cc19e8 100644
--- a/app/javascript/mastodon/components/status_action_bar.jsx
+++ b/app/javascript/mastodon/components/status_action_bar.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
-import IconButton from './icon_button';
+import { IconButton } from './icon_button';
import DropdownMenuContainer from '../containers/dropdown_menu_container';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index dd589dac6d..cece3ffc25 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -6,7 +6,7 @@ import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import classnames from 'classnames';
import PollContainer from 'mastodon/containers/poll_container';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
diff --git a/app/javascript/mastodon/components/verified_badge.tsx b/app/javascript/mastodon/components/verified_badge.tsx
index 78686b521b..da3cab9fe5 100644
--- a/app/javascript/mastodon/components/verified_badge.tsx
+++ b/app/javascript/mastodon/components/verified_badge.tsx
@@ -10,5 +10,3 @@ export const VerifiedBadge: React.FC = ({ link }) => (
);
-
-export default VerifiedBadge;
diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx
index bb35f3203b..11aff67c67 100644
--- a/app/javascript/mastodon/features/about/index.jsx
+++ b/app/javascript/mastodon/features/about/index.jsx
@@ -9,9 +9,9 @@ import { Helmet } from 'react-helmet';
import { fetchServer, fetchExtendedDescription, fetchDomainBlocks } from 'mastodon/actions/server';
import Account from 'mastodon/containers/account_container';
import Skeleton from 'mastodon/components/skeleton';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
-import Image from 'mastodon/components/image';
+import { Image } from 'mastodon/components/image';
const messages = defineMessages({
title: { id: 'column.about', defaultMessage: 'About' },
diff --git a/app/javascript/mastodon/features/account/components/follow_request_note.jsx b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
index 300ae42660..7972515af5 100644
--- a/app/javascript/mastodon/features/account/components/follow_request_note.jsx
+++ b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
export default class FollowRequestNote extends ImmutablePureComponent {
diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx
index ff8dc5fa9f..bb0982b5e4 100644
--- a/app/javascript/mastodon/features/account/components/header.jsx
+++ b/app/javascript/mastodon/features/account/components/header.jsx
@@ -6,9 +6,9 @@ import Button from 'mastodon/components/button';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { autoPlayGif, me, domain } from 'mastodon/initial_state';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
-import IconButton from 'mastodon/components/icon_button';
-import Avatar from 'mastodon/components/avatar';
+import { Icon } from 'mastodon/components/icon';
+import { IconButton } from 'mastodon/components/icon_button';
+import { Avatar } from 'mastodon/components/avatar';
import { counterRenderer } from 'mastodon/components/common_counter';
import ShortNumber from 'mastodon/components/short_number';
import { NavLink } from 'react-router-dom';
diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
index 00526016d7..9e9b9e6e16 100644
--- a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
+++ b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
@@ -1,6 +1,6 @@
-import Blurhash from 'mastodon/components/blurhash';
+import { Blurhash } from 'mastodon/components/blurhash';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state';
import PropTypes from 'prop-types';
import React from 'react';
diff --git a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
index daff47a9d6..273583c0ad 100644
--- a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import AvatarOverlay from '../../../components/avatar_overlay';
+import { AvatarOverlay } from '../../../components/avatar_overlay';
import DisplayName from '../../../components/display_name';
import { Link } from 'react-router-dom';
diff --git a/app/javascript/mastodon/features/audio/index.jsx b/app/javascript/mastodon/features/audio/index.jsx
index e8fe2c4d9a..56e913ae3a 100644
--- a/app/javascript/mastodon/features/audio/index.jsx
+++ b/app/javascript/mastodon/features/audio/index.jsx
@@ -2,12 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { formatTime, getPointerPosition, fileNameFromURL } from 'mastodon/features/video';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
import { throttle, debounce } from 'lodash';
import Visualizer from './visualizer';
import { displayMedia, useBlurhash } from '../../initial_state';
-import Blurhash from '../../components/blurhash';
+import { Blurhash } from '../../components/blurhash';
import { is } from 'immutable';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
index 1451be0e64..2c92016e86 100644
--- a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
+++ b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx
index df11d2c97e..42bba5cdf0 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx
@@ -19,7 +19,7 @@ import LanguageDropdown from '../containers/language_dropdown_container';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { length } from 'stringz';
import { countableText } from '../util/counter';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
import { maxChars } from '../../../initial_state';
diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
index be979af505..b5a7b6bda2 100644
--- a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
@@ -2,9 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ActionBar from './action_bar';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import { Link } from 'react-router-dom';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import { FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/compose/components/poll_button.jsx b/app/javascript/mastodon/features/compose/components/poll_button.jsx
index 6ad689ccc8..5d90564bd1 100644
--- a/app/javascript/mastodon/features/compose/components/poll_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_button.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx
index f81d7355ae..6bee97935d 100644
--- a/app/javascript/mastodon/features/compose/components/poll_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx
@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import IconButton from 'mastodon/components/icon_button';
-import Icon from 'mastodon/components/icon';
+import { IconButton } from 'mastodon/components/icon_button';
+import { Icon } from 'mastodon/components/icon';
import AutosuggestInput from 'mastodon/components/autosuggest_input';
import classNames from 'classnames';
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
index e65c9cb726..ecb7accad9 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
@@ -1,11 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import Overlay from 'react-overlays/Overlay';
import { supportsPassiveEvents } from 'detect-passive-events';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
index 81de4ea765..68cd7b0804 100644
--- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
+++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import Avatar from '../../../components/avatar';
-import IconButton from '../../../components/icon_button';
+import { Avatar } from '../../../components/avatar';
+import { IconButton } from '../../../components/icon_button';
import DisplayName from '../../../components/display_name';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx
index 7fff587d68..d20908b9df 100644
--- a/app/javascript/mastodon/features/compose/components/search.jsx
+++ b/app/javascript/mastodon/features/compose/components/search.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { searchEnabled } from 'mastodon/initial_state';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
diff --git a/app/javascript/mastodon/features/compose/components/search_results.jsx b/app/javascript/mastodon/features/compose/components/search_results.jsx
index 8fafd88b07..9a44e2eaf7 100644
--- a/app/javascript/mastodon/features/compose/components/search_results.jsx
+++ b/app/javascript/mastodon/features/compose/components/search_results.jsx
@@ -6,7 +6,7 @@ import AccountContainer from '../../../containers/account_container';
import StatusContainer from '../../../containers/status_container';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { ImmutableHashtag as Hashtag } from '../../../components/hashtag';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { searchEnabled } from '../../../initial_state';
import LoadMore from 'mastodon/components/load_more';
diff --git a/app/javascript/mastodon/features/compose/components/upload.jsx b/app/javascript/mastodon/features/compose/components/upload.jsx
index e3651c2290..d667f5ef71 100644
--- a/app/javascript/mastodon/features/compose/components/upload.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload.jsx
@@ -5,7 +5,7 @@ import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
export default class Upload extends ImmutablePureComponent {
diff --git a/app/javascript/mastodon/features/compose/components/upload_button.jsx b/app/javascript/mastodon/features/compose/components/upload_button.jsx
index f2e6ff85c3..3870997c3d 100644
--- a/app/javascript/mastodon/features/compose/components/upload_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_button.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
diff --git a/app/javascript/mastodon/features/compose/components/upload_progress.jsx b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
index cabf520fd9..c5740d9bf5 100644
--- a/app/javascript/mastodon/features/compose/components/upload_progress.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { FormattedMessage } from 'react-intl';
export default class UploadProgress extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
index 5ec937a393..9d9a59c414 100644
--- a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
+++ b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
@@ -72,6 +72,7 @@ const mapDispatchToProps = (dispatch, { onPickEmoji }) => ({
},
onPickEmoji: emoji => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
dispatch(useEmoji(emoji));
if (onPickEmoji) {
diff --git a/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js b/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js
index 2a040a13f4..5560fe6093 100644
--- a/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js
+++ b/app/javascript/mastodon/features/compose/containers/language_dropdown_container.js
@@ -26,6 +26,7 @@ const mapDispatchToProps = dispatch => ({
},
onClose (value) {
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
dispatch(useLanguage(value));
},
diff --git a/app/javascript/mastodon/features/compose/index.jsx b/app/javascript/mastodon/features/compose/index.jsx
index 6cba1e9ad8..df60d4347e 100644
--- a/app/javascript/mastodon/features/compose/index.jsx
+++ b/app/javascript/mastodon/features/compose/index.jsx
@@ -14,7 +14,7 @@ import SearchResultsContainer from './containers/search_results_container';
import { openModal } from 'mastodon/actions/modal';
import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
import { mascot } from '../../initial_state';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { logOut } from 'mastodon/utils/log_out';
import Column from 'mastodon/components/column';
import { Helmet } from 'react-helmet';
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index 11f2790bff..452de11619 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -8,8 +8,8 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
import AvatarComposite from 'mastodon/components/avatar_composite';
import { Link } from 'react-router-dom';
-import IconButton from 'mastodon/components/icon_button';
-import RelativeTimestamp from 'mastodon/components/relative_timestamp';
+import { IconButton } from 'mastodon/components/icon_button';
+import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import { HotKeys } from 'react-hotkeys';
import { autoPlayGif } from 'mastodon/initial_state';
import classNames from 'classnames';
diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx
index 1cee3a4e4e..4951427151 100644
--- a/app/javascript/mastodon/features/directory/components/account_card.jsx
+++ b/app/javascript/mastodon/features/directory/components/account_card.jsx
@@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { makeGetAccount } from 'mastodon/selectors';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
import DisplayName from 'mastodon/components/display_name';
import { Link } from 'react-router-dom';
import Button from 'mastodon/components/button';
diff --git a/app/javascript/mastodon/features/directory/index.jsx b/app/javascript/mastodon/features/directory/index.jsx
index afaf39b773..d98a0665ac 100644
--- a/app/javascript/mastodon/features/directory/index.jsx
+++ b/app/javascript/mastodon/features/directory/index.jsx
@@ -9,7 +9,7 @@ import { addColumn, removeColumn, moveColumn, changeColumnParams } from 'mastodo
import { fetchDirectory, expandDirectory } from 'mastodon/actions/directory';
import { List as ImmutableList } from 'immutable';
import AccountCard from './components/account_card';
-import RadioButton from 'mastodon/components/radio_button';
+import { RadioButton } from 'mastodon/components/radio_button';
import LoadMore from 'mastodon/components/load_more';
import ScrollContainer from 'mastodon/containers/scroll_container';
import LoadingIndicator from 'mastodon/components/loading_indicator';
diff --git a/app/javascript/mastodon/features/emoji/emoji_compressed.js b/app/javascript/mastodon/features/emoji/emoji_compressed.js
index 6a402f2d4b..e1bee1655d 100644
--- a/app/javascript/mastodon/features/emoji/emoji_compressed.js
+++ b/app/javascript/mastodon/features/emoji/emoji_compressed.js
@@ -1,3 +1,5 @@
+/* eslint-disable import/no-commonjs --
+ We need to use CommonJS here due to preval */
// @preval
// http://www.unicode.org/Public/emoji/5.0/emoji-test.txt
// This file contains the compressed version of the emoji data from
diff --git a/app/javascript/mastodon/features/emoji/emoji_mart_data_light.js b/app/javascript/mastodon/features/emoji/emoji_mart_data_light.js
index 49813537d7..000aeb0de4 100644
--- a/app/javascript/mastodon/features/emoji/emoji_mart_data_light.js
+++ b/app/javascript/mastodon/features/emoji/emoji_mart_data_light.js
@@ -1,8 +1,10 @@
// The output of this module is designed to mimic emoji-mart's
// "data" object, such that we can use it for a light version of emoji-mart's
// emojiIndex.search functionality.
-const { unicodeToUnifiedName } = require('./unicode_to_unified_name');
-const [ shortCodesToEmojiData, skins, categories, short_names ] = require('./emoji_compressed');
+import { unicodeToUnifiedName } from './unicode_to_unified_name';
+import emojiCompressed from './emoji_compressed';
+
+const [ shortCodesToEmojiData, skins, categories, short_names ] = emojiCompressed;
const emojis = {};
@@ -33,7 +35,7 @@ Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
};
});
-module.exports = {
+export {
emojis,
skins,
categories,
diff --git a/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js b/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js
index 70694ab6dd..83e154b0b2 100644
--- a/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js
+++ b/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js
@@ -1,7 +1,7 @@
// This code is largely borrowed from:
// https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/emoji-index.js
-import data from './emoji_mart_data_light';
+import * as data from './emoji_mart_data_light';
import { getData, getSanitizedData, uniq, intersect } from './emoji_utils';
let originalPool = {};
diff --git a/app/javascript/mastodon/features/emoji/emoji_unicode_mapping_light.js b/app/javascript/mastodon/features/emoji/emoji_unicode_mapping_light.js
index 1a38fde234..30fbd9e349 100644
--- a/app/javascript/mastodon/features/emoji/emoji_unicode_mapping_light.js
+++ b/app/javascript/mastodon/features/emoji/emoji_unicode_mapping_light.js
@@ -2,14 +2,17 @@
// (i.e. the svg filename) and a shortCode intended to be shown
// as a "title" attribute in an HTML element (aka tooltip).
+import emojiCompressed from './emoji_compressed';
+
+import { unicodeToFilename } from './unicode_to_filename';
+
const [
shortCodesToEmojiData,
- skins, // eslint-disable-line @typescript-eslint/no-unused-vars
- categories, // eslint-disable-line @typescript-eslint/no-unused-vars
- short_names, // eslint-disable-line @typescript-eslint/no-unused-vars
+ _skins,
+ _categories,
+ _short_names,
emojisWithoutShortCodes,
-] = require('./emoji_compressed');
-const { unicodeToFilename } = require('./unicode_to_filename');
+] = emojiCompressed;
// decompress
const unicodeMapping = {};
@@ -32,4 +35,4 @@ Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
});
emojisWithoutShortCodes.forEach(emojiMapData => processEmojiMapData(emojiMapData));
-module.exports = unicodeMapping;
+export default unicodeMapping;
diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.js b/app/javascript/mastodon/features/emoji/emoji_utils.js
index be793526d0..83bcc9d82f 100644
--- a/app/javascript/mastodon/features/emoji/emoji_utils.js
+++ b/app/javascript/mastodon/features/emoji/emoji_utils.js
@@ -1,7 +1,7 @@
// This code is largely borrowed from:
// https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js
-import data from './emoji_mart_data_light';
+import * as data from './emoji_mart_data_light';
const buildSearch = (data) => {
const search = [];
diff --git a/app/javascript/mastodon/features/emoji/unicode_to_filename.js b/app/javascript/mastodon/features/emoji/unicode_to_filename.js
index c75c4cd7d0..3395c77174 100644
--- a/app/javascript/mastodon/features/emoji/unicode_to_filename.js
+++ b/app/javascript/mastodon/features/emoji/unicode_to_filename.js
@@ -1,3 +1,6 @@
+/* eslint-disable import/no-commonjs --
+ We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
+
// taken from:
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
exports.unicodeToFilename = (str) => {
diff --git a/app/javascript/mastodon/features/emoji/unicode_to_unified_name.js b/app/javascript/mastodon/features/emoji/unicode_to_unified_name.js
index d29550f122..108b911222 100644
--- a/app/javascript/mastodon/features/emoji/unicode_to_unified_name.js
+++ b/app/javascript/mastodon/features/emoji/unicode_to_unified_name.js
@@ -1,3 +1,6 @@
+/* eslint-disable import/no-commonjs --
+ We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
+
function padLeft(str, num) {
while (str.length < num) {
str = '0' + str;
diff --git a/app/javascript/mastodon/features/explore/components/story.jsx b/app/javascript/mastodon/features/explore/components/story.jsx
index 5631280297..c7320c886d 100644
--- a/app/javascript/mastodon/features/explore/components/story.jsx
+++ b/app/javascript/mastodon/features/explore/components/story.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Blurhash from 'mastodon/components/blurhash';
+import { Blurhash } from 'mastodon/components/blurhash';
import { accountsCountRenderer } from 'mastodon/components/hashtag';
import ShortNumber from 'mastodon/components/short_number';
import Skeleton from 'mastodon/components/skeleton';
diff --git a/app/javascript/mastodon/features/favourites/index.jsx b/app/javascript/mastodon/features/favourites/index.jsx
index b1e81debd5..4a8c1deb6f 100644
--- a/app/javascript/mastodon/features/favourites/index.jsx
+++ b/app/javascript/mastodon/features/favourites/index.jsx
@@ -5,7 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import ColumnHeader from 'mastodon/components/column_header';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { fetchFavourites } from 'mastodon/actions/interactions';
import LoadingIndicator from 'mastodon/components/loading_indicator';
import ScrollableList from 'mastodon/components/scrollable_list';
diff --git a/app/javascript/mastodon/features/filters/select_filter.jsx b/app/javascript/mastodon/features/filters/select_filter.jsx
index 5778eec8e9..618f875dbe 100644
--- a/app/javascript/mastodon/features/filters/select_filter.jsx
+++ b/app/javascript/mastodon/features/filters/select_filter.jsx
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { toServerSideType } from 'mastodon/utils/filters';
import { loupeIcon, deleteIcon } from 'mastodon/utils/icons';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import fuzzysort from 'fuzzysort';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
index 0bd45592c9..b370b33ecb 100644
--- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
+++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
@@ -2,9 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { Link } from 'react-router-dom';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
index 5f993d2c55..ab29e3dc86 100644
--- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
@@ -3,15 +3,15 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import ReactSwipeableViews from 'react-swipeable-views';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import IconButton from 'mastodon/components/icon_button';
-import Icon from 'mastodon/components/icon';
+import { IconButton } from 'mastodon/components/icon_button';
+import { Icon } from 'mastodon/components/icon';
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
import classNames from 'classnames';
import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
-import AnimatedNumber from 'mastodon/components/animated_number';
+import { AnimatedNumber } from 'mastodon/components/animated_number';
import TransitionMotion from 'react-motion/lib/TransitionMotion';
import spring from 'react-motion/lib/spring';
import { assetHost } from 'mastodon/utils/config';
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.jsx b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
index a244dbdb22..116a5921c1 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.jsx
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
@@ -12,7 +12,7 @@ import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
import { connectHashtagStream } from 'mastodon/actions/streaming';
import { isEqual } from 'lodash';
import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
import { Helmet } from 'react-helmet';
diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx
index 9aa4c6d821..26166b254c 100644
--- a/app/javascript/mastodon/features/home_timeline/index.jsx
+++ b/app/javascript/mastodon/features/home_timeline/index.jsx
@@ -12,8 +12,8 @@ import { Link } from 'react-router-dom';
import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/announcements';
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
import classNames from 'classnames';
-import IconWithBadge from 'mastodon/components/icon_with_badge';
-import NotSignedInIndicator from 'mastodon/components/not_signed_in_indicator';
+import { IconWithBadge } from 'mastodon/components/icon_with_badge';
+import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
import { Helmet } from 'react-helmet';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx
index 5742f11042..f3db2c78d5 100644
--- a/app/javascript/mastodon/features/interaction_modal/index.jsx
+++ b/app/javascript/mastodon/features/interaction_modal/index.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { registrationsOpen } from 'mastodon/initial_state';
import { connect } from 'react-redux';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
import { openModal, closeModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/list_adder/components/account.jsx b/app/javascript/mastodon/features/list_adder/components/account.jsx
index 786af3bb1c..410f1537a5 100644
--- a/app/javascript/mastodon/features/list_adder/components/account.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/account.jsx
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import { makeGetAccount } from '../../../selectors';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
import { injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/list_adder/components/list.jsx b/app/javascript/mastodon/features/list_adder/components/list.jsx
index 34ccf8451d..954a4a5cfe 100644
--- a/app/javascript/mastodon/features/list_adder/components/list.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/list.jsx
@@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import { removeFromListAdder, addToListAdder } from '../../../actions/lists';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
diff --git a/app/javascript/mastodon/features/list_editor/components/account.jsx b/app/javascript/mastodon/features/list_editor/components/account.jsx
index 86209bb3cb..b46d0504a4 100644
--- a/app/javascript/mastodon/features/list_editor/components/account.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/account.jsx
@@ -4,9 +4,9 @@ import { connect } from 'react-redux';
import { makeGetAccount } from '../../../selectors';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import { removeFromListEditor, addToListEditor } from '../../../actions/lists';
diff --git a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
index 9c1c244cbc..65bfe7f94a 100644
--- a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { changeListEditorTitle, submitListEditor } from '../../../actions/lists';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/list_editor/components/search.jsx b/app/javascript/mastodon/features/list_editor/components/search.jsx
index f70e272f79..59e4c7d939 100644
--- a/app/javascript/mastodon/features/list_editor/components/search.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/search.jsx
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { defineMessages, injectIntl } from 'react-intl';
import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
search: { id: 'lists.search', defaultMessage: 'Search among people you follow' },
diff --git a/app/javascript/mastodon/features/list_timeline/index.jsx b/app/javascript/mastodon/features/list_timeline/index.jsx
index 8297c2748d..c93305341a 100644
--- a/app/javascript/mastodon/features/list_timeline/index.jsx
+++ b/app/javascript/mastodon/features/list_timeline/index.jsx
@@ -11,9 +11,9 @@ import { connectListStream } from 'mastodon/actions/streaming';
import { expandListTimeline } from 'mastodon/actions/timelines';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import LoadingIndicator from 'mastodon/components/loading_indicator';
-import RadioButton from 'mastodon/components/radio_button';
+import { RadioButton } from 'mastodon/components/radio_button';
import StatusListContainer from 'mastodon/features/ui/containers/status_list_container';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
diff --git a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
index 9a076ce5ed..e043f5ee1e 100644
--- a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
export default class ClearColumnButton extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
index 88e95cf48f..f16c84f97a 100644
--- a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
+++ b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const tooltips = defineMessages({
mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
diff --git a/app/javascript/mastodon/features/notifications/components/follow_request.jsx b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
index 01bf670650..0d930f0b1f 100644
--- a/app/javascript/mastodon/features/notifications/components/follow_request.jsx
+++ b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
import DisplayName from 'mastodon/components/display_name';
import { Link } from 'react-router-dom';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx
index f3104cee05..0f1aef8db1 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notification.jsx
@@ -9,7 +9,7 @@ import StatusContainer from 'mastodon/containers/status_container';
import AccountContainer from 'mastodon/containers/account_container';
import Report from './report';
import FollowRequestContainer from '../containers/follow_request_container';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
diff --git a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
index c54137e60c..a1b4248e7c 100644
--- a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
@@ -1,7 +1,7 @@
import React from 'react';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import Button from 'mastodon/components/button';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import { requestBrowserPermission } from 'mastodon/actions/notifications';
import { changeSetting } from 'mastodon/actions/settings';
import { connect } from 'react-redux';
diff --git a/app/javascript/mastodon/features/notifications/components/report.jsx b/app/javascript/mastodon/features/notifications/components/report.jsx
index a9decdc8e9..1c0e1a7750 100644
--- a/app/javascript/mastodon/features/notifications/components/report.jsx
+++ b/app/javascript/mastodon/features/notifications/components/report.jsx
@@ -3,8 +3,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import AvatarOverlay from 'mastodon/components/avatar_overlay';
-import RelativeTimestamp from 'mastodon/components/relative_timestamp';
+import { AvatarOverlay } from 'mastodon/components/avatar_overlay';
+import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
const messages = defineMessages({
openReport: { id: 'report_notification.open', defaultMessage: 'Open report' },
diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx
index bb8852abf1..8a31c5db6c 100644
--- a/app/javascript/mastodon/features/notifications/index.jsx
+++ b/app/javascript/mastodon/features/notifications/index.jsx
@@ -23,10 +23,10 @@ import { List as ImmutableList } from 'immutable';
import { debounce } from 'lodash';
import ScrollableList from '../../components/scrollable_list';
import LoadGap from '../../components/load_gap';
-import Icon from 'mastodon/components/icon';
-import compareId from 'mastodon/compare_id';
+import { Icon } from 'mastodon/components/icon';
+import { compareId } from 'mastodon/compare_id';
import NotificationsPermissionBanner from './components/notifications_permission_banner';
-import NotSignedInIndicator from 'mastodon/components/not_signed_in_indicator';
+import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
import { Helmet } from 'react-helmet';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx b/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
index 97134c0c9c..7d75e50edb 100644
--- a/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Check from 'mastodon/components/check';
+import { Check } from 'mastodon/components/check';
import classNames from 'classnames';
const ProgressIndicator = ({ steps, completed }) => (
@@ -22,4 +22,4 @@ ProgressIndicator.propTypes = {
completed: PropTypes.number,
};
-export default ProgressIndicator;
\ No newline at end of file
+export default ProgressIndicator;
diff --git a/app/javascript/mastodon/features/onboarding/components/step.jsx b/app/javascript/mastodon/features/onboarding/components/step.jsx
index 6f376e5d55..38e4b564a8 100644
--- a/app/javascript/mastodon/features/onboarding/components/step.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/step.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Icon from 'mastodon/components/icon';
-import Check from 'mastodon/components/check';
+import { Icon } from 'mastodon/components/icon';
+import { Check } from 'mastodon/components/check';
const Step = ({ label, description, icon, completed, onClick, href }) => {
const content = (
@@ -47,4 +47,4 @@ Step.propTypes = {
onClick: PropTypes.func,
};
-export default Step;
\ No newline at end of file
+export default Step;
diff --git a/app/javascript/mastodon/features/onboarding/share.jsx b/app/javascript/mastodon/features/onboarding/share.jsx
index 9555a3a43a..5f7cfb8a6b 100644
--- a/app/javascript/mastodon/features/onboarding/share.jsx
+++ b/app/javascript/mastodon/features/onboarding/share.jsx
@@ -7,7 +7,7 @@ import { connect } from 'react-redux';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage, FormattedHTMLMessage } from 'react-intl';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import ArrowSmallRight from './components/arrow_small_right';
import { Link } from 'react-router-dom';
import SwipeableViews from 'react-swipeable-views';
@@ -190,4 +190,4 @@ class Share extends React.PureComponent {
}
-export default connect(mapStateToProps)(injectIntl(Share));
\ No newline at end of file
+export default connect(mapStateToProps)(injectIntl(Share));
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
index 66124f3311..5c60284d65 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import classNames from 'classnames';
import { me, boostModal } from 'mastodon/initial_state';
import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
index 100f9db7ac..c6d2a103dc 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
@@ -3,9 +3,9 @@ import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import { Link } from 'react-router-dom';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
import DisplayName from 'mastodon/components/display_name';
import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/reblogs/index.jsx b/app/javascript/mastodon/features/reblogs/index.jsx
index 35edb0d6af..fb503f40f1 100644
--- a/app/javascript/mastodon/features/reblogs/index.jsx
+++ b/app/javascript/mastodon/features/reblogs/index.jsx
@@ -9,7 +9,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import AccountContainer from '../../containers/account_container';
import Column from '../ui/components/column';
import ScrollableList from '../../components/scrollable_list';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import ColumnHeader from '../../components/column_header';
import { Helmet } from 'react-helmet';
diff --git a/app/javascript/mastodon/features/report/components/option.jsx b/app/javascript/mastodon/features/report/components/option.jsx
index 342204e22f..34df4d73b3 100644
--- a/app/javascript/mastodon/features/report/components/option.jsx
+++ b/app/javascript/mastodon/features/report/components/option.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-import Check from 'mastodon/components/check';
+import { Check } from 'mastodon/components/check';
export default class Option extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/report/components/status_check_box.jsx b/app/javascript/mastodon/features/report/components/status_check_box.jsx
index 28d572e898..003cdc8e3a 100644
--- a/app/javascript/mastodon/features/report/components/status_check_box.jsx
+++ b/app/javascript/mastodon/features/report/components/status_check_box.jsx
@@ -2,13 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import StatusContent from 'mastodon/components/status_content';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
import DisplayName from 'mastodon/components/display_name';
-import RelativeTimestamp from 'mastodon/components/relative_timestamp';
+import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import Option from './option';
import MediaAttachments from 'mastodon/components/media_attachments';
import { injectIntl, defineMessages } from 'react-intl';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx
index 0c74c4cc4d..e5b08ff285 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/status/components/action_bar.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import ImmutablePropTypes from 'react-immutable-proptypes';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx
index 88b38c65ad..1d5edfc173 100644
--- a/app/javascript/mastodon/features/status/components/card.jsx
+++ b/app/javascript/mastodon/features/status/components/card.jsx
@@ -5,9 +5,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl';
import punycode from 'punycode';
import classnames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { useBlurhash } from 'mastodon/initial_state';
-import Blurhash from 'mastodon/components/blurhash';
+import { Blurhash } from 'mastodon/components/blurhash';
const IDNA_PREFIX = 'xn--';
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx
index e4e5720268..72c9021242 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.jsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import Avatar from '../../../components/avatar';
+import { Avatar } from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
import StatusContent from '../../../components/status_content';
import MediaGallery from '../../../components/media_gallery';
@@ -13,8 +13,8 @@ import Video from '../../video';
import Audio from '../../audio';
import scheduleIdleTask from '../../ui/util/schedule_idle_task';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
-import AnimatedNumber from 'mastodon/components/animated_number';
+import { Icon } from 'mastodon/components/icon';
+import { AnimatedNumber } from 'mastodon/components/animated_number';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
import EditedTimestamp from 'mastodon/components/edited_timestamp';
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 7f1896aedb..0c0b557487 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -58,7 +58,7 @@ import { HotKeys } from 'react-hotkeys';
import { boostModal, deleteModal } from '../../initial_state';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import { Helmet } from 'react-helmet';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
diff --git a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
index 04fe31b5c1..a9dd1e0720 100644
--- a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
+++ b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
@@ -8,7 +8,7 @@ import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
import { languages as preloadedLanguages } from 'mastodon/initial_state';
import Option from 'mastodon/features/report/components/option';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import Button from 'mastodon/components/button';
import { followAccount } from 'mastodon/actions/accounts';
diff --git a/app/javascript/mastodon/features/ui/components/actions_modal.jsx b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
index 35090e2426..9d11da6085 100644
--- a/app/javascript/mastodon/features/ui/components/actions_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
import classNames from 'classnames';
export default class ActionsModal extends ImmutablePureComponent {
diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.jsx b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
index fe55c963a8..1f28927d60 100644
--- a/app/javascript/mastodon/features/ui/components/boost_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
@@ -5,11 +5,11 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import Button from '../../../components/button';
import StatusContent from '../../../components/status_content';
-import Avatar from '../../../components/avatar';
-import RelativeTimestamp from '../../../components/relative_timestamp';
+import { Avatar } from '../../../components/avatar';
+import { RelativeTimestamp } from '../../../components/relative_timestamp';
import DisplayName from '../../../components/display_name';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import AttachmentList from 'mastodon/components/attachment_list';
import PrivacyDropdown from 'mastodon/features/compose/components/privacy_dropdown';
import classNames from 'classnames';
diff --git a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
index d79d0ca4a0..6ddf2ae7ac 100644
--- a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
+++ b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
-import IconButton from '../../../components/icon_button';
+import { IconButton } from '../../../components/icon_button';
const messages = defineMessages({
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' },
diff --git a/app/javascript/mastodon/features/ui/components/column_header.jsx b/app/javascript/mastodon/features/ui/components/column_header.jsx
index 4ceef59570..a2d3a38710 100644
--- a/app/javascript/mastodon/features/ui/components/column_header.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_header.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
export default class ColumnHeader extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/ui/components/column_link.jsx b/app/javascript/mastodon/features/ui/components/column_link.jsx
index 8eebbf5260..4e9164afb7 100644
--- a/app/javascript/mastodon/features/ui/components/column_link.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_link.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';
-import Icon from 'mastodon/components/icon';
+import { Icon } from 'mastodon/components/icon';
import classNames from 'classnames';
const ColumnLink = ({ icon, text, to, href, method, badge, transparent, ...other }) => {
diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
index 1802c167c1..8e4c4d1368 100644
--- a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
@@ -7,8 +7,8 @@ import { closeModal } from 'mastodon/actions/modal';
import emojify from 'mastodon/features/emoji/emoji';
import escapeTextContentForBrowser from 'escape-html';
import InlineAccount from 'mastodon/components/inline_account';
-import IconButton from 'mastodon/components/icon_button';
-import RelativeTimestamp from 'mastodon/components/relative_timestamp';
+import { IconButton } from 'mastodon/components/icon_button';
+import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import MediaAttachments from 'mastodon/components/media_attachments';
const mapStateToProps = (state, { statusId }) => ({
diff --git a/app/javascript/mastodon/features/ui/components/embed_modal.jsx b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
index baf6be411f..3e0bcc93cb 100644
--- a/app/javascript/mastodon/features/ui/components/embed_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import api from 'mastodon/api';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
diff --git a/app/javascript/mastodon/features/ui/components/filter_modal.jsx b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
index 8d77fb3dfe..473fe4b360 100644
--- a/app/javascript/mastodon/features/ui/components/filter_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
@@ -5,7 +5,7 @@ import { fetchFilters, createFilter, createFilterStatus } from 'mastodon/actions
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import SelectFilter from 'mastodon/features/filters/select_filter';
import AddedToFilter from 'mastodon/features/filters/added_to_filter';
diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
index 2a1e4c8bbc..eda550b04d 100644
--- a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
@@ -7,7 +7,7 @@ import classNames from 'classnames';
import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from '../../../actions/compose';
import { getPointerPosition } from '../../video';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import Button from 'mastodon/components/button';
import Video from 'mastodon/features/video';
import Audio from 'mastodon/features/audio';
@@ -16,7 +16,7 @@ import UploadProgress from 'mastodon/features/compose/components/upload_progress
import CharacterCounter from 'mastodon/features/compose/components/character_counter';
import { length } from 'stringz';
import { Tesseract as fetchTesseract } from 'mastodon/features/ui/util/async-components';
-import GIFV from 'mastodon/components/gifv';
+import { GIFV } from 'mastodon/components/gifv';
import { me } from 'mastodon/initial_state';
// eslint-disable-next-line import/no-extraneous-dependencies
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
diff --git a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
index 1cd1b79bce..9c8ebd13cd 100644
--- a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
+++ b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { fetchFollowRequests } from 'mastodon/actions/accounts';
import { connect } from 'react-redux';
import ColumnLink from 'mastodon/features/ui/components/column_link';
-import IconWithBadge from 'mastodon/components/icon_with_badge';
+import { IconWithBadge } from 'mastodon/components/icon_with_badge';
import { List as ImmutableList } from 'immutable';
import { injectIntl, defineMessages } from 'react-intl';
diff --git a/app/javascript/mastodon/features/ui/components/header.jsx b/app/javascript/mastodon/features/ui/components/header.jsx
index a4def456b4..af18ac3310 100644
--- a/app/javascript/mastodon/features/ui/components/header.jsx
+++ b/app/javascript/mastodon/features/ui/components/header.jsx
@@ -3,7 +3,7 @@ import { WordmarkLogo, SymbolLogo } from 'mastodon/components/logo';
import { Link, withRouter } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { registrationsOpen, me } from 'mastodon/initial_state';
-import Avatar from 'mastodon/components/avatar';
+import { Avatar } from 'mastodon/components/avatar';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { openModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/ui/components/image_modal.jsx b/app/javascript/mastodon/features/ui/components/image_modal.jsx
index ca93d7b4ed..31c5ab37ad 100644
--- a/app/javascript/mastodon/features/ui/components/image_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/image_modal.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { defineMessages, injectIntl } from 'react-intl';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import ImageLoader from './image_loader';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.jsx b/app/javascript/mastodon/features/ui/components/media_modal.jsx
index ec6ddc0e11..e8293c2e78 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/media_modal.jsx
@@ -6,11 +6,11 @@ import Video from 'mastodon/features/video';
import { connect } from 'react-redux';
import classNames from 'classnames';
import { defineMessages, injectIntl } from 'react-intl';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImageLoader from './image_loader';
-import Icon from 'mastodon/components/icon';
-import GIFV from 'mastodon/components/gifv';
+import { Icon } from 'mastodon/components/icon';
+import { GIFV } from 'mastodon/components/gifv';
import { disableSwiping } from 'mastodon/initial_state';
import Footer from 'mastodon/features/picture_in_picture/components/footer';
import { getAverageFromBlurhash } from 'mastodon/blurhash';
diff --git a/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js b/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
index da553cd9f0..7ef251603c 100644
--- a/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
+++ b/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
@@ -1,5 +1,5 @@
import { connect } from 'react-redux';
-import IconWithBadge from 'mastodon/components/icon_with_badge';
+import { IconWithBadge } from 'mastodon/components/icon_with_badge';
const mapStateToProps = state => ({
count: state.getIn(['notifications', 'unread']),
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.jsx b/app/javascript/mastodon/features/ui/components/report_modal.jsx
index 8b505b8bd8..f3ada9c07b 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/report_modal.jsx
@@ -9,7 +9,7 @@ import { makeGetAccount } from 'mastodon/selectors';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { OrderedSet } from 'immutable';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import Category from 'mastodon/features/report/category';
import Statuses from 'mastodon/features/report/statuses';
import Rules from 'mastodon/features/report/rules';
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
index b41d0fe316..49be6d5c3b 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import IconButton from 'mastodon/components/icon_button';
+import { IconButton } from 'mastodon/components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
diff --git a/app/javascript/mastodon/features/video/index.jsx b/app/javascript/mastodon/features/video/index.jsx
index d76d34546b..8b57cf3d10 100644
--- a/app/javascript/mastodon/features/video/index.jsx
+++ b/app/javascript/mastodon/features/video/index.jsx
@@ -6,8 +6,8 @@ import { throttle } from 'lodash';
import classNames from 'classnames';
import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen';
import { displayMedia, useBlurhash } from '../../initial_state';
-import Icon from 'mastodon/components/icon';
-import Blurhash from 'mastodon/components/blurhash';
+import { Icon } from 'mastodon/components/icon';
+import { Blurhash } from 'mastodon/components/blurhash';
const messages = defineMessages({
play: { id: 'video.play', defaultMessage: 'Play' },
diff --git a/app/javascript/mastodon/main.jsx b/app/javascript/mastodon/main.jsx
index 88a205dd24..d8654adedb 100644
--- a/app/javascript/mastodon/main.jsx
+++ b/app/javascript/mastodon/main.jsx
@@ -5,8 +5,7 @@ import Mastodon from 'mastodon/containers/mastodon';
import { store } from 'mastodon/store/configureStore';
import { me } from 'mastodon/initial_state';
import ready from 'mastodon/ready';
-
-const perf = require('mastodon/performance');
+import * as perf from 'mastodon/performance';
/**
* @returns {Promise}
diff --git a/app/javascript/mastodon/performance.js b/app/javascript/mastodon/performance.js
index 95cf962d6b..42849c82b1 100644
--- a/app/javascript/mastodon/performance.js
+++ b/app/javascript/mastodon/performance.js
@@ -2,9 +2,8 @@
// Tools for performance debugging, only enabled in development mode.
// Open up Chrome Dev Tools, then Timeline, then User Timing to see output.
// Also see config/webpack/loaders/mark.js for the webpack loader marks.
-//
-let marky;
+import * as marky from 'marky';
if (process.env.NODE_ENV === 'development') {
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
@@ -13,7 +12,6 @@ if (process.env.NODE_ENV === 'development') {
performance.setResourceTimingBufferSize(Infinity);
}
- marky = require('marky');
// allows us to easily do e.g. ReactPerf.printWasted() while debugging
//window.ReactPerf = require('react-addons-perf');
//window.ReactPerf.start();
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 65f439e03c..3e750c4cfa 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -52,7 +52,7 @@ import { TIMELINE_DELETE } from '../actions/timelines';
import { STORE_HYDRATE } from '../actions/store';
import { REDRAFT } from '../actions/statuses';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
-import uuid from '../uuid';
+import { uuid } from '../uuid';
import { me } from '../initial_state';
import { unescapeHTML } from '../utils/html';
diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js
index 7aa95b5d50..8772e175ea 100644
--- a/app/javascript/mastodon/reducers/contexts.js
+++ b/app/javascript/mastodon/reducers/contexts.js
@@ -5,7 +5,7 @@ import {
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import compareId from '../compare_id';
+import { compareId } from '../compare_id';
const initialState = ImmutableMap({
inReplyTos: ImmutableMap(),
diff --git a/app/javascript/mastodon/reducers/conversations.js b/app/javascript/mastodon/reducers/conversations.js
index feccf18f03..942c6941b6 100644
--- a/app/javascript/mastodon/reducers/conversations.js
+++ b/app/javascript/mastodon/reducers/conversations.js
@@ -11,7 +11,7 @@ import {
} from '../actions/conversations';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
-import compareId from '../compare_id';
+import { compareId } from '../compare_id';
const initialState = ImmutableMap({
items: ImmutableList(),
diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js
index 69771ad1b3..4d705f0412 100644
--- a/app/javascript/mastodon/reducers/index.js
+++ b/app/javascript/mastodon/reducers/index.js
@@ -33,7 +33,7 @@ import conversations from './conversations';
import suggestions from './suggestions';
import polls from './polls';
import trends from './trends';
-import missed_updates from './missed_updates';
+import { missedUpdatesReducer } from './missed_updates';
import announcements from './announcements';
import markers from './markers';
import picture_in_picture from './picture_in_picture';
@@ -79,7 +79,7 @@ const reducers = {
suggestions,
polls,
trends,
- missed_updates,
+ missed_updates: missedUpdatesReducer,
markers,
picture_in_picture,
history,
diff --git a/app/javascript/mastodon/reducers/missed_updates.ts b/app/javascript/mastodon/reducers/missed_updates.ts
index 043fe93faf..628fed2a99 100644
--- a/app/javascript/mastodon/reducers/missed_updates.ts
+++ b/app/javascript/mastodon/reducers/missed_updates.ts
@@ -12,7 +12,7 @@ const initialState = Record({
unread: 0,
})();
-export default function missed_updates(
+export function missedUpdatesReducer(
state = initialState,
action: Action,
) {
diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js
index 0530a52b4c..77e64284b1 100644
--- a/app/javascript/mastodon/reducers/notifications.js
+++ b/app/javascript/mastodon/reducers/notifications.js
@@ -29,7 +29,7 @@ import {
import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines';
import { fromJS, Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import compareId from '../compare_id';
+import { compareId } from '../compare_id';
const initialState = ImmutableMap({
pendingItems: ImmutableList(),
diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js
index f48d58bdc5..c8fdf1bc86 100644
--- a/app/javascript/mastodon/reducers/settings.js
+++ b/app/javascript/mastodon/reducers/settings.js
@@ -6,7 +6,7 @@ import { EMOJI_USE } from '../actions/emojis';
import { LANGUAGE_USE } from '../actions/languages';
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
import { Map as ImmutableMap, fromJS } from 'immutable';
-import uuid from '../uuid';
+import { uuid } from '../uuid';
const initialState = ImmutableMap({
saved: true,
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index 973e3cf184..41892ae462 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -17,7 +17,7 @@ import {
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
-import compareId from '../compare_id';
+import { compareId } from '../compare_id';
const initialState = ImmutableMap();
diff --git a/app/javascript/mastodon/service_worker/web_push_locales.js b/app/javascript/mastodon/service_worker/web_push_locales.js
index 7d713cd378..3912f75c7d 100644
--- a/app/javascript/mastodon/service_worker/web_push_locales.js
+++ b/app/javascript/mastodon/service_worker/web_push_locales.js
@@ -1,3 +1,6 @@
+/* eslint-disable import/no-commonjs --
+ We need to use CommonJS here as its imported into a preval file (`emoji_compressed.js`) */
+
/* @preval */
const fs = require('fs');
diff --git a/app/javascript/mastodon/uuid.ts b/app/javascript/mastodon/uuid.ts
index 01b57ee996..cabbc0f4ed 100644
--- a/app/javascript/mastodon/uuid.ts
+++ b/app/javascript/mastodon/uuid.ts
@@ -1,4 +1,4 @@
-export default function uuid(a?: string): string {
+export function uuid(a?: string): string {
return a
? (
(a as any as number) ^
diff --git a/app/javascript/packs/admin.jsx b/app/javascript/packs/admin.jsx
index 5990150001..52311af50e 100644
--- a/app/javascript/packs/admin.jsx
+++ b/app/javascript/packs/admin.jsx
@@ -1,10 +1,9 @@
import './public-path';
import ready from '../mastodon/ready';
+import React from 'react';
+import ReactDOM from 'react-dom';
ready(() => {
- const React = require('react');
- const ReactDOM = require('react-dom');
-
[].forEach.call(document.querySelectorAll('[data-admin-component]'), element => {
const componentName = element.getAttribute('data-admin-component');
const { locale, ...componentProps } = JSON.parse(element.getAttribute('data-props'));
diff --git a/app/javascript/packs/public.jsx b/app/javascript/packs/public.jsx
index 606ddc3bf7..3962a1d803 100644
--- a/app/javascript/packs/public.jsx
+++ b/app/javascript/packs/public.jsx
@@ -1,12 +1,23 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
-import ready from '../mastodon/ready';
import { start } from '../mastodon/common';
+
+import ready from '../mastodon/ready';
import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions';
import 'cocoon-js-vanilla';
import axios from 'axios';
import { throttle } from 'lodash';
import { defineMessages } from 'react-intl';
+import * as IntlMessageFormat from 'intl-messageformat';
+import { timeAgoString } from '../mastodon/components/relative_timestamp';
+import { delegate } from '@rails/ujs';
+import * as emojify from '../mastodon/features/emoji/emoji';
+import { getLocale } from '../mastodon/locales';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { createBrowserHistory } from 'history';
+
+start();
const messages = defineMessages({
usernameTaken: { id: 'username.taken', defaultMessage: 'That username is taken. Try another' },
@@ -14,18 +25,8 @@ const messages = defineMessages({
passwordDoesNotMatch: { id: 'password_confirmation.mismatching', defaultMessage: 'Password confirmation does not match' },
});
-start();
-
-function main() {
- const IntlMessageFormat = require('intl-messageformat').default;
- const { timeAgoString } = require('../mastodon/components/relative_timestamp');
- const { delegate } = require('@rails/ujs');
- const emojify = require('../mastodon/features/emoji/emoji').default;
- const { getLocale } = require('../mastodon/locales');
+function loaded() {
const { localeData } = getLocale();
- const React = require('react');
- const ReactDOM = require('react-dom');
- const { createBrowserHistory } = require('history');
const scrollToDetailedStatus = () => {
const history = createBrowserHistory();
@@ -238,6 +239,11 @@ function main() {
});
}
+
+function main() {
+ ready(loaded);
+}
+
loadPolyfills()
.then(main)
.then(loadKeyboardExtensions)
diff --git a/app/javascript/packs/share.jsx b/app/javascript/packs/share.jsx
index 1225d7b529..97c3c7b0e5 100644
--- a/app/javascript/packs/share.jsx
+++ b/app/javascript/packs/share.jsx
@@ -1,23 +1,26 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';
+import ready from '../mastodon/ready';
+import ComposeContainer from '../mastodon/containers/compose_container';
+import React from 'react';
+import ReactDOM from 'react-dom';
start();
function loaded() {
- const ComposeContainer = require('../mastodon/containers/compose_container').default;
- const React = require('react');
- const ReactDOM = require('react-dom');
const mountNode = document.getElementById('mastodon-compose');
- if (mountNode !== null) {
- const props = JSON.parse(mountNode.getAttribute('data-props'));
+ if (mountNode) {
+ const attr = mountNode.getAttribute('data-props');
+ if(!attr) return;
+
+ const props = JSON.parse(attr);
ReactDOM.render(, mountNode);
}
}
function main() {
- const ready = require('../mastodon/ready').default;
ready(loaded);
}
diff --git a/app/javascript/types/image.d.ts b/app/javascript/types/image.d.ts
index 8bd6ab0286..fae2ed7014 100644
--- a/app/javascript/types/image.d.ts
+++ b/app/javascript/types/image.d.ts
@@ -1,3 +1,4 @@
+/* eslint-disable import/no-default-export */
declare module '*.avif' {
const path: string;
export default path;
diff --git a/config/webpack/shared.js b/config/webpack/shared.js
index 9bdb60bad5..e85a2546fe 100644
--- a/config/webpack/shared.js
+++ b/config/webpack/shared.js
@@ -89,6 +89,7 @@ module.exports = {
module: {
rules: Object.keys(rules).map(key => rules[key]),
+ strictExportPresence: true,
},
plugins: [
diff --git a/package.json b/package.json
index f5db9e94f2..d5bc050e6d 100644
--- a/package.json
+++ b/package.json
@@ -79,6 +79,7 @@
"jsdom": "^21.1.2",
"lodash": "^4.17.21",
"mark-loader": "^0.1.6",
+ "marky": "^1.2.5",
"mini-css-extract-plugin": "^1.6.2",
"mkdirp": "^2.1.6",
"npmlog": "^7.0.1",
@@ -191,11 +192,11 @@
"eslint-plugin-jsx-a11y": "~6.7.1",
"eslint-plugin-promise": "~6.1.1",
"eslint-plugin-react": "~7.32.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"lint-staged": "^13.2.2",
- "marky": "^1.2.5",
"prettier": "^2.8.8",
"raf": "^3.4.1",
"react-intl-translations-manager": "^5.0.3",
diff --git a/yarn.lock b/yarn.lock
index 239c13a3e7..7c99883d7d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5130,6 +5130,11 @@ eslint-plugin-promise@~6.1.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816"
integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==
+eslint-plugin-react-hooks@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
+ integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
+
eslint-plugin-react@~7.32.2:
version "7.32.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10"