module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking', 'airbnb', 'airbnb-typescript', 'plugin:react/jsx-runtime', 'prettier', ], env: { amd: true, browser: true, mocha: true, }, parser: '@typescript-eslint/parser', parserOptions: { tsconfigRootDir: '.', project: ['./tsconfig.json'], ecmaVersion: 6, ecmaFeatures: { jsx: true, }, }, plugins: ['react-hooks', 'no-only-tests', '@typescript-eslint'], settings: { 'import/resolver': 'webpack', 'import/core-modules': [ '@woocommerce/blocks-checkout', '@woocommerce/settings', '@wordpress/a11y', '@wordpress/api-fetch', '@wordpress/block-editor', '@wordpress/compose', '@wordpress/data', '@wordpress/escape-html', '@wordpress/hooks', '@wordpress/keycodes', '@wordpress/url', 'react', ], }, rules: { 'react/no-unstable-nested-components': ['error', { allowAsProps: true }], // PropTypes 'react/prop-types': 0, 'react/jsx-props-no-spreading': 0, 'react/require-default-props': 0, // Hooks 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', // Exceptions '@typescript-eslint/no-explicit-any': 'error', // make it an error instead of warning - we treat them the same, this is more visible 'no-void': 0, // can conflict with @typescript-eslint/no-floating-promises 'react/jsx-no-useless-fragment': [ 'error', { allowExpressions: true, }, ], 'react/jsx-filename-extension': 0, 'class-methods-use-this': 0, '@typescript-eslint/no-unsafe-return': 0, // we need to disable it for wordpress select :( '@typescript-eslint/no-unsafe-member-access': 0, // this needs to be off until we have typed assignments :( '@typescript-eslint/no-unsafe-call': 0, // this needs to be off until we have typed assignments :( '@typescript-eslint/no-unsafe-assignment': 0, // this needs to be off until we have typed assignments :( 'import/extensions': 0, // we wouldn't be able to import jQuery without this line 'import/no-named-as-default': 0, // we use named default exports at the moment 'import/prefer-default-export': 0, // we want to stop using default exports and start using named exports 'react/destructuring-assignment': 0, // that would be too many changes to fix this one 'prefer-destructuring': 0, // that would be too many changes to fix this one 'jsx-a11y/label-has-for': [ 2, { required: { some: ['nesting', 'id'] }, // some of our labels are hidden and we cannot nest those }, ], 'jsx-a11y/anchor-is-valid': 0, // cannot fix this one, it would break wprdpress themes 'jsx-a11y/label-has-associated-control': [ 2, { either: 'either', // control has to be either nested or associated via htmlFor }, ], 'import/no-default-export': 1, // no default exports '@typescript-eslint/no-misused-promises': [ 'error', { checksVoidReturn: { attributes: false, // it is OK to pass an async function to JSX attributes }, }, ], }, overrides: [ { files: ['*.spec.ts'], rules: { 'no-unused-expressions': 'off', }, }, { files: ['**/_stories/*.tsx'], rules: { 'import/no-extraneous-dependencies': [ 'error', { devDependencies: true }, ], 'import/no-default-export': 0, }, }, { // this violation has been added by a formed employee and we don't know how that works any more, so ignore files: [ 'assets/js/src/common/premium_key/key_activation_button.tsx', 'assets/js/src/settings/pages/advanced/reinstall.tsx', 'assets/js/src/settings/pages/advanced/recalculate_subscriber_score.tsx', 'assets/js/src/settings/pages/send_with/other/activate_or_cancel.tsx', 'assets/js/src/settings/pages/send_with/send_with_choice.tsx', ], rules: { '@typescript-eslint/await-thenable': 0, }, }, { // too many violations, skipping for now files: [ 'assets/js/src/announcements/feature_announcement.tsx', 'assets/js/src/announcements/with_feature_announcement.tsx', 'assets/js/src/common/controls/call_api.ts', 'assets/js/src/common/form/react_select/react_select.tsx', 'assets/js/src/common/functions/is_email.ts', 'assets/js/src/common/functions/t.ts', 'assets/js/src/common/listings/newsletter_stats/stats.tsx', 'assets/js/src/common/listings/newsletter_status.tsx', 'assets/js/src/common/set_from_address_modal.tsx', 'assets/js/src/common/tabs/routed_tabs.tsx', 'assets/js/src/common/thumbnail.ts', 'assets/js/src/form_editor/blocks/submit/edit.tsx', 'assets/js/src/form_editor/components/close_button_settings.tsx', 'assets/js/src/form_editor/components/font_family_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/below_pages.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/fixed_bar.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/other.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/popup.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/animation_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/below_posts_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/fixed_bar_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/other_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/popup_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/slide_in_settings.tsx', 'assets/js/src/form_editor/components/form_settings/form_placement_options/slide_in.tsx', 'assets/js/src/form_editor/components/form_settings/form_settings.tsx', 'assets/js/src/form_editor/components/fullscreen.tsx', 'assets/js/src/form_editor/components/history_redo.tsx', 'assets/js/src/form_editor/components/history_undo.tsx', 'assets/js/src/form_editor/components/preview/preview.tsx', 'assets/js/src/form_editor/components/sidebar/default_sidebar.tsx', 'assets/js/src/form_editor/components/sidebar/placement_settings_sidebar.tsx', 'assets/js/src/form_editor/components/sidebar/sidebar.tsx', 'assets/js/src/form_editor/components/tutorial.tsx', 'assets/js/src/form_editor/form_preview.ts', 'assets/js/src/form_editor/hooks.tsx', 'assets/js/src/form_editor/rich_text/font_selection_format.tsx', 'assets/js/src/form_editor/store/actions.ts', 'assets/js/src/form_editor/store/reducers/change_active_sidebar.ts', 'assets/js/src/form_editor/store/reducers/history_record.ts', 'assets/js/src/form_editor/store/reducers/toggle_form.ts', 'assets/js/src/form_editor/store/reducers/toggle_fullscreen.ts', 'assets/js/src/form_editor/store/reducers/tutorial_dismiss.ts', 'assets/js/src/form_editor/templates/selection.tsx', 'assets/js/src/form_editor/templates/store/actions.ts', 'assets/js/src/form_editor/utils/link_suggestions.tsx', 'assets/js/src/logs/list.tsx', 'assets/js/src/newsletters/automatic_emails/events/event_options.tsx', 'assets/js/src/newsletters/campaign_stats/newsletter_general_stats.tsx', 'assets/js/src/newsletters/campaign_stats/page.tsx', 'assets/js/src/newsletters/listings/heading_steps.tsx', 'assets/js/src/newsletters/send/congratulate/success_pitch_mss.tsx', 'assets/js/src/newsletters/types.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/email_opens_absolute_count.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/subscriber_subscribed_date.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/subscriber_wordpress_role.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/woocommerce.tsx', 'assets/js/src/segments/dynamic/dynamic_segments_filters/woocommerce_subscription.tsx', 'assets/js/src/segments/dynamic/form.tsx', 'assets/js/src/segments/dynamic/subscribers_calculator.ts', 'assets/js/src/segments/dynamic/subscribers_counter.tsx', 'assets/js/src/segments/dynamic/validator.ts', 'assets/js/src/settings/components/segments_select.tsx', 'assets/js/src/settings/pages/basics/stats_notifications.tsx', 'assets/js/src/settings/pages/basics/subscribe_on.tsx', 'assets/js/src/settings/pages/send_with/other/sending_frequency.tsx', 'assets/js/src/settings/pages/send_with/send_with_choice.tsx', 'assets/js/src/settings/pages/woo_commerce/checkout_optin.tsx', 'assets/js/src/settings/pages/woo_commerce/email_customizer.tsx', 'assets/js/src/settings/pages/woo_commerce/enable_cookies.tsx', 'assets/js/src/settings/pages/woo_commerce/subscribe_old_customers.tsx', 'assets/js/src/settings/store/actions/settings.ts', 'assets/js/src/settings/store/controls.ts', 'assets/js/src/settings/store/hooks/useActions.ts', 'assets/js/src/settings/store/hooks/useSelector.ts', 'assets/js/src/settings/store/hooks/useSetting.ts', 'assets/js/src/settings/store/index.ts', 'assets/js/src/settings/store/normalize_settings.ts', 'assets/js/src/settings/store/selectors.ts', 'assets/js/src/settings/store/types.ts', 'assets/js/src/subscribers/importExport/export.ts', ], rules: { '@typescript-eslint/restrict-template-expressions': 0, '@typescript-eslint/no-unsafe-return': 0, }, }, { // there are so many violations of this rule we need to keep slowly removing it files: [ 'assets/js/src/_storybook/action.ts', 'assets/js/src/announcements/feature_announcement.tsx', 'assets/js/src/announcements/with_feature_announcement.tsx', 'assets/js/src/common/background/_stories/background.tsx', 'assets/js/src/common/background/background.tsx', 'assets/js/src/common/badge/_stories/badge.tsx', 'assets/js/src/common/badge/badge.tsx', 'assets/js/src/common/button/_stories/button.tsx', 'assets/js/src/common/button/_stories/button_icons.tsx', 'assets/js/src/common/button/button.tsx', 'assets/js/src/common/categories/_stories/categories.tsx', 'assets/js/src/common/categories/categories.tsx', 'assets/js/src/common/categories/categories_item.tsx', 'assets/js/src/common/controls/call_api.ts', 'assets/js/src/common/controls/track_event.ts', 'assets/js/src/common/datepicker/_stories/datepicker.tsx', 'assets/js/src/common/datepicker/datepicker.tsx', 'assets/js/src/common/form/checkbox/_stories/checkbox.tsx', 'assets/js/src/common/form/checkbox/checkbox.tsx', 'assets/js/src/common/form/checkbox/group.tsx', 'assets/js/src/common/form/input/_stories/input.tsx', 'assets/js/src/common/form/input/input.tsx', 'assets/js/src/common/form/radio/_stories/radio.tsx', 'assets/js/src/common/form/radio/group.tsx', 'assets/js/src/common/form/radio/radio.tsx', 'assets/js/src/common/form/react_select/_stories/react_select.tsx', 'assets/js/src/common/form/react_select/react_select.tsx', 'assets/js/src/common/form/select/_stories/select.tsx', 'assets/js/src/common/form/textarea/_stories/textarea.tsx', 'assets/js/src/common/form/textarea/textarea.tsx', 'assets/js/src/common/form/toggle/_stories/toggle.tsx', 'assets/js/src/common/form/toggle/toggle.tsx', 'assets/js/src/common/form/yesno/_stories/yesno.tsx', 'assets/js/src/common/form/yesno/yesno.tsx', 'assets/js/src/common/functions/change_handlers.ts', 'assets/js/src/common/hide_screen_options/hide_screen_options.tsx', 'assets/js/src/common/listings/_stories/newsletter_stats.tsx', 'assets/js/src/common/listings/_stories/newsletter_status.tsx', 'assets/js/src/common/listings/newsletter_stats.tsx', 'assets/js/src/common/listings/newsletter_stats/badge.tsx', 'assets/js/src/common/listings/newsletter_stats/stats.tsx', 'assets/js/src/common/listings/newsletter_status.tsx', 'assets/js/src/common/loader/_stories/loader.tsx', 'assets/js/src/common/loader/loader.tsx', 'assets/js/src/common/modal/_stories/modal.tsx', 'assets/js/src/common/modal/frame.tsx', 'assets/js/src/common/modal/header.tsx', 'assets/js/src/common/modal/modal.tsx', 'assets/js/src/common/modal/overlay.tsx', 'assets/js/src/common/premium_required/_stories/premium_required.tsx', 'assets/js/src/common/premium_required/premium_required.tsx', 'assets/js/src/common/preview/desktop_icon.tsx', 'assets/js/src/common/preview/mobile_icon.tsx', 'assets/js/src/common/remove_wrap_margin/remove_wrap_margin.tsx', 'assets/js/src/common/set_from_address_modal.tsx', 'assets/js/src/common/steps/_stories/steps.tsx', 'assets/js/src/common/steps/content_wrapper_fix.tsx', 'assets/js/src/common/steps/steps.tsx', 'assets/js/src/common/steps/steps_content.tsx', 'assets/js/src/common/subscribers_in_plan.tsx', 'assets/js/src/common/tabs/_stories/tabs.tsx', 'assets/js/src/common/tabs/_stories/tabs_icons.tsx', 'assets/js/src/common/tabs/routed_tabs.tsx', 'assets/js/src/common/tabs/tab.tsx', 'assets/js/src/common/tabs/tabs.tsx', 'assets/js/src/common/tag/_stories/tag.tsx', 'assets/js/src/common/tag/_stories/tags.tsx', 'assets/js/src/common/tag/tag.tsx', 'assets/js/src/common/tag/tags.tsx', 'assets/js/src/common/template_box/_stories/template_box.tsx', 'assets/js/src/common/template_box/template_box.tsx', 'assets/js/src/common/thumbnail.ts', 'assets/js/src/common/tooltip/_stories/tooltip.tsx', 'assets/js/src/common/tooltip/tooltip.tsx', 'assets/js/src/common/top_bar/_stories/top_bar_no_children.tsx', 'assets/js/src/common/top_bar/_stories/top_bar_with_children.tsx', 'assets/js/src/common/top_bar/beamer_icon.tsx', 'assets/js/src/common/top_bar/mailpoet_logo.tsx', 'assets/js/src/common/top_bar/mailpoet_logo_mobile.tsx', 'assets/js/src/common/top_bar/screen_options_fix.tsx', 'assets/js/src/common/top_bar/top_bar.tsx', 'assets/js/src/common/typography/heading/_stories/heading.tsx', 'assets/js/src/common/typography/heading/heading.tsx', 'assets/js/src/common/typography/list/_stories/list.tsx', 'assets/js/src/common/typography/list/list.tsx', 'assets/js/src/form_editor/store/actions.ts', 'assets/js/src/form_editor/store/mapping/from_blocks/styles_mapper.ts', 'assets/js/src/form_editor/store/mapping/to_blocks/styles_mapper.ts', 'assets/js/src/form_editor/store/reducers/change_active_sidebar.ts', 'assets/js/src/form_editor/store/reducers/history_record.ts', 'assets/js/src/form_editor/store/reducers/toggle_form.ts', 'assets/js/src/form_editor/store/reducers/toggle_fullscreen.ts', 'assets/js/src/form_editor/store/reducers/toggle_sidebar.ts', 'assets/js/src/form_editor/store/reducers/tutorial_dismiss.ts', 'assets/js/src/form_editor/template_selection.tsx', 'assets/js/src/form_editor/translations.ts', 'assets/js/src/form_editor/utils/link_suggestions.tsx', 'assets/js/src/newsletters/automatic_emails/events/event_options.tsx', 'assets/js/src/newsletters/campaign_stats/newsletter_general_stats.tsx', 'assets/js/src/newsletters/campaign_stats/newsletter_stats_info.tsx', 'assets/js/src/newsletters/campaign_stats/page.tsx', 'assets/js/src/notices/api_errors_notice.tsx', 'assets/js/src/notices/invalid_mss_key_notice.tsx', 'assets/js/src/notices/notice.tsx', 'assets/js/src/notices/transactional_emails_propose_opt_in_notice.tsx', 'assets/js/src/sending-paused-notices-fix-button.tsx', 'assets/js/src/settings/components/inputs.tsx', 'assets/js/src/settings/components/label.tsx', 'assets/js/src/settings/components/pages_select.tsx', 'assets/js/src/settings/components/save_button.tsx', 'assets/js/src/settings/components/segments_select.tsx', 'assets/js/src/settings/index.tsx', 'assets/js/src/settings/pages/advanced/advanced.tsx', 'assets/js/src/settings/pages/advanced/bounce_address.tsx', 'assets/js/src/settings/pages/advanced/captcha.tsx', 'assets/js/src/settings/pages/advanced/inactive_subscribers.tsx', 'assets/js/src/settings/pages/advanced/libs_3rd_party.tsx', 'assets/js/src/settings/pages/advanced/logging.tsx', 'assets/js/src/settings/pages/advanced/reinstall.tsx', 'assets/js/src/settings/pages/advanced/roles.tsx', 'assets/js/src/settings/pages/advanced/share_data.tsx', 'assets/js/src/settings/pages/advanced/task_scheduler.tsx', 'assets/js/src/settings/pages/advanced/tracking.tsx', 'assets/js/src/settings/pages/advanced/transactional.tsx', 'assets/js/src/settings/pages/basics/basics.tsx', 'assets/js/src/settings/pages/basics/default_sender.tsx', 'assets/js/src/settings/pages/basics/gdpr_compliant.tsx', 'assets/js/src/settings/pages/basics/manage_subscription.tsx', 'assets/js/src/settings/pages/basics/new_subscriber_notifications.tsx', 'assets/js/src/settings/pages/basics/shortcode.tsx', 'assets/js/src/settings/pages/basics/stats_notifications.tsx', 'assets/js/src/settings/pages/basics/subscribe_on.tsx', 'assets/js/src/settings/pages/basics/unsubscribe_page.tsx', 'assets/js/src/settings/pages/key_activation/key_activation.tsx', 'assets/js/src/settings/pages/key_activation/messages/key_messages.tsx', 'assets/js/src/settings/pages/key_activation/messages/mss_messages.tsx', 'assets/js/src/settings/pages/key_activation/messages/premium_messages.tsx', 'assets/js/src/settings/pages/key_activation/messages/service_unavailable_messages.tsx', 'assets/js/src/settings/pages/send_with/other/activate_or_cancel.tsx', 'assets/js/src/settings/pages/send_with/other/amazon_ses_fields.tsx', 'assets/js/src/settings/pages/send_with/other/other_sending_methods.tsx', 'assets/js/src/settings/pages/send_with/other/php_mail_fields.tsx', 'assets/js/src/settings/pages/send_with/other/sendgrid_fields.tsx', 'assets/js/src/settings/pages/send_with/other/sending_frequency.tsx', 'assets/js/src/settings/pages/send_with/other/sending_method.tsx', 'assets/js/src/settings/pages/send_with/other/smtp_fields.tsx', 'assets/js/src/settings/pages/send_with/other/spf.tsx', 'assets/js/src/settings/pages/send_with/other/test_sending.tsx', 'assets/js/src/settings/pages/send_with/send_with.tsx', 'assets/js/src/settings/pages/send_with/send_with_choice.tsx', 'assets/js/src/settings/pages/signup_confirmation/confirmation_page.tsx', 'assets/js/src/settings/pages/signup_confirmation/email_content.tsx', 'assets/js/src/settings/pages/signup_confirmation/email_subject.tsx', 'assets/js/src/settings/pages/signup_confirmation/enable_signup_confirmation.tsx', 'assets/js/src/settings/pages/signup_confirmation/signup_confirmation.tsx', 'assets/js/src/settings/pages/woo_commerce/checkout_optin.tsx', 'assets/js/src/settings/pages/woo_commerce/email_customizer.tsx', 'assets/js/src/settings/pages/woo_commerce/enable_cookies.tsx', 'assets/js/src/settings/pages/woo_commerce/subscribe_old_customers.tsx', 'assets/js/src/settings/pages/woo_commerce/woo_commerce.tsx', 'assets/js/src/settings/settings.tsx', 'assets/js/src/settings/store/actions/mss_and_premium.ts', 'assets/js/src/settings/store/actions/open_woocommerce_customizer.ts', 'assets/js/src/settings/store/actions/reinstall.ts', 'assets/js/src/settings/store/actions/send_test_email.ts', 'assets/js/src/settings/store/actions/settings.ts', 'assets/js/src/settings/store/controls.ts', 'assets/js/src/settings/store/create_reducer.ts', 'assets/js/src/settings/store/index.ts', 'assets/js/src/settings/store/make_default_state.ts', 'assets/js/src/settings/store/selectors.ts', ], rules: { '@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/explicit-module-boundary-types': 0, }, }, ], };