diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 85ef5b1a..00000000
--- a/.eslintignore
+++ /dev/null
@@ -1,4 +0,0 @@
-node_modules
-dist
-config/*
-.eslintrc.js
\ No newline at end of file
diff --git a/config/.eslintrc.js b/config/.eslintrc.js
deleted file mode 100644
index cd9bad44..00000000
--- a/config/.eslintrc.js
+++ /dev/null
@@ -1,51 +0,0 @@
-module.exports = {
- root: true,
- parserOptions: {
- tsconfigRootDir: __dirname,
- project: ["./tsconfig.eslint.json"],
- },
- plugins: ["@typescript-eslint", "jest"],
- extends: [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:@typescript-eslint/recommended-requiring-type-checking",
- "prettier",
- "plugin:no-unsanitized/DOM",
- ],
- rules: {
- "no-console": "error",
- "no-alert": "error",
- "no-process-env": "error",
- "@typescript-eslint/no-empty-object-type": "off",
- "@typescript-eslint/no-unused-expressions": "off",
- "@typescript-eslint/only-throw-error": "off",
- "@typescript-eslint/prefer-promise-reject-errors": "off",
- },
- overrides: [
- {
- // enable
- files: ["**/*.ts", "**/*.tsx"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- tsconfigRootDir: __dirname,
- },
- },
- {
- // only enable jest rules in non-e2e test files
- files: ["**/!(*.e2e).test.ts"],
- extends: ["plugin:jest/recommended", "plugin:jest/style"],
- rules: {
- "jest/no-disabled-tests": "off",
- "jest/consistent-test-it": ["error", { fn: "it" }],
- },
- },
- {
- // enable a subset of jest rules in e2e test files, since the syntax is similar-ish
- files: ["**/*.e2e.test.ts"],
- extends: ["plugin:jest/recommended"],
- rules: {
- "jest/no-standalone-expect": "off",
- },
- },
- ],
-};
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 00000000..35341ea0
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,57 @@
+const { defineConfig } = require("eslint/config");
+const js = require("@eslint/js");
+const ts = require("@typescript-eslint/eslint-plugin");
+const prettier = require("eslint-config-prettier/flat");
+const jest = require("eslint-plugin-jest");
+const noUnsanitized = require("eslint-plugin-no-unsanitized");
+
+module.exports = defineConfig([
+ {
+ ignores: ["dist/**", "config/**", "eslint.config.js"],
+ },
+ {
+ files: ["**/*.ts", "**/*.tsx"],
+ extends: [
+ js.configs.recommended,
+ ts.configs["flat/recommended-type-checked"],
+ prettier,
+ noUnsanitized.configs.recommended,
+ ],
+ languageOptions: {
+ parserOptions: {
+ tsconfigRootDir: __dirname,
+ project: ["./config/tsconfig.eslint.json"],
+ },
+ },
+ rules: {
+ // ESLint 9 removed this rule from its recommended preset.
+ "no-inner-declarations": [
+ "error",
+ "functions",
+ { blockScopedFunctions: "disallow" },
+ ],
+ "no-console": "error",
+ "no-alert": "error",
+ "no-process-env": "error",
+ "@typescript-eslint/no-empty-object-type": "off",
+ "@typescript-eslint/no-unused-expressions": "off",
+ "@typescript-eslint/only-throw-error": "off",
+ "@typescript-eslint/prefer-promise-reject-errors": "off",
+ },
+ },
+ {
+ files: ["**/!(*.e2e).test.ts"],
+ extends: [jest.configs["flat/recommended"], jest.configs["flat/style"]],
+ rules: {
+ "jest/no-disabled-tests": "off",
+ "jest/consistent-test-it": ["error", { fn: "it" }],
+ },
+ },
+ {
+ files: ["**/*.e2e.test.ts"],
+ extends: [jest.configs["flat/recommended"]],
+ rules: {
+ "jest/no-standalone-expect": "off",
+ },
+ },
+]);
diff --git a/package-lock.json b/package-lock.json
index 9967c427..47ef206f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -34,6 +34,7 @@
"@changesets/cli": "^3.0.3",
"@commitlint/cli": "^21.2.2",
"@commitlint/config-conventional": "^21.2.2",
+ "@eslint/js": "^10.0.1",
"@playwright/test": "^1.63.0",
"@stackoverflow/commitlint-config": "^1.0.0",
"@stackoverflow/prettier-config": "^1.0.0",
@@ -41,15 +42,15 @@
"@stackoverflow/tsconfig": "^1.0.0",
"@types/jest": "^30.0.0",
"@types/markdown-it": "^14.0.0",
- "@typescript-eslint/eslint-plugin": "^8.46.2",
- "@typescript-eslint/parser": "^8.46.2",
+ "@typescript-eslint/eslint-plugin": "^8.71.2",
+ "@typescript-eslint/parser": "^8.71.2",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^7.1.1",
"cssnano": "^9.0.0",
- "eslint": "^8.57.0",
+ "eslint": "^10.14.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jest": "^29.16.6",
- "eslint-plugin-no-unsanitized": "^4.0.2",
+ "eslint-plugin-no-unsanitized": "^4.1.5",
"highlight.js": "^11.9.0",
"html-loader": "^5.0.0",
"html-webpack-plugin": "^5.6.0",
@@ -710,6 +711,30 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@cacheable/memory": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz",
+ "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.5.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz",
+ "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
"node_modules/@changesets/apply-release-plan": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-8.1.1.tgz",
@@ -1630,86 +1655,90 @@
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
- "node_modules/@eslint/eslintrc": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
- "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "node_modules/@eslint/config-array": {
+ "version": "0.23.5",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
+ "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
+ "@eslint/object-schema": "^3.0.5",
+ "debug": "^4.3.1",
+ "minimatch": "^10.2.4"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@eslint/eslintrc/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz",
+ "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
+ "@eslint/core": "^1.2.1"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "node_modules/@eslint/core": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
+ "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "node_modules/@eslint/js": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
+ "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "eslint": "^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
},
- "node_modules/@eslint/eslintrc/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "node_modules/@eslint/object-schema": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
+ "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": "*"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@eslint/js": {
- "version": "8.57.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
- "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz",
+ "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.2.1",
+ "levn": "^0.4.1"
+ },
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@hotwired/stimulus": {
@@ -1719,44 +1748,42 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
- "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
- "deprecated": "Use @eslint/config-array instead",
+ "node_modules/@humanfs/core": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@humanwhocodes/object-schema": "^2.0.3",
- "debug": "^4.3.1",
- "minimatch": "^3.0.5"
+ "@humanfs/types": "^0.15.0"
},
"engines": {
- "node": ">=10.10.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "node_modules/@humanfs/node": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
}
},
- "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": "*"
+ "node": ">=18.18.0"
}
},
"node_modules/@humanwhocodes/module-importer": {
@@ -1773,13 +1800,19 @@
"url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@humanwhocodes/object-schema": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
- "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
- "deprecated": "Use @eslint/object-schema instead",
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
"dev": true,
- "license": "BSD-3-Clause"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
@@ -2870,6 +2903,30 @@
"tslib": "2"
}
},
+ "node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
@@ -2979,44 +3036,6 @@
"url": "https://paulmillr.com/funding/"
}
},
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/@parcel/watcher": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz",
@@ -3798,6 +3817,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/esrecurse": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
+ "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -5444,6 +5470,20 @@
"node": ">=20.19.0"
}
},
+ "node_modules/cacheable": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz",
+ "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.2.0",
+ "@cacheable/utils": "^2.5.0",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
+ },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@@ -6411,19 +6451,6 @@
"node": ">=6"
}
},
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/dom-converter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -6746,60 +6773,62 @@
}
},
"node_modules/eslint": {
- "version": "8.57.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
- "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
- "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "version": "10.14.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.14.0.tgz",
+ "integrity": "sha512-T0pNsxkb9IKmtQjhpK3d7nWOpFv+YHuMbTJnSVMoQblF0onvXfErrtp4V1jHtsQPan7dKaGVD0q1WCXnzMF31A==",
"dev": true,
"license": "MIT",
+ "workspaces": [
+ "packages/*"
+ ],
"dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.4",
- "@eslint/js": "8.57.1",
- "@humanwhocodes/config-array": "^0.13.0",
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.2",
+ "@eslint/config-array": "^0.23.5",
+ "@eslint/config-helpers": "^0.7.0",
+ "@eslint/core": "^1.2.1",
+ "@eslint/plugin-kit": "^0.7.3",
+ "@humanfs/node": "^0.16.8",
"@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "cross-spawn": "^7.0.6",
"debug": "^4.3.2",
- "doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
- "esquery": "^1.4.2",
+ "eslint-scope": "^9.1.2",
+ "eslint-visitor-keys": "^5.0.1",
+ "espree": "^11.2.0",
+ "esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
+ "file-entry-cache": "11.1.5 || >11.1.6 <12",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "graphemer": "^1.4.0",
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
- "js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
+ "minimatch": "^10.2.6",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.3",
- "strip-ansi": "^6.0.1",
- "text-table": "^0.2.0"
+ "optionator": "^0.9.3"
},
"bin": {
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
}
},
"node_modules/eslint-config-prettier": {
@@ -6849,27 +6878,29 @@
}
},
"node_modules/eslint-plugin-no-unsanitized": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.1.2.tgz",
- "integrity": "sha512-ydF3PMFKEIkP71ZbLHFvu6/FW8SvRv6VV/gECfrQkqyD5+5oCAtPz8ZHy0GRuMDtNe2jsNdPCQXX4LSbkapAVQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.1.5.tgz",
+ "integrity": "sha512-MSB4hXPVFQrI8weqzs6gzl7reP2k/qSjtCoL2vUMSDejIIq9YL1ZKvq5/ORBXab/PvfBBrWO2jWviYpL+4Ghfg==",
"dev": true,
"license": "MPL-2.0",
"peerDependencies": {
- "eslint": "^8 || ^9"
+ "eslint": "^9 || ^10"
}
},
"node_modules/eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
+ "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
+ "@types/esrecurse": "^4.3.1",
+ "@types/estree": "^1.0.8",
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -6889,9 +6920,9 @@
}
},
"node_modules/eslint/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6905,15 +6936,17 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/find-up": {
@@ -6956,19 +6989,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/eslint/node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
@@ -6986,18 +7006,31 @@
}
},
"node_modules/espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+ "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.9.0",
+ "acorn": "^8.16.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
+ "eslint-visitor-keys": "^5.0.1"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -7018,9 +7051,9 @@
}
},
"node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -7271,16 +7304,6 @@
"fast-string-width": "^3.0.2"
}
},
- "node_modules/fastq": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
- "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
"node_modules/fb-watchman": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
@@ -7292,16 +7315,13 @@
}
},
"node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "version": "11.1.5",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz",
+ "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^3.0.4"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "flat-cache": "^6.1.23"
}
},
"node_modules/fill-range": {
@@ -7364,41 +7384,21 @@
}
},
"node_modules/flat-cache": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
- "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "version": "6.1.23",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz",
+ "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flat-cache/node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "cacheable": "^2.5.0",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
}
},
"node_modules/flatted": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
- "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
+ "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
"dev": true,
"license": "ISC"
},
@@ -7656,22 +7656,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -7692,13 +7676,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/handlebars": {
"version": "4.7.9",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
@@ -7744,6 +7721,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -7776,6 +7766,13 @@
"node": ">=12.0.0"
}
},
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -8389,16 +8386,6 @@
"node": ">=6"
}
},
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
@@ -9419,13 +9406,6 @@
"node": ">=6"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -9468,13 +9448,13 @@
"license": "MIT"
},
"node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "json-buffer": "3.0.1"
+ "@keyv/serialize": "^1.1.1"
}
},
"node_modules/kind-of": {
@@ -9609,13 +9589,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
@@ -11538,6 +11511,26 @@
"node": ">=16.0.0"
}
},
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/qs": {
"version": "6.15.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
@@ -11555,27 +11548,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/range-parser": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz",
@@ -11745,17 +11717,6 @@
"node": ">=8"
}
},
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
"node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -11813,30 +11774,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -12808,13 +12745,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/thingies": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.1.tgz",
@@ -13170,19 +13100,6 @@
"node": ">=4"
}
},
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/type-is": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
diff --git a/package.json b/package.json
index c5e2c4d3..a8aeaeca 100644
--- a/package.json
+++ b/package.json
@@ -38,13 +38,14 @@
"build:dev": "webpack --config config/webpack.dev.js",
"build:gh-pages": "webpack --config config/webpack.dev.js --mode=production --",
"build:stats": "webpack --config config/webpack.prod.js --entry ./src/index.ts --profile --json > stats.json",
- "lint": "prettier --check . && eslint .",
+ "lint": "prettier --check . && eslint . && npm run test:lint-config",
"format": "prettier --write .",
"test": "npm run test:unit && npm run test:e2e",
"test:unit": "jest --config config/jest-unit.config.js",
"test:e2e": "npx playwright test --config config/playwright.config.ts",
"test:package": "npm run prepublishOnly && node --test scripts/package-artifact.test.mjs",
"test:release-config": "node --test scripts/stable-release-config.test.mjs",
+ "test:lint-config": "node --test scripts/eslint-config.test.mjs",
"release": "npm run build && changeset publish",
"version": "changeset version && npm install --package-lock-only",
"prepublishOnly": "npm run build && tsc --module ES6 --sourceMap false",
@@ -61,16 +62,12 @@
"@stackoverflow"
]
},
- "eslintConfig": {
- "extends": [
- "./config/.eslintrc.js"
- ]
- },
"devDependencies": {
"@commitlint/cli": "^21.2.2",
"@commitlint/config-conventional": "^21.2.2",
"@changesets/changelog-github": "^1.0.0",
"@changesets/cli": "^3.0.3",
+ "@eslint/js": "^10.0.1",
"@playwright/test": "^1.63.0",
"@stackoverflow/commitlint-config": "^1.0.0",
"@stackoverflow/prettier-config": "^1.0.0",
@@ -78,15 +75,15 @@
"@stackoverflow/tsconfig": "^1.0.0",
"@types/jest": "^30.0.0",
"@types/markdown-it": "^14.0.0",
- "@typescript-eslint/eslint-plugin": "^8.46.2",
- "@typescript-eslint/parser": "^8.46.2",
+ "@typescript-eslint/eslint-plugin": "^8.71.2",
+ "@typescript-eslint/parser": "^8.71.2",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^7.1.1",
"cssnano": "^9.0.0",
- "eslint": "^8.57.0",
+ "eslint": "^10.14.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jest": "^29.16.6",
- "eslint-plugin-no-unsanitized": "^4.0.2",
+ "eslint-plugin-no-unsanitized": "^4.1.5",
"highlight.js": "^11.9.0",
"html-loader": "^5.0.0",
"html-webpack-plugin": "^5.6.0",
diff --git a/scripts/eslint-config.test.mjs b/scripts/eslint-config.test.mjs
new file mode 100644
index 00000000..dc9ce95f
--- /dev/null
+++ b/scripts/eslint-config.test.mjs
@@ -0,0 +1,85 @@
+import assert from "node:assert/strict";
+import { test } from "node:test";
+import { ESLint } from "eslint";
+
+const eslint = new ESLint({
+ overrideConfig: {
+ languageOptions: {
+ parserOptions: {
+ // lintText supplies different source for existing project files.
+ // Keep CI from reusing an immutable program built from disk.
+ disallowAutomaticSingleRunInference: true,
+ },
+ },
+ },
+});
+
+async function lint(code, filePath) {
+ const [result] = await eslint.lintText(code, { filePath });
+ assert.equal(result.fatalErrorCount, 0, JSON.stringify(result.messages));
+ return result.messages.map(({ ruleId }) => ruleId);
+}
+
+test("rejects unsafe DOM assignments and method calls", async () => {
+ const rules = await lint(
+ 'const input = window.location.hash; document.body.innerHTML = input; document.body.insertAdjacentHTML("beforeend", input);',
+ "src/shared/utils.ts"
+ );
+
+ assert.ok(rules.includes("no-unsanitized/property"));
+ assert.ok(rules.includes("no-unsanitized/method"));
+});
+
+test("retains the prior restriction on block-scoped function declarations", async () => {
+ const rules = await lint(
+ "if (true) { function nested() { return 1; } nested(); }",
+ "src/shared/utils.ts"
+ );
+
+ assert.ok(rules.includes("no-inner-declarations"));
+});
+
+test("keeps type-aware linting enabled", async () => {
+ const rules = await lint("Promise.resolve(1);", "src/shared/utils.ts");
+
+ assert.ok(rules.includes("@typescript-eslint/no-floating-promises"));
+});
+
+test("applies unit-test conventions only to unit tests", async () => {
+ const unitRules = await lint(
+ 'test("works", () => { expect(1).toBe(1); });',
+ "test/shared/utils.test.ts"
+ );
+ const e2eRules = await lint(
+ 'test("works", () => { expect(1).toBe(1); });',
+ "test/rich-text/inputrules.e2e.test.ts"
+ );
+
+ assert.ok(unitRules.includes("jest/consistent-test-it"));
+ assert.ok(!e2eRules.includes("jest/consistent-test-it"));
+});
+
+test("allows standalone Playwright assertions while checking Jest assertions", async () => {
+ const unitRules = await lint(
+ "expect(1).toBe(1);",
+ "test/shared/utils.test.ts"
+ );
+ const e2eRules = await lint(
+ "expect(1).toBe(1);",
+ "test/rich-text/inputrules.e2e.test.ts"
+ );
+
+ assert.ok(unitRules.includes("jest/no-standalone-expect"));
+ assert.ok(!e2eRules.includes("jest/no-standalone-expect"));
+});
+
+test("ignores generated output, dependencies, and build configuration", async () => {
+ for (const file of [
+ "dist/src/index.js",
+ "node_modules/example/index.js",
+ "config/webpack.common.js",
+ "eslint.config.js",
+ ]) {
+ assert.equal(await eslint.isPathIgnored(file), true, file);
+ }
+});
diff --git a/site/serviceworker.ts b/site/serviceworker.ts
index 021b1c8b..1409e009 100644
--- a/site/serviceworker.ts
+++ b/site/serviceworker.ts
@@ -1,5 +1,5 @@
///
-// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Window extends ServiceWorkerGlobalScope {}
self.addEventListener("activate", function () {
diff --git a/src/rich-text/commands/index.ts b/src/rich-text/commands/index.ts
index c6ff819b..cb585e29 100644
--- a/src/rich-text/commands/index.ts
+++ b/src/rich-text/commands/index.ts
@@ -145,7 +145,7 @@ export function toggleTagLinkCommand(
return true;
}
- let tr = state.tr;
+ let tr: Transaction;
const nodeCheck = nodeTypeActive(state.schema.nodes.tagLink);
if (nodeCheck(state)) {
const selectedText = state.selection.content().content.firstChild
diff --git a/src/rich-text/plugins/link-editor.ts b/src/rich-text/plugins/link-editor.ts
index 746c39d3..6f73cd14 100644
--- a/src/rich-text/plugins/link-editor.ts
+++ b/src/rich-text/plugins/link-editor.ts
@@ -590,8 +590,7 @@ class LinkTooltip {
};
this.editListener = () => {
- let tr = view.state.tr;
- tr = this.expandSelection(view.state, view.state.tr);
+ let tr = this.expandSelection(view.state, view.state.tr);
const state = view.state.apply(tr);
const { from, to } = state.selection;
@@ -651,12 +650,14 @@ export const linkEditorPlugin = (features: CommonmarkParserFeatures) =>
//get decoration for current selection
const sel = state.selection;
- let selectionDecoration = null;
-
if (meta.visible && sel && sel.from !== sel.to) {
- selectionDecoration = Decoration.inline(sel.from, sel.to, {
- class: "bg-black-225",
- });
+ const selectionDecoration = Decoration.inline(
+ sel.from,
+ sel.to,
+ {
+ class: "bg-black-225",
+ }
+ );
decorations = decorations.add(newState.doc, [
selectionDecoration,
]);
diff --git a/src/shared/markdown-it/html.ts b/src/shared/markdown-it/html.ts
index aaa5ba22..0ccf78e1 100644
--- a/src/shared/markdown-it/html.ts
+++ b/src/shared/markdown-it/html.ts
@@ -36,7 +36,7 @@ function getTagInfo(tag: string): TagInfo {
};
}
- let tagType = TagType.unknown;
+ let tagType: TagType;
// check if this tag looks like `` or ``
const isClosingTag = /^<\/\S+?.*?>$/.test(tag);
@@ -139,7 +139,7 @@ function tagInfoToToken(
: tagInfo.isClosing
? "_close"
: "_open";
- let tokenType = "";
+ let tokenType: string;
switch (tagInfo.type) {
case TagType.unknown:
diff --git a/src/shared/markdown-it/tag-link.ts b/src/shared/markdown-it/tag-link.ts
index eb40c574..70c66790 100644
--- a/src/shared/markdown-it/tag-link.ts
+++ b/src/shared/markdown-it/tag-link.ts
@@ -18,7 +18,6 @@ function parse_tag_link(
return false;
}
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const labelEnd = state.md.helpers.parseLinkLabel(
state,
state.pos + 1,
@@ -51,7 +50,7 @@ function parse_tag_link(
token = state.push("text", "", 0);
token.content = tagName;
- token = state.push("tag_link_close", "a", -1);
+ state.push("tag_link_close", "a", -1);
}
state.pos = labelEnd + 1;
diff --git a/src/shared/markdown-serializer.ts b/src/shared/markdown-serializer.ts
index 37dba6de..1c4da3e6 100644
--- a/src/shared/markdown-serializer.ts
+++ b/src/shared/markdown-serializer.ts
@@ -36,7 +36,6 @@ class SOMarkdownSerializerState extends MarkdownSerializerState {
marks: MarkdownSerializerMarks,
options: { [key: string]: unknown }
) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error TODO constructor not exposed in types
super(nodes, marks, options);
}
@@ -280,7 +279,7 @@ const defaultMarkdownSerializerNodes: MarkdownSerializerNodes = {
const title = node.attrs.title
? // @ts-expect-error TODO types might be wrong here
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-plus-operands
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
" " + state.quote(node.attrs.title)
: "";
@@ -452,7 +451,6 @@ const customMarkdownSerializerNodes: MarkdownSerializerNodes = {
return null;
}
- // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
const match = alignment.match(/text-align:[ ]?(left|right|center)/);
if (match && match[1]) {
diff --git a/src/shared/utils.ts b/src/shared/utils.ts
index 31837373..09cc0b90 100644
--- a/src/shared/utils.ts
+++ b/src/shared/utils.ts
@@ -33,7 +33,7 @@ function isPlainObject(obj: unknown): boolean {
function mergeObject(object1: unknown, object2: unknown): unknown {
// if both are arrays, shallow merge (else, non-object merge)
if (object1 instanceof Array && object2 instanceof Array) {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-assignment
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
return [...object1, ...object2];
}
diff --git a/test/global.d.ts b/test/global.d.ts
index 82c4d5f7..87d4dfc7 100644
--- a/test/global.d.ts
+++ b/test/global.d.ts
@@ -4,7 +4,7 @@ export {};
* NOTE: Add all exposed matches to `expect.extend` at the bottom
* and add all the definitions below so TS can pick them up without error
*/
-/* eslint-disable @typescript-eslint/no-empty-interface */
+
interface CustomMatchers {
/**
* Compares a node dynamically via a deep tree structure, recursing through a document's content via the tree's content
@@ -32,13 +32,11 @@ export interface CompareTree {
}
declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest {
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Expect extends CustomMatchers {}
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
+
interface Matchers extends CustomMatchers {}
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
+
interface InverseAsymmetricMatchers extends CustomMatchers {}
}
}
diff --git a/test/rich-text/commands/tables.test.ts b/test/rich-text/commands/tables.test.ts
index 23aba7df..9800a572 100644
--- a/test/rich-text/commands/tables.test.ts
+++ b/test/rich-text/commands/tables.test.ts
@@ -269,7 +269,7 @@ describe("table commands", () => {
});
it("should do nothing when outside of a table", () => {
- let state = applySelection(
+ const state = applySelection(
createState(
"some paragraph
",
[]
@@ -279,7 +279,7 @@ describe("table commands", () => {
expect(state.selection.$from.node().type.name).toBe("paragraph");
- state = runCommand(state, insertTableRowBeforeCommand, false);
+ runCommand(state, insertTableRowBeforeCommand, false);
});
});
@@ -430,7 +430,7 @@ describe("table commands", () => {
});
it("should do nothing when outside of a table", () => {
- let state = applySelection(
+ const state = applySelection(
createState(
"some paragraph
",
[]
@@ -440,7 +440,7 @@ describe("table commands", () => {
expect(state.selection.$from.node().type.name).toBe("paragraph");
- state = runCommand(state, insertTableColumnAfterCommand, false);
+ runCommand(state, insertTableColumnAfterCommand, false);
});
});
diff --git a/test/rich-text/plugins/link-editor.test.ts b/test/rich-text/plugins/link-editor.test.ts
index f9d80c17..7514e1ef 100644
--- a/test/rich-text/plugins/link-editor.test.ts
+++ b/test/rich-text/plugins/link-editor.test.ts
@@ -763,7 +763,7 @@ describe("link-editor", () => {
function getDecorations(state: EditorState) {
const pState = state.plugins
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+
// @ts-expect-error this isn't a public field, but I don't care
.find((p) => p.spec?.key?.name === "LinkEditor")
?.getState(state) as {
@@ -854,7 +854,6 @@ function setFormValue(form: HTMLFormElement, name: string, value: string) {
}
function getViewContainer(editor: LinkEditor) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error this isn't a public field, but I don't care
return editor.viewContainer;
}
diff --git a/test/rich-text/plugins/plain-text-paste-handler.test.ts b/test/rich-text/plugins/plain-text-paste-handler.test.ts
index 901550fd..0979164b 100644
--- a/test/rich-text/plugins/plain-text-paste-handler.test.ts
+++ b/test/rich-text/plugins/plain-text-paste-handler.test.ts
@@ -225,7 +225,7 @@ describe("plain-text-paste-handler", () => {
);
const doc = parseHtmlToDoc(pasteData["text/html"], true);
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+
const handled = plainTextPasteHandler.props.handlePaste.bind(
plainTextPasteHandler
)(view, evt, doc) as boolean;
diff --git a/test/shared/markdown-serializer.test.ts b/test/shared/markdown-serializer.test.ts
index f66f0c31..9d27f51b 100644
--- a/test/shared/markdown-serializer.test.ts
+++ b/test/shared/markdown-serializer.test.ts
@@ -27,7 +27,6 @@ function nonMarkdownRichView(domstringInput: string) {
doc.innerHTML = domstringInput;
editor.editorView.updateState(
EditorState.create({
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
schema: oldState.schema,
doc: DOMParser.fromSchema(oldState.schema).parse(doc),
plugins: oldState.plugins,
diff --git a/test/shared/prosemirror-plugins/image-upload.e2e.test.ts b/test/shared/prosemirror-plugins/image-upload.e2e.test.ts
index 1f8fc0a1..67bc8fd7 100644
--- a/test/shared/prosemirror-plugins/image-upload.e2e.test.ts
+++ b/test/shared/prosemirror-plugins/image-upload.e2e.test.ts
@@ -1,4 +1,3 @@
-/* eslint-disable jest/no-commented-out-tests */
import { test, expect, Page } from "@playwright/test";
import { editorSelector, switchMode } from "../../e2e-helpers";
diff --git a/test/shared/prosemirror-plugins/interface-manager.test.ts b/test/shared/prosemirror-plugins/interface-manager.test.ts
index b4454c5d..0480c423 100644
--- a/test/shared/prosemirror-plugins/interface-manager.test.ts
+++ b/test/shared/prosemirror-plugins/interface-manager.test.ts
@@ -245,7 +245,7 @@ describe("interface-manager plugin", () => {
let tr = childKey1.showInterfaceTr(state, {
arbitraryData: "foo1",
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+
// @ts-expect-error we want to pass this in anyways to ensure it is not taken into account
shouldShow: false, // NOTE: this one is overwritten by showInterface
});
@@ -258,7 +258,7 @@ describe("interface-manager plugin", () => {
tr = childKey1.hideInterfaceTr(state, {
arbitraryData: "foo2",
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+
// @ts-expect-error we want to pass this in anyways to ensure it is not taken into account
shouldShow: true, // NOTE: this one is overwritten by hideInterface
});
diff --git a/test/shared/prosemirror-plugins/readonly.test.ts b/test/shared/prosemirror-plugins/readonly.test.ts
index c319429a..d5f276bf 100644
--- a/test/shared/prosemirror-plugins/readonly.test.ts
+++ b/test/shared/prosemirror-plugins/readonly.test.ts
@@ -81,10 +81,10 @@ describe("readonly plugin", () => {
expect(tr).toBeUndefined();
// toggle on for next bit...
- ({ state, tr } = toggleAndApplyState(state, true));
+ ({ state } = toggleAndApplyState(state, true));
// now, set to "on" when already on
- ({ state, tr } = toggleAndApplyState(state, true));
+ ({ tr } = toggleAndApplyState(state, true));
expect(tr).toBeUndefined();
});
});
diff --git a/test/test-helpers.ts b/test/test-helpers.ts
index 8033c346..dc597e5f 100644
--- a/test/test-helpers.ts
+++ b/test/test-helpers.ts
@@ -64,7 +64,6 @@ export function getPluginViewInstance(
editorView: EditorView,
type: PluginViewConstructor
): T | null {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error not exposed to consumers, but I don't care :P
return (editorView.pluginViews as PluginView[]).find(
(pv) => pv instanceof type
@@ -77,7 +76,6 @@ export function getPluginByName(
name: string
): Plugin | null {
return state.plugins.find(
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error not exposed to consumers, but this is a hack for tests so...
(p) => p.spec.key?.name === name || p.key === name + "$"
);