diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d22fe0..d03e85c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [#84](https://github.com/green-code-initiative/creedengo-javascript/pull/84) Add rule GCI535 "No imported number format library"
+- Add SonarQube-only rule GCI2536 "Optimize the browserslist tag in package.json"
## [3.1.0] - 2026-05-10
diff --git a/sonar-plugin/pom.xml b/sonar-plugin/pom.xml
index 712eec7..8053cff 100644
--- a/sonar-plugin/pom.xml
+++ b/sonar-plugin/pom.xml
@@ -48,7 +48,7 @@
${encoding}
${encoding}
- 3.0.0
+ main-SNAPSHOT
13.0.0.3026
11.8.0.37897
1.25.1.3002
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPlugin.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPlugin.java
index 01f9fb9..3ff6f63 100644
--- a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPlugin.java
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPlugin.java
@@ -28,6 +28,7 @@ public void define(Context context) {
context.addExtensions(
ESLintRulesBundle.class,
JavaScriptRulesDefinition.class,
+ OptimizeBrowserslistTagInPackageJsonSensor.class,
JavaScriptRuleRepository.class,
TypeScriptRulesDefinition.class,
TypeScriptRuleRepository.class
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinition.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinition.java
index 871afa0..dff9428 100644
--- a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinition.java
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinition.java
@@ -24,6 +24,8 @@
import org.sonar.api.server.rule.RulesDefinition;
import org.sonarsource.analyzer.commons.RuleMetadataLoader;
+import static java.util.List.of;
+
public class JavaScriptRulesDefinition implements RulesDefinition {
private static final String METADATA_LOCATION = "org/green-code-initiative/rules/javascript";
@@ -49,6 +51,8 @@ public void define(Context context) {
ruleMetadataLoader.addRulesByAnnotatedClass(repository, checks);
DeprecatedEcoCodeRule.addOnRepository(repository, JavaScriptRuleRepository.OLD_KEY, checks);
+ ruleMetadataLoader.addRulesByAnnotatedClass(repository, of(OptimizeBrowserslistTagInPackageJsonRule.class));
+
repository.done();
}
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRule.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRule.java
new file mode 100644
index 0000000..13a29f6
--- /dev/null
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRule.java
@@ -0,0 +1,65 @@
+/*
+ * Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.javascript;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.sonar.check.Rule;
+
+@Rule(key = OptimizeBrowserslistTagInPackageJsonRule.KEY)
+public final class OptimizeBrowserslistTagInPackageJsonRule {
+
+ public static final String KEY = "GCI2536";
+
+ static final String ISSUE_MESSAGE = "Move the browserslist configuration to a \"production\" target.";
+
+ private static final Pattern BROWSERSLIST_PATTERN = Pattern.compile(
+ "\"browserslist\"\\s*:\\s*(\\{.*?\\}|\\[.*?\\]|\".*?\")", Pattern.DOTALL);
+
+ private OptimizeBrowserslistTagInPackageJsonRule() {
+ }
+
+ static boolean isNonCompliant(String packageJsonContents) {
+ Matcher matcher = BROWSERSLIST_PATTERN.matcher(packageJsonContents);
+ if (!matcher.find()) {
+ return false;
+ }
+
+ String browserslistConfiguration = matcher.group(1).trim();
+ if (browserslistConfiguration.startsWith("{")) {
+ return !browserslistConfiguration.contains("\"production\"");
+ }
+
+ return true;
+ }
+
+ static int browserslistLineNumber(String packageJsonContents) {
+ Matcher matcher = BROWSERSLIST_PATTERN.matcher(packageJsonContents);
+ if (!matcher.find()) {
+ return 1;
+ }
+
+ return lineNumberAt(packageJsonContents, matcher.start());
+ }
+
+ private static int lineNumberAt(String text, int index) {
+ return 1 + (int) text.substring(0, index).chars().filter(c -> c == '\n').count();
+ }
+
+}
diff --git a/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensor.java b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensor.java
new file mode 100644
index 0000000..b94e5cb
--- /dev/null
+++ b/sonar-plugin/src/main/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensor.java
@@ -0,0 +1,79 @@
+/*
+ * Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.javascript;
+
+import java.io.IOException;
+
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.scanner.sensor.ProjectSensor;
+
+public class OptimizeBrowserslistTagInPackageJsonSensor implements ProjectSensor {
+
+ private static final RuleKey RULE_KEY = RuleKey.of(JavaScriptRuleRepository.KEY, OptimizeBrowserslistTagInPackageJsonRule.KEY);
+
+ private final FileSystem fileSystem;
+
+ public OptimizeBrowserslistTagInPackageJsonSensor(FileSystem fileSystem) {
+ this.fileSystem = fileSystem;
+ }
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor
+ .name("Optimize browserslist tag in package.json")
+ .createIssuesForRuleRepository(JavaScriptRuleRepository.KEY);
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ InputFile packageJson = findPackageJson();
+ if (packageJson == null || packageJson.isEmpty()) {
+ return;
+ }
+
+ try {
+ String contents = packageJson.contents();
+ if (!OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(contents)) {
+ return;
+ }
+
+ NewIssue issue = context.newIssue().forRule(RULE_KEY);
+ NewIssueLocation location = issue.newLocation()
+ .on(packageJson)
+ .at(packageJson.selectLine(OptimizeBrowserslistTagInPackageJsonRule.browserslistLineNumber(contents)))
+ .message(OptimizeBrowserslistTagInPackageJsonRule.ISSUE_MESSAGE);
+
+ issue.at(location).save();
+ } catch (IOException exception) {
+ throw new IllegalStateException("Unable to read package.json", exception);
+ }
+ }
+
+ private InputFile findPackageJson() {
+ FilePredicate packageJsonPredicate = fileSystem.predicates().hasRelativePath("package.json");
+ return fileSystem.inputFile(packageJsonPredicate);
+ }
+
+}
\ No newline at end of file
diff --git a/sonar-plugin/src/main/resources/org/greencodeinitiative/creedengo/profiles/javascript_profile.json b/sonar-plugin/src/main/resources/org/greencodeinitiative/creedengo/profiles/javascript_profile.json
index c542671..a411343 100644
--- a/sonar-plugin/src/main/resources/org/greencodeinitiative/creedengo/profiles/javascript_profile.json
+++ b/sonar-plugin/src/main/resources/org/greencodeinitiative/creedengo/profiles/javascript_profile.json
@@ -14,6 +14,7 @@
"GCI505",
"GCI523",
"GCI530",
- "GCI535"
+ "GCI535",
+ "GCI2536"
]
}
diff --git a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPluginTest.java b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPluginTest.java
index c6d07b9..5c842fb 100644
--- a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPluginTest.java
+++ b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptPluginTest.java
@@ -31,7 +31,7 @@ void extensions() {
SonarRuntime sonarRuntime = mock(SonarRuntime.class);
Plugin.Context context = new Plugin.Context(sonarRuntime);
new JavaScriptPlugin().define(context);
- assertThat(context.getExtensions()).hasSize(5);
+ assertThat(context.getExtensions()).hasSize(6);
}
}
diff --git a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinitionTest.java b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinitionTest.java
index bdc3546..09c948d 100644
--- a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinitionTest.java
+++ b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/JavaScriptRulesDefinitionTest.java
@@ -41,6 +41,7 @@ void createRepository() {
assertThat(repository.isExternal()).isFalse();
assertThat(repository.language()).isEqualTo("js");
assertThat(repository.key()).isEqualTo("creedengo-javascript");
+ assertThat(repository.rule(OptimizeBrowserslistTagInPackageJsonRule.KEY)).isNotNull();
}
}
diff --git a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRuleTest.java b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRuleTest.java
new file mode 100644
index 0000000..ac92d2c
--- /dev/null
+++ b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonRuleTest.java
@@ -0,0 +1,101 @@
+/*
+ * Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.javascript;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class OptimizeBrowserslistTagInPackageJsonRuleTest {
+
+ @Test
+ void detectNonCompliantBrowserslistArray() {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": [
+ "defaults"
+ ]
+ }
+ """;
+
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(packageJson)).isTrue();
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.browserslistLineNumber(packageJson)).isEqualTo(3);
+ }
+
+ @Test
+ void acceptProductionBrowserslistObject() {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": {
+ "production": [
+ "last 2 Chrome versions"
+ ],
+ "development": [
+ "last 1 Chrome version"
+ ]
+ }
+ }
+ """;
+
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(packageJson)).isFalse();
+ }
+
+ @Test
+ void acceptPackageJsonWithoutBrowserslist() {
+ String packageJson = """
+ {
+ "name": "app"
+ }
+ """;
+
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(packageJson)).isFalse();
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.browserslistLineNumber(packageJson)).isEqualTo(1);
+ }
+
+ @Test
+ void detectNonCompliantBrowserslistObjectWithoutProductionKey() {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": {
+ "development": [
+ "last 1 Chrome version"
+ ]
+ }
+ }
+ """;
+
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(packageJson)).isTrue();
+ }
+
+ @Test
+ void detectNonCompliantBrowserslistString() {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": "defaults and > 0.5%"
+ }
+ """;
+
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.isNonCompliant(packageJson)).isTrue();
+ assertThat(OptimizeBrowserslistTagInPackageJsonRule.browserslistLineNumber(packageJson)).isEqualTo(3);
+ }
+
+}
\ No newline at end of file
diff --git a/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensorTest.java b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensorTest.java
new file mode 100644
index 0000000..ef24f28
--- /dev/null
+++ b/sonar-plugin/src/test/java/org/greencodeinitiative/creedengo/javascript/OptimizeBrowserslistTagInPackageJsonSensorTest.java
@@ -0,0 +1,143 @@
+/*
+ * Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
+ * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.greencodeinitiative.creedengo.javascript;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.Answers;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class OptimizeBrowserslistTagInPackageJsonSensorTest {
+
+ @Test
+ void reportIssueForNonCompliantPackageJson() throws Exception {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": [
+ "defaults"
+ ]
+ }
+ """;
+
+ FileSystem fileSystem = mock(FileSystem.class);
+ FilePredicates predicates = mock(FilePredicates.class);
+ FilePredicate predicate = mock(FilePredicate.class);
+ InputFile inputFile = mock(InputFile.class);
+ SensorContext context = mock(SensorContext.class);
+ NewIssue issue = mock(NewIssue.class, Answers.RETURNS_SELF);
+ NewIssueLocation location = mock(NewIssueLocation.class, Answers.RETURNS_SELF);
+ TextRange textRange = mock(TextRange.class);
+
+ when(fileSystem.predicates()).thenReturn(predicates);
+ when(predicates.hasRelativePath("package.json")).thenReturn(predicate);
+ when(fileSystem.inputFile(predicate)).thenReturn(inputFile);
+ when(inputFile.isEmpty()).thenReturn(false);
+ when(inputFile.contents()).thenReturn(packageJson);
+ when(inputFile.selectLine(3)).thenReturn(textRange);
+ when(context.newIssue()).thenReturn(issue);
+ when(issue.newLocation()).thenReturn(location);
+
+ new OptimizeBrowserslistTagInPackageJsonSensor(fileSystem).execute(context);
+
+ verify(context).newIssue();
+ verify(issue).forRule(eq(org.sonar.api.rule.RuleKey.of(JavaScriptRuleRepository.KEY, OptimizeBrowserslistTagInPackageJsonRule.KEY)));
+ verify(location).on(inputFile);
+ verify(location).at(textRange);
+ verify(location).message(OptimizeBrowserslistTagInPackageJsonRule.ISSUE_MESSAGE);
+ verify(issue).save();
+ }
+
+ @Test
+ void doNotReportIssueWhenPackageJsonIsCompliant() throws Exception {
+ String packageJson = """
+ {
+ "name": "app",
+ "browserslist": {
+ "production": [
+ "last 2 Chrome versions"
+ ]
+ }
+ }
+ """;
+
+ FileSystem fileSystem = mock(FileSystem.class);
+ FilePredicates predicates = mock(FilePredicates.class);
+ FilePredicate predicate = mock(FilePredicate.class);
+ InputFile inputFile = mock(InputFile.class);
+ SensorContext context = mock(SensorContext.class);
+
+ when(fileSystem.predicates()).thenReturn(predicates);
+ when(predicates.hasRelativePath("package.json")).thenReturn(predicate);
+ when(fileSystem.inputFile(predicate)).thenReturn(inputFile);
+ when(inputFile.isEmpty()).thenReturn(false);
+ when(inputFile.contents()).thenReturn(packageJson);
+
+ assertThatCode(() -> new OptimizeBrowserslistTagInPackageJsonSensor(fileSystem).execute(context)).doesNotThrowAnyException();
+
+ verify(context, never()).newIssue();
+ }
+
+ @Test
+ void doNotReportIssueWhenPackageJsonNotFound() {
+ FileSystem fileSystem = mock(FileSystem.class);
+ FilePredicates predicates = mock(FilePredicates.class);
+ FilePredicate predicate = mock(FilePredicate.class);
+ SensorContext context = mock(SensorContext.class);
+
+ when(fileSystem.predicates()).thenReturn(predicates);
+ when(predicates.hasRelativePath("package.json")).thenReturn(predicate);
+ when(fileSystem.inputFile(predicate)).thenReturn(null);
+
+ assertThatCode(() -> new OptimizeBrowserslistTagInPackageJsonSensor(fileSystem).execute(context)).doesNotThrowAnyException();
+
+ verify(context, never()).newIssue();
+ }
+
+ @Test
+ void doNotReportIssueWhenPackageJsonIsEmpty() {
+ FileSystem fileSystem = mock(FileSystem.class);
+ FilePredicates predicates = mock(FilePredicates.class);
+ FilePredicate predicate = mock(FilePredicate.class);
+ InputFile inputFile = mock(InputFile.class);
+ SensorContext context = mock(SensorContext.class);
+
+ when(fileSystem.predicates()).thenReturn(predicates);
+ when(predicates.hasRelativePath("package.json")).thenReturn(predicate);
+ when(fileSystem.inputFile(predicate)).thenReturn(inputFile);
+ when(inputFile.isEmpty()).thenReturn(true);
+
+ assertThatCode(() -> new OptimizeBrowserslistTagInPackageJsonSensor(fileSystem).execute(context)).doesNotThrowAnyException();
+
+ verify(context, never()).newIssue();
+ }
+
+}
\ No newline at end of file
diff --git a/test-project/package.json b/test-project/package.json
index 48eccd6..6693dc6 100644
--- a/test-project/package.json
+++ b/test-project/package.json
@@ -13,6 +13,9 @@
"lint:report": "eslint src/. -f json -o eslint-report.json",
"sonar": "sonar"
},
+ "browserslist": [
+ "defaults"
+ ],
"devDependencies": {
"@creedengo/eslint-plugin": "../eslint-plugin",
"@eslint/js": "^10.0.1",
diff --git a/test-project/sonar-project.properties b/test-project/sonar-project.properties
index 764219c..1866cc0 100644
--- a/test-project/sonar-project.properties
+++ b/test-project/sonar-project.properties
@@ -1,3 +1,3 @@
sonar.exclusions=node_modules
-sonar.sources=src
+sonar.sources=src,package.json
sonar.projectKey=creedengo-javascript-test-project
diff --git a/test-project/yarn.lock b/test-project/yarn.lock
index 4cd76f6..4b25748 100644
--- a/test-project/yarn.lock
+++ b/test-project/yarn.lock
@@ -21,10 +21,10 @@ __metadata:
"@creedengo/eslint-plugin@file:../eslint-plugin::locator=creedengo-javascript-test-project%40workspace%3A.":
version: 3.1.0
- resolution: "@creedengo/eslint-plugin@file:../eslint-plugin#../eslint-plugin::hash=30e64e&locator=creedengo-javascript-test-project%40workspace%3A."
+ resolution: "@creedengo/eslint-plugin@file:../eslint-plugin#../eslint-plugin::hash=b22b11&locator=creedengo-javascript-test-project%40workspace%3A."
peerDependencies:
eslint: ^9.0.0 || ^10.0.0
- checksum: 10c0/35357906578cb26b758f44fb8fdb12656de3a6d3297d97002f3a1c755066b81e1321badd1f4a01a9e9d156b0545b5611774c2ed83e80600168c134f0dc0846fd
+ checksum: 10c0/b46e04628e19ea19cec1c78d01cbed468c031304326eedb1a30d39aa8451e1347daee2c7fd823a509f14df81d2801fba82e6d4a0fcecfad832b5d69eeed7bd17
languageName: node
linkType: hard