Skip to content

Commit cb61aeb

Browse files
chore: update ESLint and plugins, simplify config, apply new rules (#4052)
This PR updates ESLint and the ESLint plugins to their latest versions and takes advantage of the new versions to simplify the config. The main cleanup: removed all explicit `plugins: {}` registrations from `eslint.config.mjs`. When passing direct config objects like `js.configs.recommended`, the plugin registration is already included – we were just doing it twice. Two lint warnings are also fixed: - A wrong import style for `eslint-plugin-package-json` (named vs. default) - `playwright/no-duplicate-hooks` is disabled for e2e tests – the rule doesn't handle plain `beforeAll()`/`afterAll()` (Vitest style) correctly and produces false positives. I've created an issue for that: mskelton/eslint-plugin-playwright#443. Built-in Node.js imports were manually updated to use the `node:` prefix (e.g. `require("fs")` → `require("node:fs")`). Minor formatting fixes were applied automatically by `eslint --fix`.
1 parent e7503a4 commit cb61aeb

File tree

12 files changed

+397
-299
lines changed

12 files changed

+397
-299
lines changed

defaultmodules/clock/clock.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ Module.register("clock", {
190190
}
191191

192192
sunWrapperInnerHTML += `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunrise)}</span>`
193-
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunset)}</span>`;
193+
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunset)}</span>`;
194194

