diff --git a/.editorconfig b/.editorconfig index 4a7ea3036a..319299684a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +quote_type = single [*.md] trim_trailing_whitespace = false diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js new file mode 100644 index 0000000000..81c443bebb --- /dev/null +++ b/.eslint-doc-generatorrc.js @@ -0,0 +1,11 @@ +/** @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; diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index bf3f05d057..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/** -reports/** diff --git a/.eslintrc b/.eslintrc index 1bc1bedcb6..894df7caa9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,159 +1,85 @@ { - "env": { - "node": true + "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, + }, }, - ecmaFeatures: { - jsx: true + { + "files": "markdown.config.js", + "rules": { + "no-console": 0, + }, }, - "globals": { - }, - "plugins": [ - ], - "rules": { - // Possible Errors - "comma-dangle": [2, "never"], - "no-cond-assign": 2, - "no-console": 2, - "no-constant-condition": 2, - "no-control-regex": 2, - "no-debugger": 2, - "no-dupe-keys": 2, - "no-empty": 2, - "no-empty-class": 2, - "no-ex-assign": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": 0, - "no-extra-semi": 2, - "no-func-assign": 2, - "no-inner-declarations": 2, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-negated-in-lhs": 2, - "no-obj-calls": 2, - "no-regex-spaces": 2, - "no-reserved-keys": 0, - "no-sparse-arrays": 2, - "no-unreachable": 2, - "use-isnan": 2, - "valid-jsdoc": 0, - "valid-typeof": 2, - // Best Practices - "block-scoped-var": 2, - "complexity": 0, - "consistent-return": 2, - "curly": 2, - "default-case": 2, - "dot-notation": 2, - "eqeqeq": 2, - "guard-for-in": 2, - "no-alert": 2, - "no-caller": 2, - "no-div-regex": 2, - "no-else-return": 2, - "no-empty-label": 2, - "no-eq-null": 2, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-implied-eval": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-multi-spaces": 2, - "no-multi-str": 0, - "no-native-reassign": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-wrappers": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-process-env": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-return-assign": 2, - "no-script-url": 2, - "no-self-compare": 2, - "no-sequences": 2, - "no-unused-expressions": 2, - "no-void": 0, - "no-warning-comments": 2, - "no-with": 2, - "radix": 2, - "vars-on-top": 0, - "wrap-iife": 2, - "yoda": 2, - // Strict Mode - "strict": [2, "global"], - // Variables - "no-catch-shadow": 2, - "no-delete-var": 2, - "no-label-var": 2, - "no-shadow": 2, - "no-shadow-restricted-names": 2, - "no-undef": 2, - "no-undef-init": 2, - "no-undefined": 2, - "no-unused-vars": 2, - "no-use-before-define": 2, - // Stylistic Issues - "indent": [2, 2, { - "indentSwitchCase": true - }], - "brace-style": 2, + { + "files": ".github/workflows/*.js", + "parserOptions": { + "ecmaVersion": 2019, + }, + "rules": { "camelcase": 0, - "comma-spacing": 2, - "comma-style": 2, - "consistent-this": 0, - "eol-last": 2, - "func-names": 0, - "func-style": 0, - "key-spacing": [2, { - "beforeColon": false, - "afterColon": true - }], - "max-nested-callbacks": 0, - "new-cap": 2, - "new-parens": 2, - "no-array-constructor": 2, - "no-inline-comments": 0, - "no-lonely-if": 2, - "no-mixed-spaces-and-tabs": 2, - "no-nested-ternary": 2, - "no-new-object": 2, - "semi-spacing": [2, { - "before": false, - "after": true - }], - "no-spaced-func": 2, - "no-ternary": 0, - "no-trailing-spaces": 2, - "no-multiple-empty-lines": 2, - "no-underscore-dangle": 0, - "no-wrap-func": 2, - "one-var": 0, - "operator-assignment": [2, "always"], - "padded-blocks": 0, - "quotes": [2, "single"], - "quote-props": [2, "as-needed"], - "semi": [2, "always"], - "sort-vars": [2, "ignoreCase"], - "space-after-keywords": 2, - "space-before-blocks": 2, - "space-in-brackets": 2, - "space-in-parens": 2, - "space-infix-ops": 2, - "space-return-throw-case": 2, - "space-unary-ops": 2, - "spaced-line-comment": 2, - "wrap-regex": 0, - // Legacy - "max-depth": 0, - "max-len": [2, 120], - "max-params": 0, - "max-statements": 0, - "no-plusplus": 0 - } + "no-console": 0, + "no-restricted-syntax": 0, + }, + }, + ], } diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..f5c126d74f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# 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'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..1192d4a3c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,81 @@ +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 diff --git a/.github/workflows/node-18+.yml b/.github/workflows/node-18+.yml new file mode 100644 index 0000000000..5a48b15a88 --- /dev/null +++ b/.github/workflows/node-18+.yml @@ -0,0 +1,119 @@ +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' diff --git a/.github/workflows/node-minors.yml b/.github/workflows/node-minors.yml new file mode 100644 index 0000000000..9e227f2b89 --- /dev/null +++ b/.github/workflows/node-minors.yml @@ -0,0 +1,117 @@ +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' diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml new file mode 100644 index 0000000000..ed00d06b47 --- /dev/null +++ b/.github/workflows/node-pretest.yml @@ -0,0 +1,30 @@ +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 diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000000..2e654951b6 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,134 @@ +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 }} diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml new file mode 100644 index 0000000000..b9e1712fc4 --- /dev/null +++ b/.github/workflows/rebase.yml @@ -0,0 +1,9 @@ +name: Automatic Rebase + +on: [pull_request_target] + +jobs: + _: + uses: ljharb/actions/.github/workflows/rebase.yml@main + secrets: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..d6f97d2e84 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,78 @@ +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 }} diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml new file mode 100644 index 0000000000..549d7b4823 --- /dev/null +++ b/.github/workflows/require-allow-edits.yml @@ -0,0 +1,12 @@ +name: Require “Allow Edits” + +on: [pull_request_target] + +jobs: + _: + name: "Require “Allow Edits”" + + runs-on: ubuntu-latest + + steps: + - uses: ljharb/require-allow-edits@main diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml new file mode 100644 index 0000000000..a2dacffb91 --- /dev/null +++ b/.github/workflows/smoke-test.yml @@ -0,0 +1,26 @@ +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 diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml new file mode 100644 index 0000000000..0aaca2cb00 --- /dev/null +++ b/.github/workflows/type-check.yml @@ -0,0 +1,77 @@ +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 diff --git a/.gitignore b/.gitignore index af67fd4b29..43605edffc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +# gitignore + lib-cov *.seed *.log @@ -11,7 +13,24 @@ lib-cov 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 diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000000..8a2cb35709 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "line-length": false, + "no-inline-html": false, + "no-hard-tabs": { "spaces_per_tab": 2 }, + "ul-style": { "style": "dash" } +} diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000000..bdaede90d0 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,3 @@ +CHANGELOG.md +LICENSE +node_modules diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..43c97e719a --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5b4b0793a2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - 0.10 - - 0.12 - - iojs -after_success: - - npm run coveralls diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..9696eca775 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4514 @@ +# 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 +* [`jsx-props-no-multi-spaces`]: improve autofix for multi-line ([#3930][] @justisb) + +### Fixed +* [`no-unknown-property`]: allow `onLoad` on `body` ([#3923][] @DerekStapleton) + +[#3930]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3930 +[#3923]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3923 + +## [7.37.5] - 2025.04.03 + +### Fixed +* [`no-unknown-property`]: allow shadow root attrs on `