Repository: jsx-eslint/eslint-plugin-react Branch: master Commit: 9af88453df2c Files: 425 Total size: 3.4 MB Directory structure: gitextract_41bugypo/ ├── .editorconfig ├── .eslint-doc-generatorrc.js ├── .eslintrc ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ └── bug_report.yml │ └── workflows/ │ ├── node-18+.yml │ ├── node-minors.yml │ ├── node-pretest.yml │ ├── npm-publish.yml │ ├── rebase.yml │ ├── release.yml │ ├── require-allow-edits.yml │ ├── smoke-test.yml │ └── type-check.yml ├── .gitignore ├── .markdownlint.json ├── .markdownlintignore ├── .npmrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── build.tsconfig.json ├── configs/ │ ├── all.js │ ├── jsx-runtime.js │ └── recommended.js ├── docs/ │ └── rules/ │ ├── async-server-action.md │ ├── boolean-prop-naming.md │ ├── button-has-type.md │ ├── checked-requires-onchange-or-readonly.md │ ├── default-props-match-prop-types.md │ ├── destructuring-assignment.md │ ├── display-name.md │ ├── forbid-component-props.md │ ├── forbid-dom-props.md │ ├── forbid-elements.md │ ├── forbid-foreign-prop-types.md │ ├── forbid-prop-types.md │ ├── forward-ref-uses-ref.md │ ├── function-component-definition.md │ ├── hook-use-state.md │ ├── iframe-missing-sandbox.md │ ├── jsx-boolean-value.md │ ├── jsx-child-element-spacing.md │ ├── jsx-closing-bracket-location.md │ ├── jsx-closing-tag-location.md │ ├── jsx-curly-brace-presence.md │ ├── jsx-curly-newline.md │ ├── jsx-curly-spacing.md │ ├── jsx-equals-spacing.md │ ├── jsx-filename-extension.md │ ├── jsx-first-prop-new-line.md │ ├── jsx-fragments.md │ ├── jsx-handler-names.md │ ├── jsx-indent-props.md │ ├── jsx-indent.md │ ├── jsx-key.md │ ├── jsx-max-depth.md │ ├── jsx-max-props-per-line.md │ ├── jsx-newline.md │ ├── jsx-no-bind.md │ ├── jsx-no-comment-textnodes.md │ ├── jsx-no-constructed-context-values.md │ ├── jsx-no-duplicate-props.md │ ├── jsx-no-leaked-render.md │ ├── jsx-no-literals.md │ ├── jsx-no-script-url.md │ ├── jsx-no-target-blank.md │ ├── jsx-no-undef.md │ ├── jsx-no-useless-fragment.md │ ├── jsx-one-expression-per-line.md │ ├── jsx-pascal-case.md │ ├── jsx-props-no-multi-spaces.md │ ├── jsx-props-no-spread-multi.md │ ├── jsx-props-no-spreading.md │ ├── jsx-sort-default-props.md │ ├── jsx-sort-props.md │ ├── jsx-space-before-closing.md │ ├── jsx-tag-spacing.md │ ├── jsx-uses-react.md │ ├── jsx-uses-vars.md │ ├── jsx-wrap-multilines.md │ ├── no-access-state-in-setstate.md │ ├── no-adjacent-inline-elements.md │ ├── no-array-index-key.md │ ├── no-arrow-function-lifecycle.md │ ├── no-children-prop.md │ ├── no-danger-with-children.md │ ├── no-danger.md │ ├── no-deprecated.md │ ├── no-did-mount-set-state.md │ ├── no-did-update-set-state.md │ ├── no-direct-mutation-state.md │ ├── no-find-dom-node.md │ ├── no-invalid-html-attribute.md │ ├── no-is-mounted.md │ ├── no-multi-comp.md │ ├── no-namespace.md │ ├── no-object-type-as-default-prop.md │ ├── no-redundant-should-component-update.md │ ├── no-render-return-value.md │ ├── no-set-state.md │ ├── no-string-refs.md │ ├── no-this-in-sfc.md │ ├── no-typos.md │ ├── no-unescaped-entities.md │ ├── no-unknown-property.md │ ├── no-unsafe.md │ ├── no-unstable-nested-components.md │ ├── no-unused-class-component-methods.md │ ├── no-unused-prop-types.md │ ├── no-unused-state.md │ ├── no-will-update-set-state.md │ ├── prefer-es6-class.md │ ├── prefer-exact-props.md │ ├── prefer-read-only-props.md │ ├── prefer-stateless-function.md │ ├── prop-types.md │ ├── react-in-jsx-scope.md │ ├── require-default-props.md │ ├── require-optimization.md │ ├── require-render-return.md │ ├── self-closing-comp.md │ ├── sort-comp.md │ ├── sort-default-props.md │ ├── sort-prop-types.md │ ├── state-in-constructor.md │ ├── static-property-placement.md │ ├── style-prop-object.md │ └── void-dom-elements-no-children.md ├── index.js ├── lib/ │ ├── rules/ │ │ ├── async-server-action.js │ │ ├── boolean-prop-naming.js │ │ ├── button-has-type.js │ │ ├── checked-requires-onchange-or-readonly.js │ │ ├── default-props-match-prop-types.js │ │ ├── destructuring-assignment.js │ │ ├── display-name.js │ │ ├── forbid-component-props.js │ │ ├── forbid-dom-props.js │ │ ├── forbid-elements.js │ │ ├── forbid-foreign-prop-types.js │ │ ├── forbid-prop-types.js │ │ ├── forward-ref-uses-ref.js │ │ ├── function-component-definition.js │ │ ├── hook-use-state.js │ │ ├── iframe-missing-sandbox.js │ │ ├── index.js │ │ ├── jsx-boolean-value.js │ │ ├── jsx-child-element-spacing.js │ │ ├── jsx-closing-bracket-location.js │ │ ├── jsx-closing-tag-location.js │ │ ├── jsx-curly-brace-presence.js │ │ ├── jsx-curly-newline.js │ │ ├── jsx-curly-spacing.js │ │ ├── jsx-equals-spacing.js │ │ ├── jsx-filename-extension.js │ │ ├── jsx-first-prop-new-line.js │ │ ├── jsx-fragments.js │ │ ├── jsx-handler-names.js │ │ ├── jsx-indent-props.js │ │ ├── jsx-indent.js │ │ ├── jsx-key.js │ │ ├── jsx-max-depth.js │ │ ├── jsx-max-props-per-line.js │ │ ├── jsx-newline.js │ │ ├── jsx-no-bind.js │ │ ├── jsx-no-comment-textnodes.js │ │ ├── jsx-no-constructed-context-values.js │ │ ├── jsx-no-duplicate-props.js │ │ ├── jsx-no-leaked-render.js │ │ ├── jsx-no-literals.js │ │ ├── jsx-no-script-url.js │ │ ├── jsx-no-target-blank.js │ │ ├── jsx-no-undef.js │ │ ├── jsx-no-useless-fragment.js │ │ ├── jsx-one-expression-per-line.js │ │ ├── jsx-pascal-case.js │ │ ├── jsx-props-no-multi-spaces.js │ │ ├── jsx-props-no-spread-multi.js │ │ ├── jsx-props-no-spreading.js │ │ ├── jsx-sort-default-props.js │ │ ├── jsx-sort-props.js │ │ ├── jsx-space-before-closing.js │ │ ├── jsx-tag-spacing.js │ │ ├── jsx-uses-react.js │ │ ├── jsx-uses-vars.js │ │ ├── jsx-wrap-multilines.js │ │ ├── no-access-state-in-setstate.js │ │ ├── no-adjacent-inline-elements.js │ │ ├── no-array-index-key.js │ │ ├── no-arrow-function-lifecycle.js │ │ ├── no-children-prop.js │ │ ├── no-danger-with-children.js │ │ ├── no-danger.js │ │ ├── no-deprecated.js │ │ ├── no-did-mount-set-state.js │ │ ├── no-did-update-set-state.js │ │ ├── no-direct-mutation-state.js │ │ ├── no-find-dom-node.js │ │ ├── no-invalid-html-attribute.js │ │ ├── no-is-mounted.js │ │ ├── no-multi-comp.js │ │ ├── no-namespace.js │ │ ├── no-object-type-as-default-prop.js │ │ ├── no-redundant-should-component-update.js │ │ ├── no-render-return-value.js │ │ ├── no-set-state.js │ │ ├── no-string-refs.js │ │ ├── no-this-in-sfc.js │ │ ├── no-typos.js │ │ ├── no-unescaped-entities.js │ │ ├── no-unknown-property.js │ │ ├── no-unsafe.js │ │ ├── no-unstable-nested-components.js │ │ ├── no-unused-class-component-methods.js │ │ ├── no-unused-prop-types.js │ │ ├── no-unused-state.js │ │ ├── no-will-update-set-state.js │ │ ├── prefer-es6-class.js │ │ ├── prefer-exact-props.js │ │ ├── prefer-read-only-props.js │ │ ├── prefer-stateless-function.js │ │ ├── prop-types.js │ │ ├── react-in-jsx-scope.js │ │ ├── require-default-props.js │ │ ├── require-optimization.js │ │ ├── require-render-return.js │ │ ├── self-closing-comp.js │ │ ├── sort-comp.js │ │ ├── sort-default-props.js │ │ ├── sort-prop-types.js │ │ ├── state-in-constructor.js │ │ ├── static-property-placement.js │ │ ├── style-prop-object.js │ │ └── void-dom-elements-no-children.js │ ├── types.d.ts │ └── util/ │ ├── Components.js │ ├── annotations.js │ ├── ast.js │ ├── componentUtil.js │ ├── defaultProps.js │ ├── docsUrl.js │ ├── error.js │ ├── eslint.js │ ├── getTokenBeforeClosingBracket.js │ ├── isCreateContext.js │ ├── isCreateElement.js │ ├── isDestructuredFromPragmaImport.js │ ├── isFirstLetterCapitalized.js │ ├── jsx.js │ ├── lifecycleMethods.js │ ├── linkComponents.js │ ├── log.js │ ├── makeNoMethodSetStateRule.js │ ├── message.js │ ├── pragma.js │ ├── propTypes.js │ ├── propTypesSort.js │ ├── propWrapper.js │ ├── props.js │ ├── report.js │ ├── usedPropTypes.js │ ├── variable.js │ └── version.js ├── package.json ├── test/ │ ├── eslint-remote-tester.config.js │ └── mocha.opts ├── test-published-types/ │ ├── .npmrc │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── tests/ │ ├── fixtures/ │ │ ├── flat-config/ │ │ │ ├── config-all/ │ │ │ │ ├── eslint.config-deep.js │ │ │ │ ├── eslint.config-root.js │ │ │ │ └── test.jsx │ │ │ ├── config-jsx-runtime/ │ │ │ │ ├── eslint.config-deep.js │ │ │ │ ├── eslint.config-root.js │ │ │ │ └── test.jsx │ │ │ ├── config-recommended/ │ │ │ │ ├── eslint.config-deep.js │ │ │ │ ├── eslint.config-root.js │ │ │ │ └── test.jsx │ │ │ ├── plugin/ │ │ │ │ ├── eslint.config.js │ │ │ │ └── test.jsx │ │ │ └── plugin-and-config/ │ │ │ ├── eslint.config-deep.js │ │ │ ├── eslint.config-root.js │ │ │ └── test.jsx │ │ └── version/ │ │ ├── detect-version/ │ │ │ ├── detect-version-child/ │ │ │ │ ├── node_modules/ │ │ │ │ │ ├── flow-bin/ │ │ │ │ │ │ └── package.json │ │ │ │ │ └── react/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ └── test.js │ │ │ ├── node_modules/ │ │ │ │ ├── flow-bin/ │ │ │ │ │ └── package.json │ │ │ │ └── react/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── test.js │ │ ├── detect-version-missing/ │ │ │ ├── node_modules/ │ │ │ │ └── react/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── test.js │ │ └── detect-version-sibling/ │ │ ├── node_modules/ │ │ │ ├── flow-bin/ │ │ │ │ └── package.json │ │ │ └── react/ │ │ │ ├── index.js │ │ │ └── package.json │ │ └── test.js │ ├── flat-config.js │ ├── helpers/ │ │ ├── getESLintCoreRule.js │ │ ├── getRuleDefiner.js │ │ ├── parsers.js │ │ └── ruleTester.js │ ├── index.js │ ├── lib/ │ │ └── rules/ │ │ ├── async-server-action.js │ │ ├── boolean-prop-naming.js │ │ ├── button-has-type.js │ │ ├── checked-requires-onchange-or-readonly.js │ │ ├── default-props-match-prop-types.js │ │ ├── destructuring-assignment.js │ │ ├── display-name.js │ │ ├── forbid-component-props.js │ │ ├── forbid-dom-props.js │ │ ├── forbid-elements.js │ │ ├── forbid-foreign-prop-types.js │ │ ├── forbid-prop-types.js │ │ ├── forward-ref-uses-ref.js │ │ ├── function-component-definition.js │ │ ├── hook-use-state.js │ │ ├── iframe-missing-sandbox.js │ │ ├── jsx-boolean-value.js │ │ ├── jsx-child-element-spacing.js │ │ ├── jsx-closing-bracket-location.js │ │ ├── jsx-closing-tag-location.js │ │ ├── jsx-curly-brace-presence.js │ │ ├── jsx-curly-newline.js │ │ ├── jsx-curly-spacing.js │ │ ├── jsx-equals-spacing.js │ │ ├── jsx-filename-extension.js │ │ ├── jsx-first-prop-new-line.js │ │ ├── jsx-fragments.js │ │ ├── jsx-handler-names.js │ │ ├── jsx-indent-props.js │ │ ├── jsx-indent.js │ │ ├── jsx-key.js │ │ ├── jsx-max-depth.js │ │ ├── jsx-max-props-per-line.js │ │ ├── jsx-newline.js │ │ ├── jsx-no-bind.js │ │ ├── jsx-no-comment-textnodes.js │ │ ├── jsx-no-constructed-context-values.js │ │ ├── jsx-no-duplicate-props.js │ │ ├── jsx-no-leaked-render.js │ │ ├── jsx-no-literals.js │ │ ├── jsx-no-script-url.js │ │ ├── jsx-no-target-blank.js │ │ ├── jsx-no-undef.js │ │ ├── jsx-no-useless-fragment.js │ │ ├── jsx-one-expression-per-line.js │ │ ├── jsx-pascal-case.js │ │ ├── jsx-props-no-multi-spaces.js │ │ ├── jsx-props-no-spread-multi.js │ │ ├── jsx-props-no-spreading.js │ │ ├── jsx-sort-default-props.js │ │ ├── jsx-sort-props.js │ │ ├── jsx-space-before-closing.js │ │ ├── jsx-tag-spacing.js │ │ ├── jsx-uses-react.js │ │ ├── jsx-uses-vars.js │ │ ├── jsx-wrap-multilines.js │ │ ├── no-access-state-in-setstate.js │ │ ├── no-adjacent-inline-elements.js │ │ ├── no-array-index-key.js │ │ ├── no-arrow-function-lifecycle.js │ │ ├── no-children-prop.js │ │ ├── no-danger-with-children.js │ │ ├── no-danger.js │ │ ├── no-deprecated.js │ │ ├── no-did-mount-set-state.js │ │ ├── no-did-update-set-state.js │ │ ├── no-direct-mutation-state.js │ │ ├── no-find-dom-node.js │ │ ├── no-invalid-html-attribute.js │ │ ├── no-is-mounted.js │ │ ├── no-multi-comp.js │ │ ├── no-namespace.js │ │ ├── no-object-type-as-default-prop.js │ │ ├── no-redundant-should-component-update.js │ │ ├── no-render-return-value.js │ │ ├── no-set-state.js │ │ ├── no-string-refs.js │ │ ├── no-this-in-sfc.js │ │ ├── no-typos.js │ │ ├── no-unescaped-entities.js │ │ ├── no-unknown-property.js │ │ ├── no-unsafe.js │ │ ├── no-unstable-nested-components.js │ │ ├── no-unused-class-component-methods.js │ │ ├── no-unused-prop-types.js │ │ ├── no-unused-state.js │ │ ├── no-will-update-set-state.js │ │ ├── prefer-es6-class.js │ │ ├── prefer-exact-props.js │ │ ├── prefer-read-only-props.js │ │ ├── prefer-stateless-function.js │ │ ├── prop-types.js │ │ ├── react-in-jsx-scope.js │ │ ├── require-default-props.js │ │ ├── require-optimization.js │ │ ├── require-render-return.js │ │ ├── self-closing-comp.js │ │ ├── sort-comp.js │ │ ├── sort-default-props.js │ │ ├── sort-prop-types.js │ │ ├── state-in-constructor.js │ │ ├── static-property-placement.js │ │ ├── style-prop-object.js │ │ └── void-dom-elements-no-children.js │ └── util/ │ ├── .eslintrc │ ├── Components.js │ ├── ast.js │ ├── isFirstLetterCapitalized.js │ ├── jsx.js │ ├── linkComponents.js │ ├── pragma.js │ ├── propWrapper.js │ ├── variable.js │ └── version.js ├── tsconfig.json └── types/ ├── rules/ │ └── jsx-no-literals.d.ts └── string.prototype.repeat/ └── index.d.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true quote_type = single [*.md] trim_trailing_whitespace = false ================================================ FILE: .eslint-doc-generatorrc.js ================================================ /** @type {import('eslint-doc-generator').GenerateOptions} */ const config = { configEmoji: [ ['jsx-runtime', '🏃'], ['recommended', '☑️'], ], ignoreConfig: ['all', 'flat'], urlConfigs: 'https://github.com/jsx-eslint/eslint-plugin-react/#shareable-configs', }; module.exports = config; ================================================ FILE: .eslintrc ================================================ { "root": true, "extends": ["airbnb-base", "plugin:eslint-plugin/recommended"], "plugins": ["eslint-plugin"], "env": { "es6": true, "node": true }, "parserOptions": { "ecmaVersion": 6, "ecmaFeatures": { "jsx": true }, "sourceType": "script", }, "ignorePatterns": [ "coverage/", ".nyc_output/", "test-published-types/", "tests/fixtures/flat-config/", "**/*/*.d.ts", ], "rules": { "comma-dangle": [2, "always-multiline"], "object-shorthand": [2, "always", { "ignoreConstructors": false, "avoidQuotes": false, // this is the override vs airbnb }], "max-len": [2, 140, { "ignoreStrings": true, "ignoreTemplateLiterals": true, "ignoreComments": true, }], "consistent-return": 0, "prefer-destructuring": [2, { "array": false, "object": false }, { "enforceForRenamedProperties": false }], "prefer-object-spread": 0, // until node 8 is required "prefer-rest-params": 0, // until node 6 is required "prefer-spread": 0, // until node 6 is required "function-call-argument-newline": 1, // TODO: enable "function-paren-newline": 0, "no-plusplus": [2, {"allowForLoopAfterthoughts": true}], "no-param-reassign": 1, "no-restricted-syntax": [2, { "selector": "ObjectPattern", "message": "Object destructuring is not compatible with Node v4" }], "strict": [2, "safe"], "valid-jsdoc": [2, { "requireReturn": false, "requireParamDescription": false, "requireReturnDescription": false, }], "eslint-plugin/consistent-output": 0, "eslint-plugin/require-meta-docs-description": [2, { "pattern": "^(Enforce|Require|Disallow)" }], "eslint-plugin/require-meta-schema": 0, "eslint-plugin/require-meta-type": 0 }, "overrides": [ { "files": "tests/**", "rules": { "no-template-curly-in-string": 1, }, }, { "files": "markdown.config.js", "rules": { "no-console": 0, }, }, { "files": ".github/workflows/*.js", "parserOptions": { "ecmaVersion": 2019, }, "rules": { "camelcase": 0, "no-console": 0, "no-restricted-syntax": 0, }, }, ], } ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: [jsx-eslint, ljharb] patreon: # Replace with a single Patreon username open_collective: jsx-eslint # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: npm/eslint-plugin-react community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug Report description: File a bug report title: "[Bug]: " labels: ["bug", "triage"] assignees: [] body: - type: checkboxes attributes: label: Is there an existing issue for this? description: Please search to see if an issue already exists for the bug you encountered. options: - label: I have searched the existing issues and my issue is unique required: true - label: My issue appears in the command-line and not only in the text editor required: true - type: textarea id: Code attributes: label: Description Overview description: A clear and concise description of bug w/ examples placeholder: | Brief description here Show example of your code (as text format), add images/videos/gifs to help explain example and/or Link of repo to where issue is occurring What is happening? / What is the error? What command(s) did you run to reproduce issue? value: | validations: required: true - type: textarea id: expected_behavior attributes: label: Expected Behavior description: A clear and concise description of what you expected to happen. placeholder: | Brief description here Show example of code (as text format), add images/videos/gifs to help explain expected behavior value: | validations: required: true - type: input id: eslint-plugin-react-version attributes: label: eslint-plugin-react version placeholder: v7.31.11 validations: required: true - type: input id: eslint-version attributes: label: eslint version placeholder: v8.28.0 validations: required: true - type: input id: node-version attributes: label: node version placeholder: v8.19.2 validations: required: true ================================================ FILE: .github/workflows/node-18+.yml ================================================ name: 'Tests: node.js (18+)' on: [pull_request, push] jobs: matrix: runs-on: ubuntu-latest outputs: latest: ${{ steps.set-matrix.outputs.requireds }} minors: ${{ steps.set-matrix.outputs.optionals }} steps: - uses: ljharb/actions/node/matrix@main id: set-matrix with: versionsAsRoot: true type: majors preset: '>=18' latest: needs: [matrix] name: 'latest majors' runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: ${{ fromJson(needs.matrix.outputs.latest) }} eslint: - 9 - 8 - 7 - 6 - 5 - 4 - 4.14 # last version without messageId - 3 babel-eslint: - 10 - 9 - 8 typescript-eslint: - 5 - 6 - 7 - 8 exclude: - eslint: 3 babel-eslint: 10 - eslint: 3 typescript-eslint: 5 - eslint: 4 typescript-eslint: 5 - eslint: 4.14 typescript-eslint: 5 - eslint: 5 typescript-eslint: 5 - eslint: 3 typescript-eslint: 6 - eslint: 4 typescript-eslint: 6 - eslint: 4.14 typescript-eslint: 6 - eslint: 5 typescript-eslint: 6 - eslint: 6 typescript-eslint: 6 - eslint: 9 typescript-eslint: 6 - eslint: 3 typescript-eslint: 7 - eslint: 4 typescript-eslint: 7 - eslint: 4.14 typescript-eslint: 7 - eslint: 5 typescript-eslint: 7 - eslint: 6 typescript-eslint: 7 - eslint: 7 typescript-eslint: 7 - eslint: 9 typescript-eslint: 7 - eslint: 3 typescript-eslint: 8 - eslint: 4 typescript-eslint: 8 - eslint: 4.14 typescript-eslint: 8 - eslint: 5 typescript-eslint: 8 - eslint: 6 typescript-eslint: 8 - eslint: 7 typescript-eslint: 8 - eslint: 9 typescript-eslint: 5 - node-version: 19 typescript-eslint: 7 steps: - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' with: node-version: ${{ matrix.node-version }} after_install: | npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.typescript-eslint == 8 && 8.17 || matrix.typescript-eslint }}" "babel-eslint@${{ matrix.babel-eslint }}" env: NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.typescript-eslint >= 6 && 'false' || 'true' }}" - run: npx ls-engines - run: npm run unit-test - uses: codecov/codecov-action@v3.1.5 node: name: 'node 18+' needs: [latest] runs-on: ubuntu-latest steps: - run: 'echo tests completed' ================================================ FILE: .github/workflows/node-minors.yml ================================================ name: 'Tests: node.js (4 - 18)' on: [pull_request, push] jobs: matrix: runs-on: ubuntu-latest outputs: latest: ${{ steps.set-matrix.outputs.requireds }} minors: ${{ steps.set-matrix.outputs.optionals }} steps: - uses: ljharb/actions/node/matrix@main id: set-matrix with: versionsAsRoot: true type: majors preset: '>=4 < 18' latest: needs: [matrix] name: 'latest majors' runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: ${{ fromJson(needs.matrix.outputs.latest) }} eslint: - 8 - 7 - 6 - 5 - 4 - 4.14 # last version without messageId - 3 babel-eslint: - 10 - 9 - 8 exclude: - node-version: 5 babel-eslint: 10 - node-version: 5 babel-eslint: 9 - node-version: 4 babel-eslint: 10 - node-version: 4 babel-eslint: 9 - node-version: 15 eslint: 8 - node-version: 13 eslint: 8 - node-version: 11 eslint: 8 - node-version: 11 eslint: 7 - node-version: 10 eslint: 8 - node-version: 9 eslint: 8 - node-version: 9 eslint: 7 - node-version: 8 eslint: 8 - node-version: 8 eslint: 7 - node-version: 7 eslint: 8 - node-version: 7 eslint: 7 - node-version: 7 eslint: 6 - node-version: 6 eslint: 8 - node-version: 6 eslint: 7 - node-version: 6 eslint: 6 - node-version: 5 eslint: 8 - node-version: 5 eslint: 7 - node-version: 5 eslint: 6 - node-version: 5 eslint: 5 - node-version: 4 eslint: 8 - node-version: 4 eslint: 7 - node-version: 4 eslint: 6 - node-version: 4 eslint: 5 steps: - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main name: 'nvm install ${{ matrix.node-version }} && npm install' with: node-version: ${{ matrix.node-version }} after_install: | npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 18 && matrix.eslint >= 8 && '8.17' || (matrix.node-version >= 16 && matrix.eslint >= 7 && '6' || (matrix.node-version >= 14 && '5' || (matrix.node-version >= 12 && '4' || (matrix.node-version >= 10 && '4.0' || (matrix.node-version >= 8 && '3' || '2'))))) }}" "babel-eslint@${{ matrix.babel-eslint }}" skip-ls-check: ${{ matrix.node-version < 10 && true || false }} env: NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.node-version >= 16 && matrix.eslint >= 7 && 'false' || 'true' }}" - run: npx ls-engines if: ${{ matrix.node-version >= 12 }} - run: npm run unit-test - uses: codecov/codecov-action@v3.1.5 node: name: 'node 4 - 17' needs: [latest] runs-on: ubuntu-latest steps: - run: 'echo tests completed' ================================================ FILE: .github/workflows/node-pretest.yml ================================================ name: 'Tests: pretest/posttest' on: [pull_request, push] jobs: pretest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: node-version: 'lts/*' - run: npm run pretest posttest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: node-version: 'lts/*' env: NPM_CONFIG_LEGACY_PEER_DEPS: true - run: npx ls-engines - run: echo 'legacy-peer-deps=true' >> .npmrc - run: npm run posttest ================================================ FILE: .github/workflows/npm-publish.yml ================================================ name: Publish Package to npm on: workflow_dispatch: inputs: tag: description: "Tag to publish" required: true permissions: contents: read jobs: check-version: runs-on: ubuntu-latest outputs: is-new-version: ${{ steps.cpv.outputs.is-new-version }} steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.inputs.tag }} - name: Validate semver pattern run: npx semver ${{ inputs.tag }} - name: Check package version id: cpv uses: PostHog/check-package-version@v2 - name: Validate package version uses: actions/github-script@v6 with: script: | const isNewVersion = `${{ steps.cpv.outputs.is-new-version }}`; if (isNewVersion === 'true') { console.log(`Version ${context.payload.inputs.tag} has not been published yet`); } else { core.setFailed(`Version ${context.payload.inputs.tag} is already published`); } check-status: needs: check-version if: needs.check-version.outputs.is-new-version == 'true' runs-on: ubuntu-latest steps: - name: Verify checks passed uses: actions/github-script@v6 with: result-encoding: string retries: 3 script: | console.log(process.cwd()); const ref = context.payload.inputs.tag; console.log(`Checking status checks for ${ref}`); const { owner, repo } = context.repo; const { default_branch: branch } = context.payload.repository; const branchData = github.rest.repos.getBranch({ owner, repo, branch }); const { data: { check_suites: checkSuites } } = await github.rest.checks.listSuitesForRef({ owner, repo, ref }); const pending = checkSuites.filter(({ status }) => status !== 'completed') if (pending.length > 0) { core.setFailed(`Some workflows for ${context.payload.inputs.tag} are still in-progress`); pending.forEach(({ pull_requests, ...x }) => { core.debug(JSON.stringify(x)); }); } const result = await Promise.all( (await branchData).data.protection.required_status_checks.checks.map(({ context: check_name }) => ( github.rest.checks.listForRef({ owner, repo, ref, check_name, }) )), ); const checkRuns = result.flatMap(({ data: { check_runs } }) => check_runs); checkRuns.forEach(({ name, status, conclusion }) => { if (status !== 'completed' || conclusion !== 'success') { console.log(`${name} check failed`); core.setFailed(`Required status check ${name} did not succeed`); } console.log(`${name} check passed`); }); publish: needs: [check-status] runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: step-security/harden-runner@v2 with: egress-policy: block allowed-endpoints: > github.com:443 nodejs.org:443 prod.api.stepsecurity.io:443 registry.npmjs.org:443 raw.githubusercontent.com:443 - uses: actions/checkout@v4 with: ref: ${{ github.event.inputs.tag }} - uses: ljharb/actions/node/install@main name: "nvm install lts/* && npm install" with: node-version: "lts/*" env: NPM_CONFIG_LEGACY_PEER_DEPS: true - run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> .npmrc - run: npm publish --dry-run - uses: step-security/wait-for-secrets@v1 id: wait-for-secrets with: slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} secrets: | OTP: name: 'OTP to publish package' description: 'OTP from authenticator app' - run: npm publish --access public --otp ${{ steps.wait-for-secrets.outputs.OTP }} ================================================ FILE: .github/workflows/rebase.yml ================================================ name: Automatic Rebase on: [pull_request_target] jobs: _: uses: ljharb/actions/.github/workflows/rebase.yml@main secrets: token: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: push: tags: - "v*.*.*" jobs: release: if: github.event.repository.fork == false runs-on: ubuntu-latest permissions: contents: write steps: - uses: step-security/harden-runner@v2 with: allowed-endpoints: api.github.com:443 github.com:443 raw.githubusercontent.com:443 nodejs.org:443 registry.npmjs.org:443 - name: Get version from tag id: tag_name run: echo "current_version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" shell: bash - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main with: node-version: node skip-install: true skip-ls-check: true - uses: mindsers/changelog-reader-action@v2 id: changelog_reader with: version: ${{ steps.tag_name.outputs.current_version }} - name: Get common links from changelog id: changelog run: | # Parse the changelog for common links _links="$(egrep '^\[.*]:.+' ${GITHUB_WORKSPACE:-.}/CHANGELOG.md | sort -u)" _links="${_links//'%'/'%25'}" # _links="${_links//$'\n'/'%0A'}" _links="${_links//$'\r'/'%0D'}" # Set output 'links' to $_links DELIMITER=$(uuidgen) echo "links<<${DELIMITER}" >> "${GITHUB_OUTPUT}" echo "$_links" >> "${GITHUB_OUTPUT}" echo "${DELIMITER}" >> "${GITHUB_OUTPUT}" - name: 'concat data > tmp.md' run: | cat << 'EOF' > tmp.md ${{ steps.changelog_reader.outputs.changes }} ${{ steps.changelog.outputs.links }} EOF - run: cat tmp.md - id: prune-footnotes run: | DELIMITER=$(uuidgen) echo "body<<${DELIMITER}" >> "${GITHUB_OUTPUT}" npx gfm-footnotes -i tmp.md >> "${GITHUB_OUTPUT}" echo "${DELIMITER}" >> "${GITHUB_OUTPUT}" - uses: softprops/action-gh-release@v2 with: body: | ${{ steps.prune-footnotes.outputs.body }} ================================================ FILE: .github/workflows/require-allow-edits.yml ================================================ name: Require “Allow Edits” on: [pull_request_target] jobs: _: name: "Require “Allow Edits”" runs-on: ubuntu-latest steps: - uses: ljharb/require-allow-edits@main ================================================ FILE: .github/workflows/smoke-test.yml ================================================ name: Smoke test on: schedule: - cron: '0 0 * * SUN' workflow_dispatch: jobs: smoke-test: if: ${{ github.repository == 'jsx-eslint/eslint-plugin-react' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: node-version: 'lts/*' skip-ls-check: true - run: | npm link npm link eslint-plugin-react - uses: AriPerkkio/eslint-remote-tester-run-action@v4 with: issue-title: 'Results of weekly scheduled smoke test' issue-label: 'smoke-test' eslint-remote-tester-config: test/eslint-remote-tester.config.js ================================================ FILE: .github/workflows/type-check.yml ================================================ name: "Types: check published types" on: [pull_request, push] permissions: contents: read jobs: test: name: TS ${{ matrix.ts_version }}, "${{ matrix.ts_lib }}" runs-on: ubuntu-latest strategy: fail-fast: false matrix: ts_version: # The official ESLint types are not compatible with TS 3.9 # - 3.9 - '4.0' - 4.1 - 4.2 - 4.3 - 4.4 - 4.5 - '5.0' - 5.5 - 5.6 ts_lib: - es2015 - es2015,dom - es2020 - esnext steps: - uses: actions/checkout@v4 with: persist-credentials: false show-progress: false - uses: ljharb/actions/node/install@main name: 'nvm install lts/* && npm install' with: node-version: 'lts/*' skip-ls-check: true - name: build types run: npm run build-types # Pack the lib into a tarball so that when we install the lib later in the # test-published-types directory, it's only install `dependencies` of the # lib. - name: pack the lib run: npm pack --pack-destination /tmp/ - name: find the packed lib run: echo "ESLINT_PLUGIN_REACT_PATH=$(ls /tmp/eslint-plugin-react*.tgz | tail -n 1)" >> $GITHUB_ENV - name: show the path to the packed lib run: echo "$ESLINT_PLUGIN_REACT_PATH" - name: npm install working directory run: npm install working-directory: test-published-types - name: install eslint-plugin-react and typescript version ${{ matrix.ts_version }} run: npm install --no-save "$ESLINT_PLUGIN_REACT_PATH" typescript@${{ matrix.ts_version }} working-directory: test-published-types - name: show installed typescript version run: npm list typescript --depth=0 working-directory: test-published-types - name: show installed eslint-plugin-react version run: npm list eslint-plugin-react --depth=0 working-directory: test-published-types - name: check types with lib "${{ matrix.ts_lib }}" run: npx tsc --lib ${{ matrix.ts_lib }} working-directory: test-published-types ================================================ FILE: .gitignore ================================================ # gitignore lib-cov *.seed *.log *.csv *.dat *.out *.pid *.gz *.sublime-project *.sublime-workspace pids logs reports coverage .nyc_output/ build node_modules !tests/**/node_modules npm-debug.log sftp-config.json eslint-remote-tester-results # Only apps should have lockfiles npm-shrinkwrap≥json package-lock.json yarn.lock .npmignore /lib/**/*.d.ts /lib/**/*.d.ts.map !/lib/types.d.ts /index.d.ts /index.d.ts.map ================================================ FILE: .markdownlint.json ================================================ { "line-length": false, "no-inline-html": false, "no-hard-tabs": { "spaces_per_tab": 2 }, "ul-style": { "style": "dash" } } ================================================ FILE: .markdownlintignore ================================================ CHANGELOG.md LICENSE node_modules ================================================ FILE: .npmrc ================================================ package-lock=false ================================================ FILE: CHANGELOG.md ================================================ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com). ## Unreleased ### Added * [`async-server-action`]: add rule ([#3729][] @jorgezreik) * [`jsx-props-no-multi-spaces`]: improve autofix for multi-line ([#3930][] @justisb) * [`jsx-handler-names`]: support namespaced component names ([#3943][] @takuji) * [`jsx-no-leaked-render`]: add `ignoreAttributes` option ([#3441][] @aleclarson) * [`jsx-sort-props`]: add `sortFirst` option ([#3965][] @loderunner) * [`jsx-no-literals`]: add `restrictedAttributes` option ([#3950][] @ushiboy) * [`forbid-dom-props`]: Add `disallowedValues` option for forbidden props ([#3877][] @makxca) ### Fixed * [`no-unknown-property`]: allow `onLoad` on `body` ([#3923][] @DerekStapleton) * [`no-unknown-property`]: allow `closedby` on `dialog` ([#3980][] @ljharb) * [`no-unknown-property`]: add `onScrollEnd` and `onScrollEndCapture` events as known properties ([#3958][] @xfeeefeee) * Remove extra space from CLI warning ([#3942][] @junaidkbr) * [`jsx-key`]: detect missing keys in return statement with ternary operator ([#3928][] @hyeonbinHur) * [`jsx-key`]: detect missing keys in logical expressions ([#3986][] @yalperg) * [`display-name`]: avoid false positive when React is shadowed ([#3926][] @hyeonbinHur) * [`no-unused-prop-types`]: detect used props in nested components ([#3955][] @avaice) ### Changed * [Docs] [`no-array-index-key`]: add template literal examples ([#3978][] @akahoshi1421) [#3986]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3986 [#3978]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3978 [#3958]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3958 [#3980]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3980 [#3965]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3965 [#3955]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3955 [#3950]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3950 [#3943]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3943 [#3942]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3942 [#3930]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3930 [#3928]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3928 [#3926]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3926 [#3923]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3923 [#3877]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3877 [#3729]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3729 [#3441]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3441 ## [7.37.5] - 2025.04.03 ### Fixed * [`no-unknown-property`]: allow shadow root attrs on `