195195
sunWrapper.innerHTML = sunWrapperInnerHTML;
196196
digitalWrapper.appendChild(sunWrapper);
@@ -218,8 +218,8 @@ Module.register("clock", {
218218

219219
moonWrapper.innerHTML
220220
= `<span class="${isVisible ? "bright" : ""}">${image} ${showFraction ? illuminatedFractionString : ""}</span>`
221-
+ `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${moonRise ? formatTime(this.config, moonRise) : "..."}</span>`
222-
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${moonSet ? formatTime(this.config, moonSet) : "..."}</span>`;
221+
+ `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${moonRise ? formatTime(this.config, moonRise) : "..."}</span>`
222+
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${moonSet ? formatTime(this.config, moonSet) : "..."}</span>`;
223223
digitalWrapper.appendChild(moonWrapper);
224224
}
225225

defaultmodules/weather/provider-utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ function cardinalToDegrees (direction) {
159159
*/
160160
function validateCoordinates (config, maxDecimals = 4) {
161161
if (config.lat == null || config.lon == null
162-
|| !Number.isFinite(config.lat) || !Number.isFinite(config.lon)) {
162+
|| !Number.isFinite(config.lat) || !Number.isFinite(config.lon)) {
163163
throw new Error("Latitude and longitude are required");
164164
}
165165

defaultmodules/weather/providers/smhi.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,13 @@ class SMHIProvider {
275275
#isSamePeriod (date1, date2, groupBy) {
276276
if (groupBy === "hour") {
277277
return date1.getFullYear() === date2.getFullYear()
278-
&& date1.getMonth() === date2.getMonth()
279-
&& date1.getDate() === date2.getDate()
280-
&& date1.getHours() === date2.getHours();
278+
&& date1.getMonth() === date2.getMonth()
279+
&& date1.getDate() === date2.getDate()
280+
&& date1.getHours() === date2.getHours();
281281
} else { // day
282282
return date1.getFullYear() === date2.getFullYear()
283-
&& date1.getMonth() === date2.getMonth()
284-
&& date1.getDate() === date2.getDate();
283+
&& date1.getMonth() === date2.getMonth()
284+
&& date1.getDate() === date2.getDate();
285285
}
286286
}
287287

defaultmodules/weather/providers/weatherapi.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class WeatherAPIProvider {
221221
return null;
222222
}
223223

224-
const match = /^\s*(\d{1,2}):(\d{2})\s*(AM|PM)\s*$/i.exec(timeValue);
224+
const match = (/^\s*(\d{1,2}):(\d{2})\s*(AM|PM)\s*$/i).exec(timeValue);
225225
if (!match) {
226226
return null;
227227
}

defaultmodules/weather/providers/weatherflow.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const HTTPFetcher = require("#http_fetcher");
88
* Note that the WeatherFlow API does not provide snowfall.
99
*/
1010
class WeatherFlowProvider {
11+
1112
/**
1213
* @param {object} config - Provider configuration
1314
*/
@@ -190,8 +191,8 @@ class WeatherFlowProvider {
190191

191192
// Compare year, month, and day to ensure correct matching across month boundaries
192193
if (hourDate.getFullYear() === forecastDate.getFullYear()
193-
&& hourDate.getMonth() === forecastDate.getMonth()
194-
&& hourDate.getDate() === forecastDate.getDate()) {
194+
&& hourDate.getMonth() === forecastDate.getMonth()
195+
&& hourDate.getDate() === forecastDate.getDate()) {
195196
weather.uvIndex = Math.max(weather.uvIndex, hour.uv || 0);
196197
weather.precipitationAmount += hour.precip || 0;
197198
} else if (hourDate > forecastDate) {

defaultmodules/weather/providers/yr.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,13 @@ class YrProvider {
102102
const data = await response.json();
103103
// Transform single-day response into array format expected by #getStellarInfoForDate
104104
if (data && data.properties) {
105-
this.stellarData = [{
106-
date: data.when.interval[0], // ISO date string
107-
sunrise: data.properties.sunrise,
108-
sunset: data.properties.sunset
109-
}];
105+
this.stellarData = [
106+
{
107+
date: data.when.interval[0], // ISO date string
108+
sunrise: data.properties.sunrise,
109+
sunset: data.properties.sunset
110+
}
111+
];
110112
}
111113
this.stellarDataDate = today;
112114
}

eslint.config.mjs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { defineConfig, globalIgnores } from "eslint/config";
1+
import {defineConfig, globalIgnores} from "eslint/config";
22
import globals from "globals";
3-
import { flatConfigs as importX } from "eslint-plugin-import-x";
3+
import {flatConfigs as importX} from "eslint-plugin-import-x";
44
import js from "@eslint/js";
55
import jsdocPlugin from "eslint-plugin-jsdoc";
6-
import packageJson from "eslint-plugin-package-json";
6+
import {configs as packageJsonConfigs} from "eslint-plugin-package-json";
77
import playwright from "eslint-plugin-playwright";
88
import stylistic from "@stylistic/eslint-plugin";
99
import vitest from "@vitest/eslint-plugin";
@@ -24,8 +24,7 @@ export default defineConfig([
2424
moment: "readonly"
2525
}
2626
},
27-
plugins: { js, stylistic },
28-
extends: [importX.recommended, "js/recommended", jsdocPlugin.configs["flat/recommended"], stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })],
27+
extends: [importX.recommended, js.configs.recommended, jsdocPlugin.configs["flat/recommended"], stylistic.configs.all],
2928
rules: {
3029
"@stylistic/array-element-newline": ["error", "consistent"],
3130
"@stylistic/arrow-parens": ["error", "always"],
@@ -35,14 +34,14 @@ export default defineConfig([
3534
"@stylistic/function-paren-newline": ["error", "consistent"],
3635
"@stylistic/implicit-arrow-linebreak": ["error", "beside"],
3736
"@stylistic/indent": ["error", "tab"],
38-
"@stylistic/max-statements-per-line": ["error", { max: 2 }],
37+
"@stylistic/max-statements-per-line": ["error", {max: 2}],
3938
"@stylistic/multiline-comment-style": "off",
4039
"@stylistic/multiline-ternary": ["error", "always-multiline"],
41-
"@stylistic/newline-per-chained-call": ["error", { ignoreChainWithDepth: 4 }],
40+
"@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}],
4241
"@stylistic/no-extra-parens": "off",
4342
"@stylistic/no-tabs": "off",
4443
"@stylistic/object-curly-spacing": ["error", "always"],
45-
"@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
44+
"@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}],
4645
"@stylistic/operator-linebreak": ["error", "before"],
4746
"@stylistic/padded-blocks": "off",
4847
"@stylistic/quote-props": ["error", "as-needed"],
@@ -51,7 +50,7 @@ export default defineConfig([
5150
"@stylistic/space-before-function-paren": ["error", "always"],
5251
"@stylistic/spaced-comment": "off",
5352
"dot-notation": "error",
54-
eqeqeq: ["error", "always", { null: "ignore" }],
53+
eqeqeq: ["error", "always", {null: "ignore"}],
5554
"id-length": "off",
5655
"import-x/extensions": "error",
5756
"import-x/newline-after-import": "error",
@@ -86,12 +85,11 @@ export default defineConfig([
8685
"js/logger.js",
8786
"tests/**/*.js"
8887
],
89-
rules: { "no-console": "error" }
88+
rules: {"no-console": "error"}
9089
},
9190
{
9291
files: ["**/package.json"],
93-
plugins: { packageJson },
94-
extends: ["packageJson/recommended"]
92+
extends: [packageJsonConfigs.recommended]
9593
},
9694
{
9795
files: ["**/*.mjs"],
@@ -102,15 +100,14 @@ export default defineConfig([
102100
},
103101
sourceType: "module"
104102
},
105-
plugins: { js, stylistic },
106-
extends: [importX.recommended, "js/all", stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })],
103+
extends: [importX.recommended, js.configs.all, stylistic.configs.all],
107104
rules: {
108105
"@stylistic/array-element-newline": "off",
109106
"@stylistic/indent": ["error", "tab"],
110-
"@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
107+
"@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}],
111108
"@stylistic/padded-blocks": ["error", "never"],
112109
"@stylistic/quote-props": ["error", "as-needed"],
113-
"import-x/no-unresolved": ["error", { ignore: ["eslint/config"] }],
110+
"import-x/no-unresolved": ["error", {ignore: ["eslint/config"]}],
114111
"max-lines-per-function": ["error", 100],
115112
"no-magic-numbers": "off",
116113
"one-var": ["error", "never"],
@@ -124,7 +121,6 @@ export default defineConfig([
124121
...vitest.environments.env.globals
125122
}
126123
},
127-
plugins: { vitest },
128124
extends: [vitest.configs.recommended],
129125
rules: {
130126
"vitest/consistent-test-it": "error",
@@ -142,7 +138,7 @@ export default defineConfig([
142138
]
143139
}
144140
],
145-
"vitest/max-nested-describe": ["error", { max: 3 }],
141+
"vitest/max-nested-describe": ["error", {max: 3}],
146142
"vitest/prefer-to-be": "error",
147143
"vitest/prefer-to-have-length": "error",
148144
"max-lines-per-function": "off"
@@ -167,6 +163,13 @@ export default defineConfig([
167163
files: ["tests/e2e/**/*.js"],
168164
extends: [playwright.configs["flat/recommended"]],
169165
rules: {
166+
167+
/*
168+
* Tests use Vitest-style plain beforeAll()/afterAll() calls, not Playwright's
169+
* test.beforeAll() style. The rule incorrectly treats all plain hook calls
170+
* as the same unnamed type, flagging the second hook as a duplicate.
171+
*/
172+
"playwright/no-duplicate-hooks": "off",
170173
"playwright/no-standalone-expect": "off"
171174
}
172175
}

js/alias-resolver.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For a future ESM migration, replace this with a public export/import surface.
44

55
const path = require("node:path");
6-
const Module = require("module");
6+
const Module = require("node:module");
77

88
const root = path.join(__dirname, "..");
99

0 commit comments

Comments
 (0)