diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 5c99ba78a..000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,5 +0,0 @@
-node_modules
-dist
-coverage
-**/*.d.ts
-tests
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e5c44d99a..c42fd7572 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -43,18 +43,18 @@ repos:
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: requirements-txt-fixer
- - repo: https://github.com/pre-commit/mirrors-eslint
- rev: 9158d5162f915488785c296b5d08d6d18be10d32 # frozen: v10.3.0
- hooks:
- - id: eslint
- files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
- exclude: ipyparallel/nbextension/.*
- types: [file]
- additional_dependencies:
- - "@typescript-eslint/eslint-plugin@2.27.0"
- - "@typescript-eslint/parser@2.27.0"
- - eslint@^6.0.0
- - eslint-config-prettier@6.10.1
- - eslint-plugin-prettier@3.1.4
- - eslint-plugin-react@7.21.5
- - typescript@4.1.3
+ # - repo: https://github.com/pre-commit/mirrors-eslint
+ # rev: 9158d5162f915488785c296b5d08d6d18be10d32 # frozen: v10.3.0
+ # hooks:
+ # - id: eslint
+ # files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
+ # exclude: ipyparallel/nbextension/.*
+ # types: [file]
+ # additional_dependencies:
+ # - "@typescript-eslint/eslint-plugin@8.59.2"
+ # - "@typescript-eslint/parser@2.27.0"
+ # - eslint@^6.0.0
+ # - eslint-config-prettier@6.10.1
+ # - eslint-plugin-prettier@3.1.4
+ # - eslint-plugin-react@7.21.5
+ # - typescript@4.1.3
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 000000000..473d8f868
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,65 @@
+import js from "@eslint/js";
+import { defineConfig } from "eslint/config";
+import tseslint from "typescript-eslint";
+import prettierRecommended from "eslint-plugin-prettier/recommended";
+import globals from "globals";
+import jupyterPlugin from "@jupyter/eslint-plugin";
+
+// workaround: plugin recommended config doesn't enable itself
+for (var cfg of jupyterPlugin.configs.recommended) {
+ cfg.plugins = {
+ jupyter: jupyterPlugin,
+ };
+}
+
+export default defineConfig([
+ {
+ ignores: ["node_modules", "dist", "coverage", "**/*.js", "**/*.d.ts"],
+ },
+ js.configs.recommended,
+ tseslint.configs.recommended,
+ jupyterPlugin.configs.recommended,
+ {
+ files: ["**/*.ts", "**/*.tsx"],
+ plugins: {
+ jupyter: jupyterPlugin,
+ },
+ languageOptions: {
+ globals: {
+ ...globals.browser,
+ ...globals.es2015,
+ ...globals.node,
+ },
+ parserOptions: {
+ project: "tsconfig.eslint.json",
+ sourceType: "module",
+ },
+ },
+ rules: {
+ "@typescript-eslint/naming-convention": [
+ "error",
+ {
+ selector: "interface",
+ format: ["PascalCase"],
+ custom: {
+ regex: "^I[A-Z]",
+ match: true,
+ },
+ },
+ ],
+ "@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-namespace": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/quotes": [
+ "error",
+ "single",
+ { avoidEscape: true, allowTemplateLiterals: false },
+ ],
+ curly: ["error", "all"],
+ eqeqeq: "error",
+ "prefer-arrow-callback": "error",
+ },
+ },
+ prettierRecommended,
+]);
diff --git a/lab/src/clusters.tsx b/lab/src/clusters.tsx
index b1e855540..0401dcfe8 100644
--- a/lab/src/clusters.tsx
+++ b/lab/src/clusters.tsx
@@ -282,7 +282,7 @@ export class ClusterManager extends Widget {
*/
protected onAfterAttach(msg: Message): void {
super.onAfterAttach(msg);
- let node = this._clusterListing.node;
+ const node = this._clusterListing.node;
node.addEventListener("p-dragenter", this);
node.addEventListener("p-dragleave", this);
node.addEventListener("p-dragover", this);
@@ -293,7 +293,7 @@ export class ClusterManager extends Widget {
* Handle `before-detach` messages for the widget.
*/
protected onBeforeDetach(msg: Message): void {
- let node = this._clusterListing.node;
+ const node = this._clusterListing.node;
node.removeEventListener("p-dragenter", this);
node.removeEventListener("p-dragleave", this);
node.removeEventListener("p-dragover", this);
@@ -378,13 +378,13 @@ export class ClusterManager extends Widget {
* Handle the `'mousemove'` event for the widget.
*/
private _evtMouseMove(event: MouseEvent): void {
- let data = this._dragData;
+ const data = this._dragData;
if (!data) {
return;
}
// Check for a drag initialization.
- let dx = Math.abs(event.clientX - data.pressX);
- let dy = Math.abs(event.clientY - data.pressY);
+ const dx = Math.abs(event.clientX - data.pressX);
+ const dy = Math.abs(event.clientY - data.pressY);
if (dx >= DRAG_THRESHOLD || dy >= DRAG_THRESHOLD) {
event.preventDefault();
event.stopPropagation();
@@ -641,7 +641,7 @@ export namespace ClusterManager {
* A React component for a launcher button listing.
*/
function ClusterListing(props: IClusterListingProps) {
- let listing = props.clusters.map((cluster) => {
+ const listing = props.clusters.map((cluster) => {
return (