Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for ESLint v9 compatibility #52

Merged
merged 16 commits into from
Oct 28, 2024
15 changes: 0 additions & 15 deletions .eslintrc.js

This file was deleted.

16 changes: 12 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ jobs:
test:
runs-on: ubuntu-latest

permissions:
# https://docs.npmjs.com/generating-provenance-statements#publishing-packages-with-provenance-via-github-actions
id-token: write

steps:
- uses: actions/checkout@v2

- uses: actions/setup-node@v2
with:
node-version: 16.x
node-version: 22.x
registry-url: https://registry.npmjs.org

- uses: actions/cache@v2
Expand All @@ -25,14 +29,18 @@ jobs:
key: v1-${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: v1-${{ runner.os }}-node-

- run: npm install
- run: npm run tsc
- run: npm ci
- run: npm run build
- run: npm run lint
- run: npm run test

# publish version tags
- name: npm publish (dry run)
run: npm publish --provenance --access public --dry-run
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: npm publish
run: npm publish --access public
run: npm publish --provenance --access public
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.log
*.tsbuildinfo
node_modules/
dist
6 changes: 2 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.options": {
"reportUnusedDisableDirectives": "error"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.prettierPath": "./node_modules/prettier",
"files.eol": "\n"
"files.eol": "\n",
"typescript.tsdk": "node_modules/typescript/lib"
}
51 changes: 11 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,34 @@

Foxglove default eslint configuration & rules.

Please err on the side of conservative changes to this repo - multiple Foxglove projects should adopt a change before making it a default.

## Rules

See [rules/README.md](rules/README.md) for details on each rule.

## Installation

The following configurations are available:

- `plugin:@foxglove/base`
- `plugin:@foxglove/jest`
- `plugin:@foxglove/react`
- `plugin:@foxglove/typescript`

**Typescript + React Example**

```sh
yarn add -D \
@foxglove/eslint-plugin \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
typescript-eslint \
eslint \
eslint-config-prettier \
eslint-plugin-es \
eslint-plugin-filenames \
eslint-plugin-import \
eslint-plugin-jest \
eslint-plugin-prettier \
eslint-plugin-react \
eslint-plugin-react-hooks \
prettier
```

In your `.eslintrc.js`:
In your `eslint.config.cjs`:

```js
module.exports = {
extends: [
"plugin:@foxglove/base",
"plugin:@foxglove/jest",
"plugin:@foxglove/react",
],
overrides: [
{
files: ["*.ts", "*.tsx"],
extends: ["plugin:@foxglove/typescript"],
parserOptions: {
project: "tsconfig.json",
},
},
],
};
const foxglove = require("@foxglove/eslint-plugin");
const tseslint = require("typescript-eslint");

module.exports = tseslint.config(
...foxglove.configs.base,
...foxglove.configs.react,
...foxglove.configs.jest,
...foxglove.configs.typescript
);
```

You can add `"plugin:@foxglove/typescript"` to the top level `extends` instead of using `overrides` if your project contains no `.js` files.

## License

