Browse Source

Use TypeScript configuration for all JS linting (#6862)

- Switches our JS linting to be done with the TypeScript parser, and TypeScript rules. They handle JavaScript as well, and using the same parser everywhere matches how our build tools work. Additionally I had to disable a few rules for test files and webpack.config.js.
- Adds --report-unused-disable-directives to our linting script, and removes the unused directives.
Thibaud Colas 4 years ago
parent
commit
fd563b6adf

+ 23 - 25
.eslintrc

@@ -1,5 +1,12 @@
 {
-  "extends": "wagtail",
+  "parser": "@typescript-eslint/parser",
+  "plugins": [
+    "@typescript-eslint"
+  ],
+  "extends": [
+    "wagtail",
+    "plugin:@typescript-eslint/recommended"
+  ],
 
   "env": {
     "jest": true
@@ -12,35 +19,26 @@
       }
     }
   },
-
   "rules": {
-    "no-underscore-dangle": ["error", { "allow": ["__REDUX_DEVTOOLS_EXTENSION__"] }]
+    "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/no-explicit-any": "off"
   },
 
   "overrides": [
     {
-        "files": ["*.ts", "*.tsx"],
-
-        "parser": "@typescript-eslint/parser",
-        "plugins": [
-          "@typescript-eslint"
-        ],
-        "extends": [
-          "wagtail",
-          "plugin:@typescript-eslint/recommended"
-        ],
-        "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/no-explicit-any": "off"
-        }
+      // Rules we don’t want to enforce for test and tooling code.
+      "files": ["*.test.ts", "*.test.tsx", "*.test.js", "webpack.config.js"],
+      "rules": {
+        "@typescript-eslint/no-empty-function": "off",
+        "@typescript-eslint/no-var-requires": "off"
+      }
     }
   ]
 }

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

