diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 0defc64..d0038a0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -17,9 +17,9 @@ The issue tracker is for bug reports and feature discussions. ## Found an Issue or Bug? -Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available. +Before you submit an issue, please search the issue tracker, an issue for your problem may already exist, and the discussion might inform you of workarounds readily available. -We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we ask that you to provide a minimal reproduction scenario (github repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like: +We want to fix all the issues as soon as possible, but before fixing a bug, we need to reproduce and confirm it. In order to reproduce bugs, we ask that you provide a minimal reproduction scenario (GitHub repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like: - version of Webpack used - version of the loader / plugin you are creating a bug report for @@ -27,24 +27,24 @@ We want to fix all the issues as soon as possible, but before fixing a bug we ne A minimal reproduce scenario allows us to quickly confirm a bug (or point out config problems) as well as confirm that we are fixing the right problem. -We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. +We will be insisting on a minimal reproduction scenario in order to save the maintainers' time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase, but we really need to isolate the problem before we can fix it. -Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced. +Unfortunately, we are unable to investigate or fix bugs without a minimal reproduction, so if we don't hear back from you, we may have to close an issue that doesn't have enough info to be reproduced. ## Feature Requests? -You can _request_ a new feature by creating an issue on Github. +You can _request_ a new feature by creating an issue on GitHub. -If you would like to _implement_ a new feature, please submit an issue with a proposal for your work `first`, to be sure that particular makes sense for the project. +If you would like to _implement_ a new feature yourself, please **first submit an issue** with a proposal to ensure the idea aligns with the goals of the project. ## Pull Request Submission Guidelines Before you submit your Pull Request (PR) consider the following guidelines: -- Search Github for an open or closed PR that relates to your submission. You don't want to duplicate effort. -- Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages. -- Fill out our `Pull Request Template`. Your pull request will not be considered if it is ignored. -- Please sign the `Contributor License Agreement (CLA)` when a pull request is opened. We cannot accept your pull request without this. Make sure you sign with the primary email address associated with your local / github account. +- Search GitHub for an open or closed PR related to your submission to avoid duplicating effort. +- Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). This is important because release notes are automatically generated from these messages. +- Complete the `Pull Request Template`. Pull requests that ignore the template will not be reviewed. +- Please sign the `Contributor License Agreement (CLA)` when you open your pull request. We cannot accept your contribution without it. Be sure to sign using the primary email address associated with your local and GitHub account. ## Webpack Contrib Commit Conventions @@ -61,8 +61,7 @@ format that includes a **type**, a **scope** and a **subject**: The **header** is mandatory and the **scope** of the header is optional. -Any line of the commit message cannot be longer 100 characters! This allows the message to be easier -to read on GitHub as well as in various git tools. +No line in the commit message should exceed 100 characters! This makes the message easier to read on GitHub as well as in various Git tools. The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any. @@ -83,7 +82,7 @@ In the body it should say: `This reverts commit .`, where the hash is the ### Type -Must be one of the following: +Must be one of the following commit types: - **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm) - **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults) @@ -99,27 +98,26 @@ Must be one of the following: ### Scope -The scope is subjective & depends on the `type` see above. A good example would be a change to a particular class / module. +The scope is subjective & depends on the `type` see above. A good example of a scope would be a change to a particular class or module. ### Subject The subject contains a succinct description of the change: -- use the imperative, present tense: "change" not "changed" nor "changes" +- use the imperative, present tense: "change" not "changed" or "changes" - don't capitalize the first letter - no dot (.) at the end ### Body -Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes". -The body should include the motivation for the change and contrast this with previous behavior. +Just as in the **subject**, use the imperative, present tense: "change" not "changed" or "changes". +The body should include the motivation for the change and contrast it with previous behavior. ### Footer -The footer should contain any information about **Breaking Changes** and is also the place to -reference GitHub issues that this commit **Closes**. +The footer should include any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**. -**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this. +**Breaking Changes** must start with the word `BREAKING CHANGE:` followed by a space or two new lines. The rest of the breaking change details should be provided after this. Example @@ -133,9 +131,7 @@ Migration: see webpack/webpack#5225 ## Testing Your Pull Request -You may have the need to test your changes in a real-world project or dependent -module. Thankfully, Github provides a means to do this. Add a dependency to the -`package.json` for such a project as follows: +You may need to test your changes in a real-world project or a dependent module. Thankfully, GitHub provides a means to do this. To add a dependency to the `package.json` of such a project, use the following syntax: ```json { @@ -149,9 +145,9 @@ Where `{id}` is the # ID of your Pull Request. ## Contributor License Agreement -When submitting your contribution, a CLA (Contributor License Agreement) bot will come by to verify that you signed the [CLA](https://easycla.lfx.linuxfoundation.org/#/?version=2). +When submitting your contribution, a CLA (Contributor License Agreement) bot will verify whether you have signed the [CLA](https://easycla.lfx.linuxfoundation.org/#/?version=2). If it is your first time, it will link you to the right place to sign it. -However, if you have committed your contributions using an email that is not the same as your email used on GitHub, the CLA bot can't accept your contribution. +However, if the email used in your commits doesn’t match the email associated with your GitHub account, the CLA bot won’t accept your contribution. Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails). diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 3ce9cf3..f92d3cb 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,16 +1,15 @@ diff --git a/.github/ISSUE_TEMPLATE/BUG.md b/.github/ISSUE_TEMPLATE/BUG.md index 374f347..931d2e2 100644 --- a/.github/ISSUE_TEMPLATE/BUG.md +++ b/.github/ISSUE_TEMPLATE/BUG.md @@ -3,32 +3,31 @@ name: πŸ› Bug Report about: Something went awry and you'd like to tell us about it. --- - - + + ### Bug report - + - + ### Actual Behavior - + ### Expected Behavior - - + + ### How Do We Reproduce? - - - - - - + + + + + -### Please paste the results of `npx webpack-cli info` here, and mention other relevant information +### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. diff --git a/.github/ISSUE_TEMPLATE/DOCS.md b/.github/ISSUE_TEMPLATE/DOCS.md index a94c0c9..1f9fad7 100644 --- a/.github/ISSUE_TEMPLATE/DOCS.md +++ b/.github/ISSUE_TEMPLATE/DOCS.md @@ -3,12 +3,12 @@ name: πŸ“š Documentation about: Are the docs lacking or missing something? Do they need some new πŸ”₯ hotness? Tell us here. --- - - + + -Documentation Is: +Documentation is: - + - [ ] Missing - [ ] Needed @@ -17,9 +17,9 @@ Documentation Is: ### Please Explain in Detail... - + - + ### Your Proposal for Changes diff --git a/.github/ISSUE_TEMPLATE/FEATURE.md b/.github/ISSUE_TEMPLATE/FEATURE.md index 1e5304e..d1e618f 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE.md +++ b/.github/ISSUE_TEMPLATE/FEATURE.md @@ -3,16 +3,18 @@ name: ✨ Feature Request about: Suggest an idea for this project --- - - + + ### Feature Proposal - + - + ### Feature Use Case -### Please paste the results of `npx webpack-cli info` here, and mention other relevant information + + +### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. diff --git a/.github/ISSUE_TEMPLATE/MODIFICATION.md b/.github/ISSUE_TEMPLATE/MODIFICATION.md index c60a501..3560244 100644 --- a/.github/ISSUE_TEMPLATE/MODIFICATION.md +++ b/.github/ISSUE_TEMPLATE/MODIFICATION.md @@ -1,20 +1,25 @@ --- name: πŸ”§ Modification Request -about: Would you like something work differently? Have an alternative approach? This is the template for you. +about: Want something to work differently? Have an alternative approach? This is the template for you. --- - - + + ### Modification Proposal - + + - + ### Expected Behavior / Situation + + ### Actual Behavior / Situation -### Please paste the results of `npx webpack-cli info` here, and mention other relevant information + + +### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. diff --git a/.github/ISSUE_TEMPLATE/SUPPORT.md b/.github/ISSUE_TEMPLATE/SUPPORT.md index daaf912..066348a 100644 --- a/.github/ISSUE_TEMPLATE/SUPPORT.md +++ b/.github/ISSUE_TEMPLATE/SUPPORT.md @@ -1,7 +1,15 @@ --- name: πŸ†˜ Support, Help, and Advice -about: πŸ‘‰πŸ½ Need support, help, or advice? Don't open an issue! Head to https://github.com/webpack/webpack/discussions or StackOverflow. +about: πŸ‘‰πŸ½ Need support, help, or advice? Don't open an issue - visit "GitHub Discussions" or "Stack Overflow" instead. --- -Hey there! If you need support, help, or advice then this is not the place to ask. -Please visit [GitHub Discussions](https://github.com/webpack/webpack/discussions) or [StackOverflow](https://stackoverflow.com/questions/tagged/webpack) instead. +Hey there! πŸ‘‹ + +If you need support, help, or advice then this is not the right place to ask. + +Please visit one of the following instead: + +- [GitHub Discussions](https://github.com/webpack/webpack/discussions) +- [Stack Overflow](https://stackoverflow.com/questions/tagged/webpack) + +Thanks for understanding! diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 02dcb80..f35eb24 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -60,7 +60,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [18.x, 20.x, 22.x, 23.x] + node-version: [18.x, 20.x, 22.x, 24.x] eslint-version: [8.x, 9.x] webpack-version: [latest] diff --git a/CHANGELOG.md b/CHANGELOG.md index b080238..86c00c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [5.0.2](https://github.com/webpack-contrib/eslint-webpack-plugin/compare/v5.0.1...v5.0.2) (2025-06-09) + + +### Bug Fixes + +* don't error on circular eslint plugins ([#277](https://github.com/webpack-contrib/eslint-webpack-plugin/issues/277)) ([32f05c6](https://github.com/webpack-contrib/eslint-webpack-plugin/commit/32f05c6fdd70ec5532682ce5ed134998a269cdf3)) + ### [5.0.1](https://github.com/webpack-contrib/eslint-webpack-plugin/compare/v5.0.0...v5.0.1) (2025-04-15) diff --git a/README.md b/README.md index a23dc95..2957c19 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ # eslint-webpack-plugin -> This version of eslint-webpack-plugin only works with webpack 5. For the webpack 4, see the [2.x branch](https://github.com/webpack-contrib/eslint-webpack-plugin/tree/2.x). +> This version of eslint-webpack-plugin only supports webpack 5. For the webpack 4, see the [2.x branch](https://github.com/webpack-contrib/eslint-webpack-plugin/tree/2.x). -This plugin uses [`eslint`](https://eslint.org/) to find and fix problems in your JavaScript code +This plugin uses [`ESlint`](https://eslint.org/) to find and fix problems in your JavaScript code during the Webpack build process. ## Getting Started @@ -56,7 +56,7 @@ or pnpm add -D eslint ``` -Then add the plugin to your webpack config. For example: +Then add the plugin to your webpack configuration. For example: ```js const ESLintPlugin = require('eslint-webpack-plugin'); @@ -70,17 +70,17 @@ module.exports = { ## Options -You can pass [eslint options](https://eslint.org/docs/developer-guide/nodejs-api#-new-eslintoptions). +You can pass [ESLint Node.js API options](https://eslint.org/docs/developer-guide/nodejs-api#-new-eslintoptions). > [!NOTE] > > The config option you provide will be passed to the `ESLint` class. > This is a different set of options than what you'd specify in `package.json` or `.eslintrc`. -> See the [eslint docs](https://eslint.org/docs/developer-guide/nodejs-api#-new-eslintoptions) for more details. +> See the [ESlint docs](https://eslint.org/docs/developer-guide/nodejs-api#-new-eslintoptions) for more details. > [!WARNING] > -> In eslint-webpack-plugin version 1 the options were passed to the now deprecated [CLIEngine](https://eslint.org/docs/developer-guide/nodejs-api#cliengine). +> In eslint-webpack-plugin version 1 the options were passed to the now-deprecated [CLIEngine](https://eslint.org/docs/developer-guide/nodejs-api#cliengine). ### `cache` @@ -133,7 +133,7 @@ type context = string; - Default: `compiler.context` -A string indicating the root of your files. +Base directory for linting. ### `eslintPath` @@ -145,7 +145,9 @@ type eslintPath = string; - Default: `eslint` -Path to `eslint` instance that will be used for linting. If the `eslintPath` is a folder like a official eslint, or specify a `formatter` option. now you don't have to install `eslint`. +Path to `eslint` instance that will be used for linting. + +If the `eslintPath` is a folder like a official ESlint, or specify a `formatter` option, now you don't have to install `eslint`. ### `extensions` @@ -157,7 +159,7 @@ type extensions = string | Array; - Default: `'js'` -Specify extensions that should be checked. +Specify file extensions that should be checked. ### `exclude` @@ -169,7 +171,7 @@ type exclude = string | Array; - Default: `'node_modules'` -Specify the files and/or directories to exclude. Must be relative to `options.context`. +Specify the files/directories to exclude. Must be relative to `options.context`. ### `resourceQueryExclude` @@ -209,7 +211,7 @@ type fix = boolean; Will enable [ESLint autofix feature](https://eslint.org/docs/developer-guide/nodejs-api#-eslintoutputfixesresults). -**Be careful: this option will change source files.** +**Be careful: this option will modify source files.** ### `formatter` @@ -224,7 +226,9 @@ type formatter = string| ( - Default: `'stylish'` -Accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string. You can use official [eslint formatters](https://eslint.org/docs/user-guide/formatters/). +Accepts a function that receives an array of ESLint messages (object) as its argument and must return a string as output. + +You can use official [ESlint formatters](https://eslint.org/docs/user-guide/formatters/). ### `lintDirtyModulesOnly` @@ -236,7 +240,7 @@ type lintDirtyModulesOnly = boolean; - Default: `false` -Lint only changed files, skip lint on start. +Lint only changed files, skipping initial lint on build start. ### `threads` @@ -253,6 +257,7 @@ Will run lint tasks across a thread pool. The pool size is automatic unless you ### Errors and Warning **By default the plugin will auto adjust error reporting depending on eslint errors/warnings counts.** + You can still force this behavior by using `emitError` **or** `emitWarning` options: #### `emitError` @@ -289,7 +294,7 @@ type failOnError = boolean; - Default: `true` -Will cause the module build to fail if there are any errors, to disable set to `false`. +Will cause the module build to fail if any errors are found, to disable set to `false`. #### `failOnWarning` @@ -301,7 +306,7 @@ type failOnWarning = boolean; - Default: `false` -Will cause the module build to fail if there are any warnings, if set to `true`. +Will cause the module build to fail if any warnings are found, if set to `true`. #### `quiet` @@ -338,16 +343,24 @@ type outputReport = - Default: `false` -Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI. +Write ESLint results to a file, for example a checkstyle xml file for use for reporting on Jenkins CI. -The `filePath` is an absolute path or relative to the webpack config: `output.path`. -You can pass in a different `formatter` for the output file, -if none is passed in the default/configured formatter will be used. +- filePath: Path to output report file (relative to output.path or absolute). +- formatter: You can pass in a different `formatter` for the output file. + if none is passed in the default/configured formatter will be used. ## Changelog [Changelog](CHANGELOG.md) +## Contributing + +We welcome all contributions! + +If you're new here, please take a moment to review our contributing guidelines. + +[CONTRIBUTING](./.github/CONTRIBUTING.md) + ## License [MIT](./LICENSE) diff --git a/package-lock.json b/package-lock.json index 8522e6e..58ac0bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { "name": "eslint-webpack-plugin", - "version": "5.0.1", + "version": "5.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "eslint-webpack-plugin", - "version": "5.0.1", + "version": "5.0.2", "license": "MIT", "dependencies": { "@types/eslint": "^9.6.1", + "flatted": "^3.3.3", "jest-worker": "^29.7.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", @@ -7417,10 +7418,10 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", @@ -18959,10 +18960,9 @@ } }, "flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index 24d05af..6f0627b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-webpack-plugin", - "version": "5.0.1", + "version": "5.0.2", "description": "A ESLint plugin for webpack", "license": "MIT", "repository": "webpack-contrib/eslint-webpack-plugin", @@ -51,6 +51,7 @@ }, "dependencies": { "@types/eslint": "^9.6.1", + "flatted": "^3.3.3", "jest-worker": "^29.7.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", diff --git a/src/getESLint.js b/src/getESLint.js index c55915d..6c852ff 100644 --- a/src/getESLint.js +++ b/src/getESLint.js @@ -6,6 +6,7 @@ const { Worker: JestWorker } = require('jest-worker'); const { setup, lintFiles } = require('./worker'); const { getESLintOptions } = require('./options'); const { jsonStringifyReplacerSortKeys } = require('./utils'); +const { stringify } = require('flatted'); /** @type {{[key: string]: any}} */ const cache = {}; @@ -115,7 +116,7 @@ async function getESLint(key, { threads, ...options }) { * @returns {string} */ function getCacheKey(key, options) { - return JSON.stringify({ key, options }, jsonStringifyReplacerSortKeys); + return stringify({ key, options }, jsonStringifyReplacerSortKeys); } module.exports = { diff --git a/src/utils.js b/src/utils.js index b9ebc36..13aa67e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -104,9 +104,13 @@ const jsonStringifyReplacerSortKeys = (_, value) => { return sorted; }; - return value instanceof Object && !(value instanceof Array) - ? Object.keys(value).sort().reduce(insert, {}) - : value; + if (value instanceof Object && !(value instanceof Array)) { + let sorted = Object.keys(value).sort().reduce(insert, {}); + Object.keys(value).forEach((key) => delete value[key]); + Object.assign(value, sorted); + } + + return value; }; module.exports = { diff --git a/test/circular-plugin.test.js b/test/circular-plugin.test.js new file mode 100644 index 0000000..54b93ad --- /dev/null +++ b/test/circular-plugin.test.js @@ -0,0 +1,38 @@ +import pack from './utils/pack'; +import { ESLint } from 'eslint'; + +(ESLint && parseFloat(ESLint.version) < 9 ? describe.skip : describe)( + 'circular plugin', + () => { + it('should support plugins with circular configs', async () => { + const plugin = { + configs: {}, + rules: {}, + processors: {}, + }; + + Object.assign(plugin.configs, { + recommended: { + plugins: { + self: plugin, + }, + rules: {}, + }, + }); + + const loaderOptions = { + configType: 'flat', + overrideConfig: { + plugins: { plugin: plugin }, + }, + overrideConfigFile: true, + }; + + const compiler = pack('good', loaderOptions); + + const stats = await compiler.runAsync(); + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(false); + }); + }, +);