diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml index 48c68f5955..cea4567406 100644 --- a/.github/workflows/node-pretest.yml +++ b/.github/workflows/node-pretest.yml @@ -2,6 +2,9 @@ name: 'Tests: pretest/posttest' on: [pull_request, push] +permissions: + contents: read + jobs: pretest: runs-on: ubuntu-latest @@ -18,7 +21,7 @@ jobs: working-directory: "packages/${{ matrix.package }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index 6fc77ea08d..af1b557d11 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -2,6 +2,9 @@ name: 'Tests: node.js' on: [pull_request, push] +permissions: + contents: read + jobs: matrix: runs-on: ubuntu-latest @@ -39,7 +42,7 @@ jobs: working-directory: "packages/${{ matrix.package }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' with: @@ -50,7 +53,7 @@ jobs: - run: node -pe "require('eslint/package.json').version" name: 'eslint version' - run: npm run travis - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v5 react: needs: [matrix] @@ -74,7 +77,7 @@ jobs: working-directory: "packages/${{ matrix.package }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' with: @@ -87,7 +90,7 @@ jobs: - run: npm install --no-save "eslint-plugin-react-hooks@${{ matrix.react-hooks }}" if: ${{ matrix.react-hooks > 0}} - run: npm run travis - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v5 prepublish-base: name: 'prepublish tests (base config)' @@ -106,7 +109,7 @@ jobs: working-directory: "packages/${{ matrix.package }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: @@ -139,7 +142,7 @@ jobs: working-directory: "packages/${{ matrix.package }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index 027aed0797..fff3ba2d33 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -2,14 +2,20 @@ name: Automatic Rebase on: [pull_request_target] +permissions: + contents: read + jobs: _: + permissions: + contents: write # for ljharb/rebase to push code to rebase + pull-requests: read # for ljharb/rebase to get info about PR name: "Automatic Rebase" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ljharb/rebase@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml index 549d7b4823..eb3631b9e3 100644 --- a/.github/workflows/require-allow-edits.yml +++ b/.github/workflows/require-allow-edits.yml @@ -2,8 +2,13 @@ name: Require “Allow Edits” on: [pull_request_target] +permissions: + contents: read + jobs: _: + permissions: + pull-requests: read # for ljharb/require-allow-edits to check 'allow edits' on PR name: "Require “Allow Edits”" runs-on: ubuntu-latest diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..f405009e86 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +Airbnb has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full Code of Conduct text](https://airbnb.tech/open-source/code-of-conduct/) so that you can understand what actions will and will not be tolerated. Report violations to the maintainers of this project or to [opensource-conduct@airbnb.com](mailto:opensource-conduct@airbnb.com). + +Reports sent to [opensource-conduct@airbnb.com](mailto:opensource-conduct@airbnb.com) are received by Airbnb's open source code of conduct moderation team, which is composed of Airbnb employees. All communications are private and confidential. diff --git a/README.md b/README.md index 0f66720755..bd91faf2ea 100644 --- a/README.md +++ b/README.md @@ -2133,8 +2133,8 @@ Other Style Guides ```javascript // bad const foo = maybe1 > maybe2 - ? "bar" - : value1 > value2 ? "baz" : null; + ? 'bar' + : value1 > value2 ? 'baz' : null; // split into 2 separated ternary expressions const maybeNull = value1 > value2 ? 'baz' : null; @@ -3746,7 +3746,7 @@ Other Style Guides ## ECMAScript 5 Compatibility - - [27.1](#es5-compat--kangax) Refer to [Kangax](https://twitter.com/kangax/)’s ES5 [compatibility table](https://kangax.github.io/es5-compat-table/). + - [27.1](#es5-compat--kangax) Refer to [Kangax](https://twitter.com/kangax/)’s ES5 [compatibility table](https://compat-table.github.io/compat-table/es5/). **[⬆ back to top](#table-of-contents)** @@ -3952,7 +3952,6 @@ Other Style Guides - **Axept**: [axept/javascript](https://github.com/axept/javascript) - **Billabong**: [billabong/javascript](https://github.com/billabong/javascript) - **Bisk**: [bisk](https://github.com/Bisk/) - - **Bonhomme**: [bonhommeparis/javascript](https://github.com/bonhommeparis/javascript) - **Brainshark**: [brainshark/javascript](https://github.com/brainshark/javascript) - **CaseNine**: [CaseNine/javascript](https://github.com/CaseNine/javascript) - **Cerner**: [Cerner](https://github.com/cerner/) @@ -3965,7 +3964,6 @@ Other Style Guides - **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript) - **Drupal**: [www.drupal.org](https://git.drupalcode.org/project/drupal/blob/8.6.x/core/.eslintrc.json) - **Ecosia**: [ecosia/javascript](https://github.com/ecosia/javascript) - - **Evernote**: [evernote/javascript-style-guide](https://github.com/evernote/javascript-style-guide) - **Evolution Gaming**: [evolution-gaming/javascript](https://github.com/evolution-gaming/javascript) - **EvozonJs**: [evozonjs/javascript](https://github.com/evozonjs/javascript) - **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript) @@ -3978,10 +3976,10 @@ Other Style Guides - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript) - **Grupo-Abraxas**: [Grupo-Abraxas/javascript](https://github.com/Grupo-Abraxas/javascript) - **Happeo**: [happeo/javascript](https://github.com/happeo/javascript) - - **Honey**: [honeyscience/javascript](https://github.com/honeyscience/javascript) - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript-style-guide) - **HubSpot**: [HubSpot/javascript](https://github.com/HubSpot/javascript) - **Hyper**: [hyperoslo/javascript-playbook](https://github.com/hyperoslo/javascript-playbook/blob/master/style.md) + - **ILIAS**: [ILIAS](https://github.com/ILIAS-eLearning/ILIAS) - **InterCity Group**: [intercitygroup/javascript-style-guide](https://github.com/intercitygroup/javascript-style-guide) - **Jam3**: [Jam3/Javascript-Code-Conventions](https://github.com/Jam3/Javascript-Code-Conventions) - **JSSolutions**: [JSSolutions/javascript](https://github.com/JSSolutions/javascript) @@ -4004,7 +4002,6 @@ Other Style Guides - **Pier 1**: [Pier1/javascript](https://github.com/pier1/javascript) - **Qotto**: [Qotto/javascript-style-guide](https://github.com/Qotto/javascript-style-guide) - **React**: [reactjs.org/docs/how-to-contribute.html#style-guide](https://reactjs.org/docs/how-to-contribute.html#style-guide) - - **REI**: [reidev/js-style-guide](https://github.com/rei/code-style-guides/) - **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide) - **Sainsbury’s Supermarkets**: [jsainsburyplc](https://github.com/jsainsburyplc) - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript) @@ -4028,6 +4025,7 @@ Other Style Guides - **WeBox Studio**: [weboxstudio/javascript](https://github.com/weboxstudio/javascript) - **Weggo**: [Weggo/javascript](https://github.com/Weggo/javascript) - **Zillow**: [zillow/javascript](https://github.com/zillow/javascript) + - **Zit Software**: [zit-software/javascript](https://github.com/zit-software/javascript) - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript) **[⬆ back to top](#table-of-contents)** diff --git a/css-in-javascript/README.md b/css-in-javascript/README.md index d6162df55d..2e6ab68a1b 100644 --- a/css-in-javascript/README.md +++ b/css-in-javascript/README.md @@ -34,7 +34,7 @@ - Use an underscore for modifiers to other styles. - > Why? Similar to BEM, this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes. + > Why? Similar to [BEM](https://getbem.com/introduction/), this naming convention makes it clear that the styles are intended to modify the element preceded by the underscore. Underscores do not need to be quoted, so they are preferred over other characters, such as dashes. ```js // bad diff --git a/package.json b/package.json index a78bc250d4..afe129da02 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A mostly reasonable approach to JavaScript.", "scripts": { "preinstall": "npm run install:config && npm run install:config:base", - "postinstall": "rm -rf node_modules/markdownlint-cli/node_modules/markdownlint", + "postinstall": "rimraf node_modules/markdownlint-cli/node_modules/markdownlint", "install:config": "cd packages/eslint-config-airbnb && npm prune && npm install", "install:config:base": "cd packages/eslint-config-airbnb-base && npm prune && npm install", "lint": "markdownlint --config linters/.markdownlint.json README.md */README.md", @@ -41,6 +41,7 @@ "homepage": "https://github.com/airbnb/javascript", "devDependencies": { "markdownlint": "^0.29.0", - "markdownlint-cli": "^0.35.0" + "markdownlint-cli": "^0.35.0", + "rimraf": "^6.0.1" } } diff --git a/packages/eslint-config-airbnb-base/README.md b/packages/eslint-config-airbnb-base/README.md index 6ddc34dac1..79052b256a 100644 --- a/packages/eslint-config-airbnb-base/README.md +++ b/packages/eslint-config-airbnb-base/README.md @@ -62,6 +62,16 @@ Our default export contains all of our ESLint rules, including ECMAScript 6+. It 2. Add `"extends": "airbnb-base"` to your .eslintrc. +> **Note**: ESLint only lints `.js` files by default. + + If your project uses `.jsx` (or `.tsx` with TypeScript), you need to pass extensions to the CLI: + + ```sh + eslint . --ext .js, .jsx, .mjs + ``` + + Without this, JSX-related rules will not apply to `.jsx` files. + ### eslint-config-airbnb-base/legacy Lints ES5 and below. Requires `eslint` and `eslint-plugin-import`. diff --git a/packages/eslint-config-airbnb-base/package.json b/packages/eslint-config-airbnb-base/package.json index 6ae226d583..8f039d4d7c 100644 --- a/packages/eslint-config-airbnb-base/package.json +++ b/packages/eslint-config-airbnb-base/package.json @@ -68,20 +68,20 @@ }, "homepage": "https://github.com/airbnb/javascript", "devDependencies": { - "@babel/runtime": "^7.23.9", + "@babel/runtime": "^7.25.6", "babel-preset-airbnb": "^4.5.0", "babel-tape-runner": "^3.0.0", "eclint": "^2.8.1", "eslint": "^7.32.0 || ^8.2.0", "eslint-find-rules": "^4.1.0", - "eslint-plugin-import": "^2.29.1", + "eslint-plugin-import": "^2.30.0", "in-publish": "^2.0.1", "safe-publish-latest": "^2.0.0", - "tape": "^5.7.5" + "tape": "^5.9.0" }, "peerDependencies": { "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.29.1" + "eslint-plugin-import": "^2.30.0" }, "engines": { "node": "^10.12.0 || >=12.0.0" diff --git a/packages/eslint-config-airbnb-base/rules/imports.js b/packages/eslint-config-airbnb-base/rules/imports.js index d36e4908fa..b9453924dc 100644 --- a/packages/eslint-config-airbnb-base/rules/imports.js +++ b/packages/eslint-config-airbnb-base/rules/imports.js @@ -279,5 +279,9 @@ module.exports = { // https://github.com/import-js/eslint-plugin-import/blob/d5fc8b670dc8e6903dbb7b0894452f60c03089f5/docs/rules/no-empty-named-blocks.md // TODO, semver-minor: enable 'import/no-empty-named-blocks': 'off', + + // https://github.com/import-js/eslint-plugin-import/blob/3a99e4c8d3bfd2cd466353d11784eb06dad9b166/docs/rules/enforce-node-protocol-usage.md + // TODO, semver-major: enable + 'import/enforce-node-protocol-usage': ['off', 'never'], }, }; diff --git a/packages/eslint-config-airbnb-base/rules/style.js b/packages/eslint-config-airbnb-base/rules/style.js index 2e7f6fed44..ad38834d88 100644 --- a/packages/eslint-config-airbnb-base/rules/style.js +++ b/packages/eslint-config-airbnb-base/rules/style.js @@ -345,7 +345,7 @@ module.exports = { }, { selector: 'ForOfStatement', - message: 'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', + message: 'iterators/generators require regenerator-runtime in older browsers/engines, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', }, { selector: 'LabeledStatement', @@ -510,7 +510,7 @@ module.exports = { markers: ['=', '!', '/'], // space here to support sprockets directives, slash for TS /// comments }, block: { - exceptions: ['-', '+'], + exceptions: ['-', '+', '*'], markers: ['=', '!', ':', '::'], // space here to support sprockets directives and flow comment types balanced: true, } diff --git a/packages/eslint-config-airbnb-base/whitespace.js b/packages/eslint-config-airbnb-base/whitespace.js index e896072154..01e5198671 100644 --- a/packages/eslint-config-airbnb-base/whitespace.js +++ b/packages/eslint-config-airbnb-base/whitespace.js @@ -51,5 +51,11 @@ if (CLIEngine) { const path = require('path'); const { execSync } = require('child_process'); - module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js')))); + // NOTE: ESLint adds runtime statistics to the output (so it's no longer JSON) if TIMING is set + module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js'), { + env: { + ...process.env, + TIMING: undefined, + } + }))); } diff --git a/packages/eslint-config-airbnb/README.md b/packages/eslint-config-airbnb/README.md index 3b3f43196d..e18088143a 100644 --- a/packages/eslint-config-airbnb/README.md +++ b/packages/eslint-config-airbnb/README.md @@ -58,6 +58,15 @@ If you don't need React, see [eslint-config-airbnb-base](https://npmjs.com/eslin 2. Add `"extends": "airbnb"` to your `.eslintrc` +> **Note**: ESLint only lints `.js` files by default. + If your project uses `.jsx` (or `.tsx` with TypeScript), you need to pass extensions to the CLI: + + ```sh + eslint . --ext .js, .jsx, .mjs + ``` + + Without this, JSX-related rules will not apply to `.jsx` files. + ### eslint-config-airbnb/hooks This entry point enables the linting rules for React hooks (requires v16.8+). To use, add `"extends": ["airbnb", "airbnb/hooks"]` to your `.eslintrc`. diff --git a/packages/eslint-config-airbnb/package.json b/packages/eslint-config-airbnb/package.json index 2b18a55f64..c36359ea7c 100644 --- a/packages/eslint-config-airbnb/package.json +++ b/packages/eslint-config-airbnb/package.json @@ -69,27 +69,27 @@ "eslint-config-airbnb-base": "^15.0.0" }, "devDependencies": { - "@babel/runtime": "^7.23.9", + "@babel/runtime": "^7.25.6", "babel-preset-airbnb": "^4.5.0", "babel-tape-runner": "^3.0.0", "eclint": "^2.8.1", "eslint": "^7.32.0 || ^8.2.0", "eslint-find-rules": "^4.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.36.1", + "eslint-plugin-react-hooks": "^5.1.0", "in-publish": "^2.0.1", "react": ">= 0.13.0", "safe-publish-latest": "^2.0.0", - "tape": "^5.7.5" + "tape": "^5.9.0" }, "peerDependencies": { "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0" + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.36.1", + "eslint-plugin-react-hooks": "^5.1.0" }, "engines": { "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" diff --git a/packages/eslint-config-airbnb/rules/react.js b/packages/eslint-config-airbnb/rules/react.js index b5ccc6ccf2..c4d29e0b39 100644 --- a/packages/eslint-config-airbnb/rules/react.js +++ b/packages/eslint-config-airbnb/rules/react.js @@ -583,17 +583,23 @@ module.exports = { // TODO: semver-major, enable 'react/jsx-no-leaked-render': 'off', - // https://github.com/jsx-eslint/eslint-plugin-react/blob/66b58dd4864678eb869a7bf434c72ff7ac530eb1/docs/rules/no-object-type-as-default-prop.md // https://github.com/jsx-eslint/eslint-plugin-react/blob/66b58dd4864678eb869a7bf434c72ff7ac530eb1/docs/rules/no-object-type-as-default-prop.md // TODO: semver-major, enable 'react/no-object-type-as-default-prop': 'off', - // https://github.com/jsx-eslint/eslint-plugin-react/blob/66b58dd4864678eb869a7bf434c72ff7ac530eb1/docs/rules/sort-default-props.md // https://github.com/jsx-eslint/eslint-plugin-react/blob/66b58dd4864678eb869a7bf434c72ff7ac530eb1/docs/rules/sort-default-props.md // TODO: semver-major, enable? 'react/sort-default-props': ['off', { ignoreCase: false }], + + // https://github.com/jsx-eslint/eslint-plugin-react/blob/9668ee0762acd5c23f53cd3a372e2d8d9563944d/docs/rules/forward-ref-uses-ref.md + // TODO: semver-major, enable + 'react/forward-ref-uses-ref': 'off', + + // https://github.com/jsx-eslint/eslint-plugin-react/blob/9668ee0762acd5c23f53cd3a372e2d8d9563944d/docs/rules/jsx-props-no-spread-multi.md + // TODO: semver-major, enable + 'react/jsx-props-no-spread-multi': 'off', }, settings: { diff --git a/packages/eslint-config-airbnb/whitespace.js b/packages/eslint-config-airbnb/whitespace.js index e896072154..01e5198671 100644 --- a/packages/eslint-config-airbnb/whitespace.js +++ b/packages/eslint-config-airbnb/whitespace.js @@ -51,5 +51,11 @@ if (CLIEngine) { const path = require('path'); const { execSync } = require('child_process'); - module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js')))); + // NOTE: ESLint adds runtime statistics to the output (so it's no longer JSON) if TIMING is set + module.exports = JSON.parse(String(execSync(path.join(__dirname, 'whitespace-async.js'), { + env: { + ...process.env, + TIMING: undefined, + } + }))); } diff --git a/react/README.md b/react/README.md index a590a19672..f61602d161 100644 --- a/react/README.md +++ b/react/README.md @@ -350,7 +350,7 @@ This style guide is mostly based on the standards that are currently prevalent i Me waving hello ``` - - Use only valid, non-abstract [ARIA roles](https://www.w3.org/TR/wai-aria/#usage_intro). eslint: [`jsx-a11y/aria-role`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md) + - Use only valid, non-abstract [ARIA roles](https://www.w3.org/TR/wai-aria/#usage). eslint: [`jsx-a11y/aria-role`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md) ```jsx // bad - not an ARIA role