Repository: green-code-initiative/creedengo-javascript
Pull request #51: fix(eslint): flat config support
Author: login: AMorgaut
Labels: name: 🚀 enhancement
description: New feature or request
name: 🏗️ refactoring
description: Refactoring for best practices
Created: 2024-08-21T13:09:20Z | Merged: 2025-04-24T21:55:46Z

Fix issue #50 (ESLint flat config support)

see: https://eslint.org/docs/latest/extend/plugin-migration-flat-config


Diff:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4b401e6..8bd7d2b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -57,6 +57,9 @@ jobs:
       - name: Update Docker Compose configuration
         run: sed -i -E 's/plugin-(.*).jar/plugin-${{ steps.package-version.outputs.version }}.jar/' docker-compose.yml
 
+      - name: Update ESLint plugin version
+        run: 'sed -i -E ''s/version: "(.*)"/version: "${{ steps.package-version.outputs.version }}"/'' eslint-plugin/lib/standalone.js'
+
       - name: Extract release notes
         id: extract-release-notes
         uses: ffurrer2/extract-release-notes@v1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d7ebe5..b6468ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Added
+
+-   [#51](https://github.com/green-code-initiative/creedengo-javascript/pull/51) Add ESLint v9 and flat config support
+
 ## [2.1.0] - 2025-03-31
 
 ### Added
diff --git a/eslint-plugin/.eslint-doc-generatorrc.js b/eslint-plugin/.eslint-doc-generatorrc.js
new file mode 100644
index 0000000..e49a684
--- /dev/null
+++ b/eslint-plugin/.eslint-doc-generatorrc.js
@@ -0,0 +1,11 @@
+"use strict";
+
+/** @type {import('eslint-doc-generator').GenerateOptions} */
+const config = {
+  configEmoji: [["flat/recommended", "✅"]],
+  postprocess: (doc) => {
+    return doc.replace(/✅\s*✅/gu, "✅");
+  },
+};
+
+module.exports = config;
diff --git a/eslint-plugin/README.md b/eslint-plugin/README.md
index fe33f21..f4cba47 100644
--- a/eslint-plugin/README.md
+++ b/eslint-plugin/README.md
@@ -8,7 +8,7 @@ An ESLint plugin which provides JavaScript and TypeScript rules of the Creedengo
 
 ### Installation
 
-You'll need to install [ESLint](https://eslint.org/) (v7 or v8) and this plugin:
+You'll need to install [ESLint](https://eslint.org/) (v7+) and this plugin:
 
 ```sh
 # yarn
@@ -32,19 +32,54 @@ yarn add -D eslint @green-code-initiative/creedengo-eslint-plugin
 npm install -D eslint @green-code-initiative/creedengo-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@creedengo` recommended configuration to `extends` section of your `.eslintrc`:
+#### ESLint Flat Configuration (`eslint.config.js`)
 
-```jsonc
+Add `@creedengo` **"flat/recommended"** configuration to your `eslint.config.js`:
+
+```js
+import creedengo from "@creedengo/eslint-plugin";
+
+export default [
+  /* other eslint configurations */
+  creedengo.configs["flat/recommended"],
+];
+```
+
+#### ESLint deprecated legacy configuration (`.eslintrc`)
+
+For legacy ESLint versions using the deprecated `.eslintrc` file, add the `@creedengo` **"recommended"** configuration to the `extends` array :
+
+```json
 {
-  "extends": ["plugin:@creedengo/recommended"],
+  "extends": ["plugin:@creedengo/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### ESLint Flat configuration (`eslint.config.js`)
+
+Add the `creedengo` plugin configuration to your `eslint.config.js` and select the rules to activate:
+
+```js
+import creedengo from "@creedengo/eslint-plugin";
+
+export default [
+  /* other eslint configurations */
+  {
+    plugins: { "@creedengo": creedengo },
+    rules: {
+      "@creedengo/no-multiple-access-dom-element": "error",
+    },
+  },
+];
+```
+
+#### ESLint deprecated legacy configuration (`.eslintrc`)
 
-Add `@creedengo` to the `plugins` section of your `.eslintrc`, followed by rules configuration:
+If your project uses a legacy ESLint version, it may use as well the now deprecated `.eslintrc` file. In such case, add `@creedengo` to the `plugins` array, potentially followed by rules specific configurations:
 
 ```jsonc
 {
@@ -59,9 +94,10 @@ Add `@creedengo` to the `plugins` section of your `.eslintrc`, followed by rules
 
 <!-- begin auto-generated configs list -->
 
-|    | Name          |
-| :- | :------------ |
-| ✅  | `recommended` |
+|    | Name               |
+| :- | :----------------- |
+| ✅  | `flat/recommended` |
+| ✅  | `recommended`      |
 
 <!-- end auto-generated configs list -->
 
@@ -70,25 +106,26 @@ Add `@creedengo` to the `plugins` section of your `.eslintrc`, followed by rules
 <!-- begin auto-generated rules list -->
 
 ⚠️ Configurations set to warn in.\
+✅ Set in the `flat/recommended` configuration.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                           | Description                                               | ⚠️ |
-| :--------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- |
-| [avoid-autoplay](docs/rules/avoid-autoplay.md)                                                 | Avoid autoplay for videos and audio content               | ✅  |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                           | Should avoid to override brightness                       | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                                     | Avoid usage of CSS animations                             | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)               | Avoid using high accuracy geolocation in web applications | ✅  |
-| [avoid-keep-awake](docs/rules/avoid-keep-awake.md)                                             | Avoid screen keep awake                                   | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                                 | Should limit the number of returns for a SQL query        | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)                     | Disallow usage of image with empty source attribute       | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                         | Should not import all from library                        | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)                 | Disallow multiple access of same DOM element              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                           | Disallow multiple style changes at once                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                             | Should not programmatically enable torch mode             | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md)         | Prefer API collections with pagination                    | ✅  |
-| [prefer-lighter-formats-for-image-files](docs/rules/prefer-lighter-formats-for-image-files.md) | Prefer lighter formats for image files                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)                 | Encourage usage of shorthand CSS notations                | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                           | Enforce providing a print stylesheet                      | ✅  |
+| Name                                                                                           | Description                                               | ⚠️  |
+| :--------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :-- |
+| [avoid-autoplay](docs/rules/avoid-autoplay.md)                                                 | Avoid autoplay for videos and audio content               | ✅ |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                           | Should avoid to override brightness                       | ✅ |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                                     | Avoid usage of CSS animations                             | ✅ |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)               | Avoid using high accuracy geolocation in web applications | ✅ |
+| [avoid-keep-awake](docs/rules/avoid-keep-awake.md)                                             | Avoid screen keep awake                                   | ✅ |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                                 | Should limit the number of returns for a SQL query        | ✅ |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)                     | Disallow usage of image with empty source attribute       | ✅ |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                         | Should not import all from library                        | ✅ |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)                 | Disallow multiple access of same DOM element              | ✅ |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                           | Disallow multiple style changes at once                   | ✅ |
+| [no-torch](docs/rules/no-torch.md)                                                             | Should not programmatically enable torch mode             | ✅ |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md)         | Prefer API collections with pagination                    | ✅ |
+| [prefer-lighter-formats-for-image-files](docs/rules/prefer-lighter-formats-for-image-files.md) | Prefer lighter formats for image files                    | ✅ |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)                 | Encourage usage of shorthand CSS notations                | ✅ |
+| [provide-print-css](docs/rules/provide-print-css.md)                                           | Enforce providing a print stylesheet                      | ✅ |
 
 <!-- end auto-generated rules list -->
 
diff --git a/eslint-plugin/docs/rules/avoid-autoplay.md b/eslint-plugin/docs/rules/avoid-autoplay.md
index 738860a..23a3ecc 100644
--- a/eslint-plugin/docs/rules/avoid-autoplay.md
+++ b/eslint-plugin/docs/rules/avoid-autoplay.md
@@ -1,6 +1,6 @@
 # Avoid autoplay for videos and audio content (`@creedengo/avoid-autoplay`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/avoid-brightness-override.md b/eslint-plugin/docs/rules/avoid-brightness-override.md
index 83bc6fe..50ba47c 100644
--- a/eslint-plugin/docs/rules/avoid-brightness-override.md
+++ b/eslint-plugin/docs/rules/avoid-brightness-override.md
@@ -1,6 +1,6 @@
 # Should avoid to override brightness (`@creedengo/avoid-brightness-override`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/avoid-css-animations.md b/eslint-plugin/docs/rules/avoid-css-animations.md
index 5b4afa5..f1316bc 100644
--- a/eslint-plugin/docs/rules/avoid-css-animations.md
+++ b/eslint-plugin/docs/rules/avoid-css-animations.md
@@ -1,6 +1,6 @@
 # Avoid usage of CSS animations (`@creedengo/avoid-css-animations`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md b/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md
index 28c5a10..2a207ea 100644
--- a/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md
+++ b/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md
@@ -1,6 +1,6 @@
 # Avoid using high accuracy geolocation in web applications (`@creedengo/avoid-high-accuracy-geolocation`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/avoid-keep-awake.md b/eslint-plugin/docs/rules/avoid-keep-awake.md
index 056ccf2..595cd0c 100644
--- a/eslint-plugin/docs/rules/avoid-keep-awake.md
+++ b/eslint-plugin/docs/rules/avoid-keep-awake.md
@@ -1,6 +1,6 @@
 # Avoid screen keep awake (`@creedengo/avoid-keep-awake`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/limit-db-query-results.md b/eslint-plugin/docs/rules/limit-db-query-results.md
index 7137dec..4c1eda5 100644
--- a/eslint-plugin/docs/rules/limit-db-query-results.md
+++ b/eslint-plugin/docs/rules/limit-db-query-results.md
@@ -1,6 +1,6 @@
 # Should limit the number of returns for a SQL query (`@creedengo/limit-db-query-results`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/no-empty-image-src-attribute.md b/eslint-plugin/docs/rules/no-empty-image-src-attribute.md
index 4723ac3..fa7c527 100644
--- a/eslint-plugin/docs/rules/no-empty-image-src-attribute.md
+++ b/eslint-plugin/docs/rules/no-empty-image-src-attribute.md
@@ -1,6 +1,6 @@
 # Disallow usage of image with empty source attribute (`@creedengo/no-empty-image-src-attribute`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/no-import-all-from-library.md b/eslint-plugin/docs/rules/no-import-all-from-library.md
index b802a01..c864338 100644
--- a/eslint-plugin/docs/rules/no-import-all-from-library.md
+++ b/eslint-plugin/docs/rules/no-import-all-from-library.md
@@ -1,6 +1,6 @@
 # Should not import all from library (`@creedengo/no-import-all-from-library`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/no-multiple-access-dom-element.md b/eslint-plugin/docs/rules/no-multiple-access-dom-element.md
index 7bf450c..6f1d2e9 100644
--- a/eslint-plugin/docs/rules/no-multiple-access-dom-element.md
+++ b/eslint-plugin/docs/rules/no-multiple-access-dom-element.md
@@ -1,6 +1,6 @@
 # Disallow multiple access of same DOM element (`@creedengo/no-multiple-access-dom-element`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/no-multiple-style-changes.md b/eslint-plugin/docs/rules/no-multiple-style-changes.md
index 59d13a9..69b40bb 100644
--- a/eslint-plugin/docs/rules/no-multiple-style-changes.md
+++ b/eslint-plugin/docs/rules/no-multiple-style-changes.md
@@ -1,6 +1,6 @@
 # Disallow multiple style changes at once (`@creedengo/no-multiple-style-changes`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/no-torch.md b/eslint-plugin/docs/rules/no-torch.md
index 9e0c0f6..c27a51e 100644
--- a/eslint-plugin/docs/rules/no-torch.md
+++ b/eslint-plugin/docs/rules/no-torch.md
@@ -1,6 +1,6 @@
 # Should not programmatically enable torch mode (`@creedengo/no-torch`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 ## Why is this an issue?
diff --git a/eslint-plugin/docs/rules/prefer-collections-with-pagination.md b/eslint-plugin/docs/rules/prefer-collections-with-pagination.md
index ab79078..b46dd9b 100644
--- a/eslint-plugin/docs/rules/prefer-collections-with-pagination.md
+++ b/eslint-plugin/docs/rules/prefer-collections-with-pagination.md
@@ -1,6 +1,6 @@
 # Prefer API collections with pagination (`@creedengo/prefer-collections-with-pagination`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/prefer-lighter-formats-for-image-files.md b/eslint-plugin/docs/rules/prefer-lighter-formats-for-image-files.md
index d8e3e29..d9cf796 100644
--- a/eslint-plugin/docs/rules/prefer-lighter-formats-for-image-files.md
+++ b/eslint-plugin/docs/rules/prefer-lighter-formats-for-image-files.md
@@ -1,6 +1,6 @@
 # Prefer lighter formats for image files (`@creedengo/prefer-lighter-formats-for-image-files`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/prefer-shorthand-css-notations.md b/eslint-plugin/docs/rules/prefer-shorthand-css-notations.md
index a8c3cd9..8846090 100644
--- a/eslint-plugin/docs/rules/prefer-shorthand-css-notations.md
+++ b/eslint-plugin/docs/rules/prefer-shorthand-css-notations.md
@@ -1,6 +1,6 @@
 # Encourage usage of shorthand CSS notations (`@creedengo/prefer-shorthand-css-notations`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/docs/rules/provide-print-css.md b/eslint-plugin/docs/rules/provide-print-css.md
index d90225f..691a99e 100644
--- a/eslint-plugin/docs/rules/provide-print-css.md
+++ b/eslint-plugin/docs/rules/provide-print-css.md
@@ -1,6 +1,6 @@
 # Enforce providing a print stylesheet (`@creedengo/provide-print-css`)
 
-⚠️ This rule _warns_ in the ✅ `recommended` config.
+⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-plugin/lib/rules/no-multiple-access-dom-element.js b/eslint-plugin/lib/rules/no-multiple-access-dom-element.js
index 61aac75..93e4d68 100644
--- a/eslint-plugin/lib/rules/no-multiple-access-dom-element.js
+++ b/eslint-plugin/lib/rules/no-multiple-access-dom-element.js
@@ -54,15 +54,18 @@ module.exports = {
         ) {
           const selectorValue = node.arguments[0].value;
           const uniqueCallStr = node.callee.property.name + selectorValue;
+          // todo: legacy support of context#getScope for eslint v7
+          const scope =
+            context.sourceCode?.getScope(node) ?? context.getScope();
 
-          if (map[uniqueCallStr] === context.getScope()) {
+          if (map[uniqueCallStr] === scope) {
             context.report({
               node,
               messageId: "ShouldBeAssignToVariable",
               data: { selector: selectorValue },
             });
           } else {
-            map[uniqueCallStr] = context.getScope();
+            map[uniqueCallStr] = scope;
           }
         }
       },
diff --git a/eslint-plugin/lib/rules/no-multiple-style-changes.js b/eslint-plugin/lib/rules/no-multiple-style-changes.js
index 3f0877e..022a818 100644
--- a/eslint-plugin/lib/rules/no-multiple-style-changes.js
+++ b/eslint-plugin/lib/rules/no-multiple-style-changes.js
@@ -40,7 +40,7 @@ module.exports = {
     const getNodeFullName = (node) => {
       let names = [];
       do {
-        names.unshift(node.name ?? node.property.name);
+        names.unshift(node.name ?? node.property?.name);
         node = node.object;
       } while (node);
       return names.join(".");
@@ -60,10 +60,13 @@ module.exports = {
            * Store parent AST to check if there is more
            * than one assignation on the style of the same domElement
            */
+          // todo: legacy support of context#getScope for eslint v7
+          const scope =
+            context.sourceCode?.getScope(node) ?? context.getScope();
           const currentScopeASTBody =
-            context.getScope().block.body.length != null
-              ? context.getScope().block.body
-              : context.getScope().block.body.body;
+            scope.block.body.length != null
+              ? scope.block.body
+              : scope.block.body.body;
 
           const filtered = currentScopeASTBody.filter(
             (e) =>
diff --git a/eslint-plugin/lib/rules/prefer-collections-with-pagination.js b/eslint-plugin/lib/rules/prefer-collections-with-pagination.js
index aa0b398..1aa8647 100644
--- a/eslint-plugin/lib/rules/prefer-collections-with-pagination.js
+++ b/eslint-plugin/lib/rules/prefer-collections-with-pagination.js
@@ -90,10 +90,12 @@ module.exports = {
               returnType.type === "TSTypeReference" &&
               returnType.typeName.name === "Promise"
             ) {
-              if (
-                returnType.typeParameters.params.length === 1 &&
-                !isPaginated(returnType.typeParameters.params[0])
-              ) {
+              // todo: legacy support of typeParameters for eslint v7
+              const params = (
+                returnType.typeArguments ?? returnType.typeParameters
+              ).params;
+
+              if (params.length === 1 && !isPaginated(params[0])) {
                 report(context, returnType);
               }
             } else if (
diff --git a/eslint-plugin/lib/standalone.js b/eslint-plugin/lib/standalone.js
index bedfa78..417344c 100644
--- a/eslint-plugin/lib/standalone.js
+++ b/eslint-plugin/lib/standalone.js
@@ -24,19 +24,33 @@
 
 const rules = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {};
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@creedengo/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rules) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@creedengo/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@creedengo"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@creedengo/eslint-plugin",
+    version: "2.1.0", // dynamically updated by the release workflow
+  },
+  rules: allRules,
 };
+
+plugin.configs = {
+  recommended: {
+    plugins: ["@creedengo"],
+    rules: recommendedRules,
+  },
+  ["flat/recommended"]: {
+    plugins: { "@creedengo": plugin },
+    rules: recommendedRules,
+  },
+};
+
+module.exports = plugin;


Reviews:
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-21T15:32:11Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-21T15:34:12Z
user: login: utarwyn
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2024-10-14T18:45:43Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-16T14:42:05Z
user: login: utarwyn
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-17T22:44:37Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-18T07:17:31Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-18T07:30:15Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-18T08:55:45Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-18T08:57:09Z
user: login: utarwyn
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-18T10:54:43Z
user: login: AMorgaut
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-18T20:13:28Z
user: login: utarwyn
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T23:20:05Z
user: login: utarwyn
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T23:35:49Z
user: login: utarwyn
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-24T21:53:40Z

Review comments:
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
path: eslint-plugin/lib/standalone.js
user: login: AMorgaut
body: Previous implementation did 2 loops

The updated code does it only once
created_at: 2024-08-21T15:32:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@ecocode/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@ecocode"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@ecocode/eslint-plugin",
+    version: "1.6.0",
+  },
+  rules: allRules,
 };
+
+plugin.configs = {
+  recommended: {
path: eslint-plugin/lib/standalone.js
user: login: AMorgaut
body: legacy configuration is maintained as-is 

no expected regressions
created_at: 2024-08-21T15:33:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@ecocode/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@ecocode"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@ecocode/eslint-plugin",
+    version: "1.6.0",
+  },
+  rules: allRules,
 };
+
+plugin.configs = {
+  recommended: {
+    plugins: ["@ecocode"],
+    rules: recommendedRules,
+  },
+  ["flat/recommended"]: {
path: eslint-plugin/lib/standalone.js
user: login: AMorgaut
body: the new flat configuration follows the plugin naming convention
created_at: 2024-08-21T15:34:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,20 +102,20 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
 ⚠️ Configurations set to warn in.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                   | Description                                                | ⚠️ |
-| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅  |
+| Name                                                                                   | Description                                                | ⚠️                            |
+| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :---------------------------- |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅ ![badge-flat/recommended][] |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅ ![badge-flat/recommended][] |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅ ![badge-flat/recommended][] |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅ ![badge-flat/recommended][] |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅ ![badge-flat/recommended][] |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅ ![badge-flat/recommended][] |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅ ![badge-flat/recommended][] |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅ ![badge-flat/recommended][] |
+| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅ ![badge-flat/recommended][] |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅ ![badge-flat/recommended][] |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅ ![badge-flat/recommended][] |
+| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅ ![badge-flat/recommended][] |
path: eslint-plugin/README.md
user: login: utarwyn
body: I don't understand the addition of `![badge-flat/recommended][]`?
created_at: 2024-10-14T18:36:52Z
author_association: MEMBER
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
+
+Add the `ecocode` plugin configuration to  your `eslint.config.js` and select the rules to activate:
path: eslint-plugin/README.md
user: login: utarwyn
body: ```suggestion
Add the `ecocode` plugin configuration to your `eslint.config.js` and select the rules to activate:
```
created_at: 2024-10-14T18:37:02Z
author_association: MEMBER
diff_hunk: @@ -1,6 +1,6 @@
 {
   "name": "@ecocode/eslint-plugin",
-  "version": "1.5.0",
+  "version": "1.6.0",
path: eslint-plugin/package.json
user: login: utarwyn
body: You don't need to edit this yourself 😉 
created_at: 2024-10-14T18:38:03Z
author_association: MEMBER
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@ecocode/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@ecocode"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@ecocode/eslint-plugin",
+    version: "1.6.0",
path: eslint-plugin/lib/standalone.js
user: login: utarwyn
body: I'm not a big fan of version being hard-coded here.
This makes it necessary to modify the version bump workflow to change this value dynamically.
created_at: 2024-10-14T18:39:49Z
author_association: MEMBER
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
path: eslint-plugin/lib/standalone.js
user: login: utarwyn
body: I think this comment is unnecessary
```suggestion
const recommendedRules = {};
```
created_at: 2024-10-14T18:40:37Z
author_association: MEMBER
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
+
+Add the `ecocode` plugin configuration to  your `eslint.config.js` and select the rules to activate:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  {
+    plugins: { "@ecocode": ecocode },
+    rules: {
+      "@ecocode/no-multiple-access-dom-element": "error"
+    }
+  }
+]
+```
+
+#### With the legacy `.eslintrc` 
path: eslint-plugin/README.md
user: login: utarwyn
body: Same wording as [ESLint documentation here](https://eslint.org/docs/latest/use/configure/configuration-files)
```suggestion
#### With the deprecated eslintrc format
```
created_at: 2024-10-14T18:44:02Z
author_association: MEMBER
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
path: eslint-plugin/README.md
user: login: utarwyn
body: ESLint documentation talks about "flat configurations", so I think we can keep this term to remain consistent.
```suggestion
#### With modern flat configuration
```
created_at: 2024-10-14T18:44:58Z
author_association: MEMBER
diff_hunk: @@ -67,20 +102,20 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
 ⚠️ Configurations set to warn in.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                   | Description                                                | ⚠️ |
-| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅  |
+| Name                                                                                   | Description                                                | ⚠️                            |
+| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :---------------------------- |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅ ![badge-flat/recommended][] |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅ ![badge-flat/recommended][] |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅ ![badge-flat/recommended][] |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅ ![badge-flat/recommended][] |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅ ![badge-flat/recommended][] |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅ ![badge-flat/recommended][] |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅ ![badge-flat/recommended][] |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅ ![badge-flat/recommended][] |
+| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅ ![badge-flat/recommended][] |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅ ![badge-flat/recommended][] |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅ ![badge-flat/recommended][] |
+| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅ ![badge-flat/recommended][] |
path: eslint-plugin/README.md
user: login: AMorgaut
body: I didn't edited it myself
These changes were done by calling the `yarn run update:eslint-docs` command
as mentioned in the CONTRIBUTING documentation
https://github.com/green-code-initiative/ecoCode-javascript/blob/main/CONTRIBUTING.md#generate-rule-documentation
created_at: 2024-10-16T14:42:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,20 +102,20 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
 ⚠️ Configurations set to warn in.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                   | Description                                                | ⚠️ |
-| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅  |
+| Name                                                                                   | Description                                                | ⚠️                            |
+| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :---------------------------- |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅ ![badge-flat/recommended][] |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅ ![badge-flat/recommended][] |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅ ![badge-flat/recommended][] |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅ ![badge-flat/recommended][] |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅ ![badge-flat/recommended][] |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅ ![badge-flat/recommended][] |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅ ![badge-flat/recommended][] |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅ ![badge-flat/recommended][] |
+| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅ ![badge-flat/recommended][] |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅ ![badge-flat/recommended][] |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅ ![badge-flat/recommended][] |
+| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅ ![badge-flat/recommended][] |
path: eslint-plugin/README.md
user: login: utarwyn
body: Maybe we need to edit the configuration, because the current result is pretty strange 😞 
created_at: 2024-10-17T22:44:37Z
author_association: MEMBER
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
path: eslint-plugin/README.md
user: login: AMorgaut
body: I'm unsure on that one

I think you might be right for new projects from scratch, but for existing projects and projects generated by framework generators (Nx, Angular, preact, Vue, ...) that still generate project with previous eslint configurations (which is what happened to ecocode-dashboard), it it really not obvious, and actually, it took me some time to figure out about the new eslint "flat config". What you first see when you want to add a plugin to your project is the name of your eslint configuration file

I based this part of the documentation on what I saw on another eslint plugin and which looked cristal clear to apply.
created_at: 2024-10-18T07:17:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
path: eslint-plugin/README.md
user: login: AMorgaut
body: Not sure from which plugin I originally took it but the playwright one use both "flat config" and the file name to describe how to add it. It looks to be a good compromise

> [Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new) (eslint.config.js)
> ...
>
> [Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files) (.eslintrc)
> ... 

https://github.com/playwright-community/eslint-plugin-playwright/blob/main/README.md
created_at: 2024-10-18T07:30:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@ecocode/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@ecocode"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@ecocode/eslint-plugin",
+    version: "1.6.0",
path: eslint-plugin/lib/standalone.js
user: login: AMorgaut
body: Agree not fan neither

The ESLint configuration says:

> you should add a meta key that contains **at least a name key, and ideally, a version key**

So version is not mandatory and looking a other plugins, it looks like they don't include it, so we could drop it.

I'll just do some check because it also says:

> Without this meta information, your plugin will not be usable with the --cache and --print-config command line options.

Even if the version is not mandatory, I would like to make sure about its impact regarding the cache feature
created_at: 2024-10-18T08:55:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,6 +1,6 @@
 {
   "name": "@ecocode/eslint-plugin",
-  "version": "1.5.0",
+  "version": "1.6.0",
path: eslint-plugin/package.json
user: login: AMorgaut
body: sure I can revert it
I guess it is done by the package release workflow
created_at: 2024-10-18T08:56:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,17 +36,52 @@ yarn add -D eslint @green-code-initiative/ecocode-eslint-plugin
 npm install -D eslint @green-code-initiative/ecocode-eslint-plugin
 ```
 
-### Enable whole plugin
+### Enable plugin with recommended configuration
 
-Add `@ecocode` recommended configuration to `extends` section of your `.eslintrc`:
+#### With modern `eslint.config.js`
 
-```jsonc
+Add `@ecocode` **"flat/recommended"** configuration to  your `eslint.config.js`:
+
+```js
+import ecocode from '@ecocode/eslint-plugin'
+
+export default [
+  /* other eslint configurations */
+  ecocode.configs['flat/recommended'],
+]
+```
+
+#### With the legacy `.eslintrc` 
+
+Add `@ecocode` **"recommended"** configuration to `extends` section of your `.eslintrc`:
+
+```json
 {
   "extends": ["plugin:@ecocode/recommended"]
 }
 ```
 
-### Enable only some rules
+### Enable specific rules
+
+#### With modern `eslint.config.js`
path: eslint-plugin/README.md
user: login: utarwyn
body: Thank you for the feedback! I think this is a great idea, we can go for it 💯 
created_at: 2024-10-18T10:54:42Z
author_association: MEMBER
diff_hunk: @@ -67,20 +102,20 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
 ⚠️ Configurations set to warn in.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                   | Description                                                | ⚠️ |
-| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅  |
+| Name                                                                                   | Description                                                | ⚠️                            |
+| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :---------------------------- |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅ ![badge-flat/recommended][] |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅ ![badge-flat/recommended][] |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅ ![badge-flat/recommended][] |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅ ![badge-flat/recommended][] |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅ ![badge-flat/recommended][] |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅ ![badge-flat/recommended][] |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅ ![badge-flat/recommended][] |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅ ![badge-flat/recommended][] |
+| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅ ![badge-flat/recommended][] |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅ ![badge-flat/recommended][] |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅ ![badge-flat/recommended][] |
+| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅ ![badge-flat/recommended][] |
path: eslint-plugin/README.md
user: login: AMorgaut
body: manually fixed for now
created_at: 2024-10-18T20:13:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,20 +102,20 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c
 ⚠️ Configurations set to warn in.\
 ✅ Set in the `recommended` configuration.
 
-| Name                                                                                   | Description                                                | ⚠️ |
-| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
-| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅  |
-| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅  |
-| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅  |
-| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅  |
-| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅  |
-| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅  |
-| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅  |
-| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅  |
-| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅  |
-| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅  |
-| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅  |
-| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅  |
+| Name                                                                                   | Description                                                | ⚠️                            |
+| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :---------------------------- |
+| [avoid-brightness-override](docs/rules/avoid-brightness-override.md)                   | Should avoid to override brightness                        | ✅ ![badge-flat/recommended][] |
+| [avoid-css-animations](docs/rules/avoid-css-animations.md)                             | Avoid usage of CSS animations                              | ✅ ![badge-flat/recommended][] |
+| [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md)       | Avoid using high accuracy geolocation in web applications. | ✅ ![badge-flat/recommended][] |
+| [limit-db-query-results](docs/rules/limit-db-query-results.md)                         | Should limit the number of returns for a SQL query         | ✅ ![badge-flat/recommended][] |
+| [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md)             | Disallow usage of image with empty source attribute        | ✅ ![badge-flat/recommended][] |
+| [no-import-all-from-library](docs/rules/no-import-all-from-library.md)                 | Should not import all from library                         | ✅ ![badge-flat/recommended][] |
+| [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md)         | Disallow multiple access of same DOM element.              | ✅ ![badge-flat/recommended][] |
+| [no-multiple-style-changes](docs/rules/no-multiple-style-changes.md)                   | Disallow multiple style changes at once.                   | ✅ ![badge-flat/recommended][] |
+| [no-torch](docs/rules/no-torch.md)                                                     | Should not programmatically enable torch mode              | ✅ ![badge-flat/recommended][] |
+| [prefer-collections-with-pagination](docs/rules/prefer-collections-with-pagination.md) | Prefer API collections with pagination.                    | ✅ ![badge-flat/recommended][] |
+| [prefer-shorthand-css-notations](docs/rules/prefer-shorthand-css-notations.md)         | Encourage usage of shorthand CSS notations                 | ✅ ![badge-flat/recommended][] |
+| [provide-print-css](docs/rules/provide-print-css.md)                                   | Enforce providing a print stylesheet                       | ✅ ![badge-flat/recommended][] |
path: eslint-plugin/README.md
user: login: utarwyn
body: Fixed in [290df21](https://github.com/green-code-initiative/creedengo-javascript/pull/51/commits/290df21e868bdc0890d7861d7b86a2809f0b245b)
created_at: 2025-04-18T23:20:05Z
author_association: MEMBER
diff_hunk: @@ -22,21 +22,35 @@
  */
 "use strict";
 
-const rules = require("./rule-list");
+const rulesList = require("./rule-list");
 
-const ruleModules = rules.reduce((map, rule) => {
-  map[rule.ruleName] = rule.ruleModule;
-  return map;
-}, {});
+const allRules = {};
+const recommendedRules = {}; // recommended rules
 
-const ruleConfigs = rules.reduce((map, rule) => {
-  const recommended = rule.ruleModule.meta.docs.recommended;
-  map[`@ecocode/${rule.ruleName}`] =
-    recommended === false ? "off" : recommended;
-  return map;
-}, {});
+for (let { ruleName, ruleModule } of rulesList) {
+  allRules[ruleName] = ruleModule;
+  const { recommended } = ruleModule.meta.docs;
+  const ruleConfiguration = recommended === false ? "off" : recommended;
+  recommendedRules[`@ecocode/${ruleName}`] = ruleConfiguration;
+}
 
-module.exports = {
-  rules: ruleModules,
-  configs: { recommended: { plugins: ["@ecocode"], rules: ruleConfigs } },
+const plugin = {
+  meta: {
+    name: "@ecocode/eslint-plugin",
+    version: "1.6.0",
path: eslint-plugin/lib/standalone.js
user: login: utarwyn
body: Fixed in 6f3b25940be33f7ee9e81e4591a2a1672e29426f
created_at: 2025-04-18T23:35:49Z
author_association: MEMBER

PR comments:
user: login: utarwyn
created_at: 2025-04-18T23:39:02Z
body: Just need a bit of testing and we will be good to go 🤞 
author_association: MEMBER
user: login: utarwyn
created_at: 2025-04-21T18:18:34Z
body: There are some problems with the rules code on the test project when upgrading it to ESLint v9 and typescript-eslint v8 (needed to parse TypeScript code using ESLint v9). We need to fix the code at some places due to some breaking changes in the AST API of typescript-eslint v8 ([see more here](https://typescript-eslint.io/blog/announcing-typescript-eslint-v8/#developer-facing-changes)).

I will check asap 🤞 We need to support both syntaxes in order to keep plugin working with ESLint v8.
author_association: MEMBER
user: login: utarwyn
created_at: 2025-04-23T18:20:21Z
body: ### Testing matrix

- [x] SonarQube 9.9 (LTA)
- [x] SonarQube 25.4 (latest)
- [x] ESLint 7.x (oldest supported)
- [x] ESLint 8.x
- [x] ESLint 9.x (latest)

author_association: MEMBER