@@ -25,7 +25,6 @@ describe('admin API', () => {
 
     it('#fields', () => {
       getPageChildren(3, { fields: ['title', 'latest_revision_created_at'] });
-      // eslint-disable-next-line max-len
       expect(client.get).toBeCalledWith(
         `${ADMIN_API.PAGES}?child_of=3&for_explorer=1&fields=parent,title%2Clatest_revision_created_at`
       );

+ 2 - 2
client/src/entrypoints/admin/core.js

@@ -247,7 +247,7 @@ $(() => {
 
     $input.on('keyup cut paste change', () => {
       clearTimeout($input.data('timer'));
-      // eslint-disable-next-line no-use-before-define
+      // eslint-disable-next-line @typescript-eslint/no-use-before-define
       $input.data('timer', setTimeout(search, 200));
     });
 
@@ -259,7 +259,7 @@ $(() => {
       const workingClasses = 'icon-spinner';
 
       const newQuery = $input.val();
-      // eslint-disable-next-line no-use-before-define
+      // eslint-disable-next-line @typescript-eslint/no-use-before-define
       const currentQuery = getURLParam('q');
       // only do the query if it has changed for trimmed queries
       // eg. " " === "" and "firstword " ==== "firstword"

+ 1 - 1
client/src/entrypoints/admin/hallo-bootstrap.js

@@ -61,7 +61,7 @@ function makeHalloRichTextEditable(id, plugins) {
       });
     });
 
-  // eslint-disable-next-line no-use-before-define
+  // eslint-disable-next-line @typescript-eslint/no-use-before-define
   setupLinkTooltips(editor);
 }
 window.makeHalloRichTextEditable = makeHalloRichTextEditable;

+ 1 - 0
client/src/entrypoints/admin/hallo-plugins/hallo-wagtaillink.js

@@ -6,6 +6,7 @@ $.widget('IKS.hallowagtaillink', {
     editable: null
   },
   populateToolbar(toolbar) {
+    // eslint-disable-next-line @typescript-eslint/no-this-alias
     const widget = this;
     // eslint-disable-next-line func-names
     const getEnclosingLink = function () {

+ 0 - 14
client/src/entrypoints/admin/modal-workflow.js

@@ -20,16 +20,13 @@ function ModalWorkflow(opts) {
 
   const self = {};
   const responseCallbacks = opts.responses || {};
-  // eslint-disable-next-line func-names
   const errorCallback = opts.onError || function () {};
 
   /* remove any previous modals before continuing (closing doesn't remove them from the dom) */
   $('body > .modal').remove();
 
   // set default contents of container
-  // eslint-disable-next-line max-len
   const iconClose = '<svg class="icon icon-cross" aria-hidden="true" focusable="false"><use href="#icon-cross"></use></svg>';
-  // eslint-disable-next-line max-len
   const container = $('<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">\n  <div class="modal-dialog">\n    <div class="modal-content">\n      <button type="button" class="button close button--icon text-replace" data-dismiss="modal">' + iconClose + wagtailConfig.STRINGS.CLOSE + '</button>\n      <div class="modal-body"></div>\n    </div><!-- /.modal-content -->\n  </div><!-- /.modal-dialog -->\n</div>');
 
   // add container to body and hide it, so content can be added to it before display
@@ -38,29 +35,23 @@ function ModalWorkflow(opts) {
 
   self.body = container.find('.modal-body');
 
-  // eslint-disable-next-line func-names
   self.loadUrl = function (url, urlParams) {
     $.get(url, urlParams, self.loadResponseText, 'text').fail(errorCallback);
   };
 
-  // eslint-disable-next-line func-names
   self.postForm = function (url, formData) {
     $.post(url, formData, self.loadResponseText, 'text').fail(errorCallback);
   };
 
-  // eslint-disable-next-line func-names
   self.ajaxifyForm = function (formSelector) {
-    // eslint-disable-next-line func-names
     $(formSelector).each(function () {
       const action = this.action;
       if (this.method.toLowerCase() === 'get') {
-        // eslint-disable-next-line func-names
         $(this).on('submit', function () {
           self.loadUrl(action, $(this).serialize());
           return false;
         });
       } else {
-        // eslint-disable-next-line func-names
         $(this).on('submit', function () {
           self.postForm(action, $(this).serialize());
           return false;
@@ -69,13 +60,11 @@ function ModalWorkflow(opts) {
     });
   };
 
-  // eslint-disable-next-line func-names
   self.loadResponseText = function (responseText) {
     const response = JSON.parse(responseText);
     self.loadBody(response);
   };
 
-  // eslint-disable-next-line func-names
   self.loadBody = function (response) {
     if (response.html) {
       // if response contains an 'html' item, replace modal body with it
@@ -90,16 +79,13 @@ function ModalWorkflow(opts) {
     }
   };
 
-  // eslint-disable-next-line func-names
   self.respond = function (responseType) {
     if (responseType in responseCallbacks) {
-      // eslint-disable-next-line prefer-rest-params
       const args = Array.prototype.slice.call(arguments, 1);
       responseCallbacks[responseType].apply(self, args);
     }
   };
 
-  // eslint-disable-next-line func-names
   self.close = function () {
     container.modal('hide');
   };

+ 2 - 2
client/src/entrypoints/admin/page-chooser-modal.js

@@ -43,7 +43,7 @@ const PAGE_CHOOSER_MODAL_ONLOAD_HANDLERS = {
           success(data) {
             request = null;
             $('.page-results', modal.body).html(data);
-            // eslint-disable-next-line no-use-before-define
+            // eslint-disable-next-line @typescript-eslint/no-use-before-define
             ajaxifySearchResults();
           },
           error() {
@@ -53,7 +53,7 @@ const PAGE_CHOOSER_MODAL_ONLOAD_HANDLERS = {
       } else {
         /* search box is empty - restore original page browser HTML */
         $('.page-results', modal.body).html(initialPageResultsHtml);
-        // eslint-disable-next-line no-use-before-define
+        // eslint-disable-next-line @typescript-eslint/no-use-before-define
         ajaxifyBrowseResults();
       }
       return false;

+ 1 - 1
client/src/entrypoints/admin/page-editor.js

@@ -2,7 +2,7 @@ import $ from 'jquery';
 
 window.halloPlugins = {};
 
-// eslint-disable-next-line no-unused-vars
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 function registerHalloPlugin(name, opts) {  // lgtm[js/unused-local-variable]
   /* Obsolete - used on Wagtail <1.12 to register plugins for the hallo.js editor.
   Defined here so that third-party plugins can continue to call it to provide Wagtail <1.12

+ 1 - 1
client/src/entrypoints/admin/task-chooser-modal.js

@@ -13,7 +13,7 @@ const TASK_CHOOSER_MODAL_ONLOAD_HANDLERS = {
       // eslint-disable-next-line func-names
       $('.pagination a', context).on('click', function () {
         const page = this.getAttribute('data-page');
-        // eslint-disable-next-line no-use-before-define
+        // eslint-disable-next-line @typescript-eslint/no-use-before-define
         setPage(page);
         return false;
       });

+ 7 - 7
client/src/entrypoints/admin/userbar.js

@@ -17,33 +17,33 @@ document.addEventListener('DOMContentLoaded', (e) => {
     // in accordance with: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/
     trigger.addEventListener('touchend', (e2) => {
       e.preventDefault();
-      // eslint-disable-next-line no-use-before-define
+      // eslint-disable-next-line @typescript-eslint/no-use-before-define
       toggleUserbar(e2);
     });
   } else {
     userbar.classList.add('no-touch');
   }
 
-  // eslint-disable-next-line no-use-before-define
+  // eslint-disable-next-line @typescript-eslint/no-use-before-define
   trigger.addEventListener(clickEvent, toggleUserbar, false);
 
   // make sure userbar is hidden when navigating back
-  // eslint-disable-next-line no-use-before-define
+  // eslint-disable-next-line @typescript-eslint/no-use-before-define
   window.addEventListener('pageshow', hideUserbar, false);
 
   function showUserbar() {
     userbar.classList.add(className);
-    // eslint-disable-next-line no-use-before-define
+    // eslint-disable-next-line @typescript-eslint/no-use-before-define
     list.addEventListener(clickEvent, sandboxClick, false);
-    // eslint-disable-next-line no-use-before-define
+    // eslint-disable-next-line @typescript-eslint/no-use-before-define
     window.addEventListener(clickEvent, clickOutside, false);
   }
 
   function hideUserbar() {
     userbar.classList.remove(className);
-    // eslint-disable-next-line no-use-before-define
+    // eslint-disable-next-line @typescript-eslint/no-use-before-define
     list.addEventListener(clickEvent, sandboxClick, false);
-    // eslint-disable-next-line no-use-before-define
+    // eslint-disable-next-line @typescript-eslint/no-use-before-define
     window.removeEventListener(clickEvent, clickOutside, false);
   }
 

+ 1 - 1
client/src/entrypoints/admin/wagtailadmin.js

@@ -14,7 +14,7 @@ import {
 if (process.env.NODE_ENV === 'development') {
   // Run react-axe in development only, so it does not affect performance
   // in production, and does not break unit tests either.
-  // eslint-disable-next-line global-require
+  // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
   const axe = require('react-axe');
   axe(React, ReactDOM, 1000);
 }

+ 1 - 1
package.json

@@ -110,7 +110,7 @@
     "gulp:prod:build": "gulp build",
     "webpack:dev:watch": "webpack --config ./client/webpack.config.js --mode development --progress --watch",
     "webpack:prod:build": "webpack --config ./client/webpack.config.js --mode production",
-    "lint:js": "eslint --max-warnings 16 ./client",
+    "lint:js": "eslint --report-unused-disable-directives --max-warnings 16 ./client",
     "lint:css": "stylelint **/*.scss",
     "lint": "npm run lint:js && npm run lint:css",
     "test": "npm run test:unit",