@foxglove/eslint-plugin is released under the [MIT License](/LICENSE.md).
Expand Down
182 changes: 111 additions & 71 deletions configs/base.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,122 @@
module.exports = {
extends: ["eslint:recommended", "plugin:prettier/recommended"],
plugins: ["@foxglove", "import", "filenames", "es"],
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
},
rules: {
// even new Safari versions do not support regexp lookbehinds
"es/no-regexp-lookbehind-assertions": "error",
const { fixupPluginRules } = require("@eslint/compat");
const js = require("@eslint/js");
// @ts-expect-error Missing type definitions
const es = require("eslint-plugin-es");
// @ts-expect-error Missing type definitions
const filenames = require("eslint-plugin-filenames");
// @ts-expect-error Missing type definitions
const importPlugin = require("eslint-plugin-import");
const eslintPluginPrettierRecommended = require("eslint-plugin-prettier/recommended");

// import plugin is slow, only enable the critical stuff
"import/export": "error",
"import/first": "error",
"import/named": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
"import/no-mutable-exports": "error",
"import/no-useless-path-segments": "error",
"import/order": [
"error",
{
alphabetize: {
order: "asc",
},
"newlines-between": "always",
groups: [
["builtin", "external"],
["internal"],
["parent", "sibling", "index"],
],
const foxglove = require("../plugin");

const fixedFilenames = fixupPluginRules(filenames);

/** @type {import("eslint").Linter.Config[]} */
module.exports = [
js.configs.recommended,
eslintPluginPrettierRecommended,
{
linterOptions: {
reportUnusedDisableDirectives: "error",
},
plugins: {
"@foxglove": foxglove,
import: importPlugin,
es: fixupPluginRules(es),

// eslint-plugin-filenames allows rules to have options, but fixupPluginRules defaults to a
// schema that does not allow passing any options. We replace this with `false` to disable
// validation so that options can be passed in.
filenames: {
...fixedFilenames,
rules: Object.fromEntries(
Object.entries(fixedFilenames.rules ?? {}).map(([ruleId, rule]) => [
ruleId,
{
...rule,
meta: {
...rule.meta,
schema: rule.meta?.schema ?? false,
},
},
])
),
},
],
},
rules: {
// even new Safari versions do not support regexp lookbehinds
"es/no-regexp-lookbehind-assertions": "error",

"filenames/match-exported": "error",
// import plugin is slow, only enable the critical stuff
"import/export": "error",
"import/first": "error",
"import/named": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
"import/no-mutable-exports": "error",
"import/no-useless-path-segments": "error",
"import/order": [
"error",
{
alphabetize: {
order: "asc",
},
"newlines-between": "always",
groups: [
["builtin", "external"],
["internal"],
["parent", "sibling", "index"],
],
},
],

// require double equal for null and undefined, triple equal everywhere else
"@foxglove/strict-equality": "error",
"@foxglove/no-return-promise-resolve": "error",
"@foxglove/prefer-hash-private": "error",
"filenames/match-exported": "error",

// require curly braces everywhere
curly: "error",
// require double equal for null and undefined, triple equal everywhere else
"@foxglove/strict-equality": "error",
"@foxglove/no-return-promise-resolve": "error",
"@foxglove/prefer-hash-private": "error",

// avoid eval
"no-eval": "error",
"no-implied-eval": "error",
"no-new-func": "error",
// require curly braces everywhere
curly: "error",

// unused vars must have `_` prefix
"no-unused-vars": [
"error",
{
vars: "all",
args: "after-used",
varsIgnorePattern: "^_",
argsIgnorePattern: "^_",
},
],
// avoid eval
"no-eval": "error",
"no-implied-eval": "error",
"no-new-func": "error",

"no-underscore-dangle": [
"error",
{
allowAfterThis: true,
},
],
// unused vars must have `_` prefix
"no-unused-vars": [
"error",
{
vars: "all",
args: "after-used",
varsIgnorePattern: "^_",
argsIgnorePattern: "^_",
},
],

// avoid TO.DO and FIX.ME comments, create a ticket to track future work
"no-warning-comments": [
"error",
{
location: "anywhere",
},
],
"no-underscore-dangle": [
"error",
{
allowAfterThis: true,
},
],

// avoid TO.DO and FIX.ME comments, create a ticket to track future work
"no-warning-comments": [
"error",
{
location: "anywhere",
},
],

"no-unused-expressions": ["error", { enforceForJSX: true }],
"no-param-reassign": "error",
"no-useless-rename": "error",
"object-shorthand": "error",
"prefer-arrow-callback": ["error", { allowNamedFunctions: true }],
"no-unused-expressions": ["error", { enforceForJSX: true }],
"no-param-reassign": "error",
"no-useless-rename": "error",
"object-shorthand": "error",
"prefer-arrow-callback": ["error", { allowNamedFunctions: true }],
},
},
};
];
16 changes: 11 additions & 5 deletions configs/jest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
module.exports = {
extends: ["plugin:jest/recommended"],
rules: {
"jest/consistent-test-it": ["error", { fn: "it" }],
// @ts-ignore
const jest = require("eslint-plugin-jest");

/** @type {import("eslint").Linter.Config[]} */
module.exports = [
jest.configs["flat/recommended"],
{
rules: {
"jest/consistent-test-it": ["error", { fn: "it" }],
},
},
};
];
Loading
Loading