Browse Source

Cleanup - eslint config fixes (#8543)

Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
LB (Ben Johnston) 2 years ago
parent
commit
7c9b6fd415

+ 40 - 17
.eslintrc.js

@@ -4,11 +4,11 @@ const legacyCode = {
   'class-methods-use-this': 'off',
   'constructor-super': 'off',
   'default-param-last': 'off',
-  'import/extensions': 'off',
   'import/first': 'off',
   'import/newline-after-import': 'off',
+  'import/no-cycle': 'off',
   'import/no-extraneous-dependencies': 'off',
-  'import/no-unresolved': 'off',
+  'import/no-unresolved': ['error', { ignore: ['jquery'] }],
   'import/no-useless-path-segments': 'off',
   'import/order': 'off',
   'import/prefer-default-export': 'off',
@@ -61,19 +61,11 @@ module.exports = {
     browser: true,
   },
   rules: {
-    'no-underscore-dangle': [
-      'error',
-      { allow: ['__REDUX_DEVTOOLS_EXTENSION__'] },
-    ],
-    // note you must disable the base rule as it can report incorrect errors
-    'no-use-before-define': 'off',
-    '@typescript-eslint/no-use-before-define': ['error'],
-
-    '@typescript-eslint/explicit-module-boundary-types': 'off',
-    '@typescript-eslint/explicit-member-accessibility': 'off',
     '@typescript-eslint/explicit-function-return-type': 'off',
+    '@typescript-eslint/explicit-member-accessibility': 'off',
+    '@typescript-eslint/explicit-module-boundary-types': 'off',
     '@typescript-eslint/no-explicit-any': 'off',
-    'react/jsx-filename-extension': ['error', { extensions: ['.js', '.tsx'] }],
+    '@typescript-eslint/no-use-before-define': ['error'],
     'import/extensions': [
       'error',
       'always',
@@ -87,24 +79,55 @@ module.exports = {
         },
       },
     ],
-    ...legacyCode,
+    // note you must disable the base rule as it can report incorrect errors
+    'no-use-before-define': 'off',
+    'react/jsx-filename-extension': ['error', { extensions: ['.js', '.tsx'] }],
+    'no-underscore-dangle': [
+      'error',
+      { allow: ['__REDUX_DEVTOOLS_EXTENSION__'] },
+    ],
+  },
+  settings: {
+    'import/resolver': {
+      node: {
+        extensions: ['.js', '.ts', '.tsx'],
+      },
+    },
   },
   overrides: [
+    // Legacy Code - remove from `files` when adopting desired rules in new code progressively
+    {
+      files: [
+        'client/src/components/**',
+        'client/src/entrypoints/**',
+        'client/src/utils/**',
+        '**/documents/static_src/wagtaildocs/js/add-multiple.js',
+        '**/images/static_src/wagtailimages/js/add-multiple.js',
+        '**/images/static_src/wagtailimages/js/focal-point-chooser.js',
+        '**/snippets/static_src/wagtailsnippets/js/snippet-multiple-select.js',
+      ],
+      rules: legacyCode,
+    },
     {
       // Rules we don’t want to enforce for test and tooling code.
       files: [
+        'client/extract-translatable-strings.js',
+        'client/tests/**',
+        'webpack.config.js',
+        'tailwind.config.js',
+        'storybook/**/*',
         '*.test.ts',
         '*.test.tsx',
         '*.test.js',
-        'webpack.config.js',
-        'tailwind.config.js',
         '*.stories.js',
         '*.stories.tsx',
-        'storybook/**/*',
       ],
       rules: {
         '@typescript-eslint/no-empty-function': 'off',
         '@typescript-eslint/no-var-requires': 'off',
+        'import/no-extraneous-dependencies': 'off',
+        'react/function-component-definition': 'off',
+        'react/jsx-props-no-spreading': 'off',
       },
     },
     {

+ 0 - 1
client/extract-translatable-strings.js

@@ -1,4 +1,3 @@
-// eslint-disable-next-line @typescript-eslint/no-var-requires
 const { GettextExtractor, JsExtractors } = require('gettext-extractor');
 
 const extractor = new GettextExtractor();

+ 15 - 10
client/src/api/admin.test.js

@@ -1,17 +1,22 @@
 import { ADMIN_API } from '../config/wagtailConfig';
 import { getPageChildren, getPage } from './admin';
-import * as client from './client';
-
-const stubResult = {
-  __types: {
-    test: {
-      verbose_name: 'Test',
+import client from './client';
+
+jest.mock('./client', () => {
+  const stubResult = {
+    __types: {
+      test: {
+        verbose_name: 'Test',
+      },
     },
-  },
-  items: [{ meta: { type: 'test' } }, { meta: { type: 'foo' } }],
-};
+    items: [{ meta: { type: 'test' } }, { meta: { type: 'foo' } }],
+  };
 
-client.get = jest.fn(() => Promise.resolve(stubResult));
+  return {
+    __esModule: true,
+    default: { get: jest.fn(() => Promise.resolve(stubResult)) },
+  };
+});
 
 describe('admin API', () => {
   describe('getPageChildren', () => {

+ 6 - 4
client/src/api/admin.ts

@@ -1,4 +1,4 @@
-import { get } from '../api/client';
+import client from './client';
 
 import { ADMIN_API } from '../config/wagtailConfig';
 
@@ -32,7 +32,7 @@ interface WagtailPageListAPI {
 export const getPage: (id: number) => Promise<WagtailPageAPI> = (id) => {
   const url = `${ADMIN_API.PAGES}${id}/`;
 
-  return get(url);
+  return client.get(url);
 };
 
 interface GetPageChildrenOptions {
@@ -66,7 +66,7 @@ export const getPageChildren: GetPageChildren = (id, options = {}) => {
 
   url += ADMIN_API.EXTRA_CHILDREN_PARAMETERS;
 
-  return get(url);
+  return client.get(url);
 };
 
 interface GetPageTranslationsOptions {
@@ -97,7 +97,7 @@ export const getPageTranslations: GetPageTranslations = (id, options = {}) => {
     url += `&offset=${options.offset}`;
   }
 
-  return get(url);
+  return client.get(url);
 };
 
 interface GetAllPageTranslationsOptions {
@@ -113,6 +113,7 @@ export const getAllPageTranslations = async (
   let iterLimit = 100;
 
   for (;;) {
+    // eslint-disable-next-line no-await-in-loop
     const page = await getPageTranslations(id, {
       offset: items.length,
       ...options,
@@ -120,6 +121,7 @@ export const getAllPageTranslations = async (
 
     page.items.forEach((item) => items.push(item));
 
+    // eslint-disable-next-line no-plusplus
     if (items.length >= page.meta.total_count || iterLimit-- <= 0) {
       return items;
     }

+ 2 - 3
client/src/api/client.js

@@ -1,5 +1,4 @@
-const fetch = global.fetch;
-const Headers = global.Headers;
+const { fetch, Headers } = global;
 
 const REQUEST_TIMEOUT = 15000;
 
@@ -57,4 +56,4 @@ const request = (method, url) => {
     .then(parseJSON);
 };
 
-export const get = (url) => request('GET', url);
+export default { get: (url) => request('GET', url) };

+ 1 - 1
client/src/api/client.test.js

@@ -1,4 +1,4 @@
-import * as client from './client';
+import client from './client';
 
 describe('client API', () => {
   it('should succeed fetching', (done) => {

+ 2 - 2
client/src/config/wagtailConfig.js

@@ -1,5 +1,5 @@
-export const ADMIN_API = global.wagtailConfig.ADMIN_API;
-export const ADMIN_URLS = global.wagtailConfig.ADMIN_URLS;
+export const { ADMIN_API } = global.wagtailConfig;
+export const { ADMIN_URLS } = global.wagtailConfig;
 
 // Maximum number of pages to load inside the explorer menu.
 export const MAX_EXPLORER_PAGES = 200;

+ 1 - 1
client/src/includes/initSkipLink.js

@@ -22,4 +22,4 @@ const initSkipLink = () => {
   }
 };
 
-export { initSkipLink };
+export default initSkipLink;

+ 4 - 4
client/src/includes/tabs.js

@@ -55,7 +55,7 @@ class Tabs {
     // Set active tab from url or make first tab active
     if (this.tabButtons) {
       // Set each button's aria-controls attribute and select tab if aria-selected has already been set on the element
-      this.setAriaControlsByHref(this.tabButtons);
+      Tabs.setAriaControlsByHref(this.tabButtons);
       // Check for active items set by the template
       const tabActive = [...this.tabButtons].find(
         (button) => button.getAttribute('aria-selected') === 'true',
@@ -78,7 +78,7 @@ class Tabs {
 
     // Set each external trigger button's aria-controls attribute
     if (this.tabTriggerLinks) {
-      this.setAriaControlsByHref(this.tabTriggerLinks);
+      Tabs.setAriaControlsByHref(this.tabTriggerLinks);
     }
   }
 
@@ -310,7 +310,7 @@ class Tabs {
     const tabs = this.tabButtons;
 
     if (direction[pressed]) {
-      const target = event.target;
+      const { target } = event;
       if (target.index !== undefined) {
         if (tabs[target.index + direction[pressed]]) {
           const tab = tabs[target.index + direction[pressed]];
@@ -346,7 +346,7 @@ class Tabs {
    *  Populate a list of links aria-controls attributes with their href value
    * @param links{HTMLAnchorElement[]}
    */
-  setAriaControlsByHref(links) {
+  static setAriaControlsByHref(links) {
     links.forEach((link) => {
       link.setAttribute(
         'aria-controls',

+ 1 - 1
client/src/index.ts

@@ -10,4 +10,4 @@ export { default as Portal } from './components/Portal/Portal';
 export { default as PublicationStatus } from './components/PublicationStatus/PublicationStatus';
 export { default as Transition } from './components/Transition/Transition';
 export { initUpgradeNotification } from './components/UpgradeNotification';
-export { initSkipLink } from './includes/initSkipLink';
+export { default as initSkipLink } from './includes/initSkipLink';

+ 1 - 1
client/src/plugins/scrollbarThin.js

@@ -1,4 +1,4 @@
-// eslint-disable-next-line @typescript-eslint/no-var-requires
+// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-extraneous-dependencies
 const plugin = require('tailwindcss/plugin');
 
 module.exports = plugin(({ addComponents, theme }) => {

+ 1 - 1
client/storybook/middleware.js

@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
+/* eslint-disable @typescript-eslint/no-var-requires, import/no-extraneous-dependencies */
 const middleware = require('storybook-django/src/middleware');
 
 const origin = process.env.TEST_ORIGIN ?? 'http://localhost:8000';

+ 1 - 0
client/storybook/preview.js

@@ -3,6 +3,7 @@ import '../tests/stubs';
 import '../../wagtail/admin/static_src/wagtailadmin/scss/core.scss';
 import './preview.scss';
 
+// eslint-disable-next-line import/prefer-default-export
 export const parameters = {
   controls: {
     hideNoControlsWarning: true,

+ 1 - 0
client/tests/mock-fetch.js

@@ -25,6 +25,7 @@ fetch.mockResponseFailure = () => {
 
 fetch.mockResponseCrash = () => {
   fetch.mockImplementationOnce(() =>
+    // eslint-disable-next-line prefer-promise-reject-errors
     Promise.reject({
       status: 500,
       statusText: 'Internal Error',

+ 1 - 0
client/webpack.config.js

@@ -72,6 +72,7 @@ module.exports = function exports(env, argv) {
   };
 
   const entry = {};
+  // eslint-disable-next-line no-restricted-syntax
   for (const [appName, moduleNames] of Object.entries(entrypoints)) {
     moduleNames.forEach((moduleName) => {
       entry[moduleName] = {

+ 1 - 0
wagtail/admin/templates/wagtailadmin/shared/icons.stories.tsx

@@ -35,6 +35,7 @@ const IconsTable = ({ color }: { color: string }) => {
       {window.WAGTAIL_ICONS.map((icon) => (
         <tr key={icon}>
           <td
+            // eslint-disable-next-line react/no-danger
             dangerouslySetInnerHTML={{
               __html: template
                 .replace(/__icon__/g, icon)