Alexandre Alapetite 1 год назад
Родитель
Сommit
692e30465d
6 измененных файлов с 140 добавлено и 123 удалено
  1. 4 0
      Docker/README.md
  2. 0 1
      app/Models/Feed.php
  3. 5 5
      composer.lock
  4. 15 11
      docs/en/developers/03_Running_tests.md
  5. 114 104
      package-lock.json
  6. 2 2
      package.json

+ 4 - 0
Docker/README.md

@@ -162,6 +162,10 @@ They need to be compiled manually:
 cd ./FreshRSS/
 docker build --pull --tag freshrss/freshrss:oldest -f Docker/Dockerfile-Oldest .
 docker build --pull --tag freshrss/freshrss:newest -f Docker/Dockerfile-Newest .
+
+# Example of use:
+make composer-test
+docker run --rm -e FRESHRSS_ENV=development -e TZ=UTC -v $(pwd):/var/www/FreshRSS freshrss/freshrss:oldest bin/composer test
 ```
 
 ## Supported databases

+ 0 - 1
app/Models/Feed.php

@@ -350,7 +350,6 @@ class FreshRSS_Feed extends Minz_Model {
 		if ($this->url != '') {
 			/**
 			 * @throws Minz_FileNotExistException
-			 * @phpstan-ignore if.alwaysFalse
 			 */
 			if (CACHE_PATH == '') {
 				throw new Minz_FileNotExistException(

+ 5 - 5
composer.lock

@@ -315,16 +315,16 @@
         },
         {
             "name": "phpstan/phpstan",
-            "version": "1.11.9",
+            "version": "1.11.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "e370bcddadaede0c1716338b262346f40d296f82"
+                "reference": "640410b32995914bde3eed26fa89552f9c2c082f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e370bcddadaede0c1716338b262346f40d296f82",
-                "reference": "e370bcddadaede0c1716338b262346f40d296f82",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f",
+                "reference": "640410b32995914bde3eed26fa89552f9c2c082f",
                 "shasum": ""
             },
             "require": {
@@ -369,7 +369,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-08-01T16:25:18+00:00"
+            "time": "2024-08-08T09:02:50+00:00"
         },
         {
             "name": "phpstan/phpstan-phpunit",

+ 15 - 11
docs/en/developers/03_Running_tests.md

@@ -1,32 +1,36 @@
 # Running tests
 
-FreshRSS is tested with [PHPUnit](https://phpunit.de/). No code should be merged in `edge` if the tests don’t pass.
+FreshRSS is tested with [PHPUnit](https://phpunit.de/), [PHPStan](https://phpstan.org/), [PHP\_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/), and more.
+No code should be merged in `edge` if the tests don’t pass.
 
 ## Locally
 
 As a developer, you can run the test suite on your PC easily with `make` commands. You can run the test suite with:
 
 ```sh
-make test
+cd ./FreshRSS/
+make test-all
 ```
 
-This command downloads the PHPUnit binary and verifies its checksum. If the verification fails, the file is deleted. In this case, you should [open an issue on GitHub](https://github.com/FreshRSS/FreshRSS/issues/new) to let maintainers know about the problem.
-
-Then, it executes PHPUnit in a Docker container. If you don’t use Docker, you can run the command directly with:
+Some syntax, formatting, whitespace, and i18n conventions can be fixed automatically with:
 
 ```sh
-NO_DOCKER=true make test
+make fix-all
 ```
 
-The linter can be run with a `make` command as well:
+Some tests can run inside some Docker images, in particular to test against minimum and maximum versions of PHP:
 
 ```sh
-make lint # to execute the linter on the PHP files
-make lint-fix # or, to fix the errors detected by the linter
+# Prepare
+make composer-test
+docker build --pull --tag freshrss/freshrss:oldest -f Docker/Dockerfile-Oldest .
+docker build --pull --tag freshrss/freshrss:newest -f Docker/Dockerfile-Newest .
+
+# Run
+docker run --rm -e FRESHRSS_ENV=development -e TZ=UTC -v $(pwd):/var/www/FreshRSS freshrss/freshrss:oldest bin/composer test
+docker run --rm -e FRESHRSS_ENV=development -e TZ=UTC -v $(pwd):/var/www/FreshRSS freshrss/freshrss:newest bin/composer test
 ```
 
-Similarly to PHPUnit, it downloads a [PHP\_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) binary (i.e. `phpcs` or `phpcbf` depending on the command) and verifies its checksum.
-
 ## GitHub Actions for Continuous Integration
 
 Tests are automatically run when you open a pull request on GitHub.

+ 114 - 104
package-lock.json

@@ -7,9 +7,9 @@
       "name": "freshrss",
       "license": "AGPL-3.0",
       "devDependencies": {
-        "@eslint/js": "^9.8.0",
+        "@eslint/js": "^9.9.0",
         "@stylistic/stylelint-plugin": "^3.0.0",
-        "eslint": "^9.8.0",
+        "eslint": "^9.9.0",
         "globals": "^15.9.0",
         "markdownlint-cli": "^0.41.0",
         "neostandard": "^0.11.2",
@@ -313,9 +313,9 @@
       }
     },
     "node_modules/@eslint/js": {
-      "version": "9.8.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz",
-      "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==",
+      "version": "9.9.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz",
+      "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==",
       "dev": true,
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -456,15 +456,15 @@
       }
     },
     "node_modules/@stylistic/eslint-plugin": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.1.tgz",
-      "integrity": "sha512-UT0f4t+3sQ/GKW7875NiIIjZJ1Bh4gd7JNfoIkwIQyWqO7wGd0Pqzu0Ho30Ka8MNF5lm++SkVeqAk26vGxoUpg==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.2.tgz",
+      "integrity": "sha512-Ic5oFNM/25iuagob6LiIBkSI/A2y45TsyKtDtODXHRZDy52WfPfeexI6r+OH5+aWN9QGob2Bw+4JRM9/4areWw==",
       "dev": true,
       "dependencies": {
-        "@stylistic/eslint-plugin-js": "2.6.1",
-        "@stylistic/eslint-plugin-jsx": "2.6.1",
-        "@stylistic/eslint-plugin-plus": "2.6.1",
-        "@stylistic/eslint-plugin-ts": "2.6.1",
+        "@stylistic/eslint-plugin-js": "2.6.2",
+        "@stylistic/eslint-plugin-jsx": "2.6.2",
+        "@stylistic/eslint-plugin-plus": "2.6.2",
+        "@stylistic/eslint-plugin-ts": "2.6.2",
         "@types/eslint": "^9.6.0"
       },
       "engines": {
@@ -475,9 +475,9 @@
       }
     },
     "node_modules/@stylistic/eslint-plugin-js": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.1.tgz",
-      "integrity": "sha512-iLOiVzcvqzDGD9U0EuVOX680v+XOPiPAjkxWj+Q6iV2GLOM5NB27tKVOpJY7AzBhidwpRbaLTgg3T4UzYx09jw==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz",
+      "integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==",
       "dev": true,
       "dependencies": {
         "@types/eslint": "^9.6.0",
@@ -493,12 +493,12 @@
       }
     },
     "node_modules/@stylistic/eslint-plugin-jsx": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.1.tgz",
-      "integrity": "sha512-5qHLXqxfY6jubAQfDqrifv41fx7gaqA9svDaChxMI6JiHpEBfh+PXxmm3g+B8gJCYVBTC62Rjl0Ny5QabK58bw==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.2.tgz",
+      "integrity": "sha512-dSXK/fSPA938J1fBi10QmhzLKtZ/2TuyVNHQMk8jUhWfKJDleAogaSqcWNAbN8fwcoe9UWmt/3StiIf2oYC1aQ==",
       "dev": true,
       "dependencies": {
-        "@stylistic/eslint-plugin-js": "^2.6.1",
+        "@stylistic/eslint-plugin-js": "^2.6.2",
         "@types/eslint": "^9.6.0",
         "estraverse": "^5.3.0",
         "picomatch": "^4.0.2"
@@ -511,9 +511,9 @@
       }
     },
     "node_modules/@stylistic/eslint-plugin-plus": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.1.tgz",
-      "integrity": "sha512-z/IYu/q8ipApzNam5utSU+BrXg4pK/Gv9xNbr4eWv/bZppvTWJU62xCO4nw/6r2dHNPnqc7uCHEC7GMlBnPY0A==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.2.tgz",
+      "integrity": "sha512-cANcPASfRvq3VTbbQCrSIXq+2AI0IW68PNYaZoXXS0ENlp7HDB8dmrsJnOgWCcoEvdCB8z/eWcG/eq/v5Qcl+Q==",
       "dev": true,
       "dependencies": {
         "@types/eslint": "^9.6.0",
@@ -524,12 +524,12 @@
       }
     },
     "node_modules/@stylistic/eslint-plugin-ts": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.1.tgz",
-      "integrity": "sha512-Mxl1VMorEG1Hc6oBYPD0+KIJOWkjEF1R0liL7wWgKfwpqOkgmnh5lVdZBrYyfRKOE4RlGcwEFTNai1IW6orgVg==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.2.tgz",
+      "integrity": "sha512-6OEN3VtUNxjgOvWPavnC10MByr1H4zsgwNND3rQXr5lDFv93MLUnTsH+/SH15OkuqdyJgrQILI6b9lYecb1vIg==",
       "dev": true,
       "dependencies": {
-        "@stylistic/eslint-plugin-js": "2.6.1",
+        "@stylistic/eslint-plugin-js": "2.6.2",
         "@types/eslint": "^9.6.0",
         "@typescript-eslint/utils": "^8.0.0"
       },
@@ -585,16 +585,16 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0.tgz",
-      "integrity": "sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz",
+      "integrity": "sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "8.0.0",
-        "@typescript-eslint/type-utils": "8.0.0",
-        "@typescript-eslint/utils": "8.0.0",
-        "@typescript-eslint/visitor-keys": "8.0.0",
+        "@typescript-eslint/scope-manager": "8.1.0",
+        "@typescript-eslint/type-utils": "8.1.0",
+        "@typescript-eslint/utils": "8.1.0",
+        "@typescript-eslint/visitor-keys": "8.1.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.3.1",
         "natural-compare": "^1.4.0",
@@ -618,15 +618,15 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0.tgz",
-      "integrity": "sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.1.0.tgz",
+      "integrity": "sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "8.0.0",
-        "@typescript-eslint/types": "8.0.0",
-        "@typescript-eslint/typescript-estree": "8.0.0",
-        "@typescript-eslint/visitor-keys": "8.0.0",
+        "@typescript-eslint/scope-manager": "8.1.0",
+        "@typescript-eslint/types": "8.1.0",
+        "@typescript-eslint/typescript-estree": "8.1.0",
+        "@typescript-eslint/visitor-keys": "8.1.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -646,13 +646,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0.tgz",
-      "integrity": "sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz",
+      "integrity": "sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "8.0.0",
-        "@typescript-eslint/visitor-keys": "8.0.0"
+        "@typescript-eslint/types": "8.1.0",
+        "@typescript-eslint/visitor-keys": "8.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -663,13 +663,13 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0.tgz",
-      "integrity": "sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz",
+      "integrity": "sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "8.0.0",
-        "@typescript-eslint/utils": "8.0.0",
+        "@typescript-eslint/typescript-estree": "8.1.0",
+        "@typescript-eslint/utils": "8.1.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.3.0"
       },
@@ -687,9 +687,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.1.0.tgz",
+      "integrity": "sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==",
       "dev": true,
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -700,13 +700,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0.tgz",
-      "integrity": "sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz",
+      "integrity": "sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "8.0.0",
-        "@typescript-eslint/visitor-keys": "8.0.0",
+        "@typescript-eslint/types": "8.1.0",
+        "@typescript-eslint/visitor-keys": "8.1.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -752,15 +752,15 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0.tgz",
-      "integrity": "sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.1.0.tgz",
+      "integrity": "sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "8.0.0",
-        "@typescript-eslint/types": "8.0.0",
-        "@typescript-eslint/typescript-estree": "8.0.0"
+        "@typescript-eslint/scope-manager": "8.1.0",
+        "@typescript-eslint/types": "8.1.0",
+        "@typescript-eslint/typescript-estree": "8.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -774,12 +774,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0.tgz",
-      "integrity": "sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz",
+      "integrity": "sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "8.0.0",
+        "@typescript-eslint/types": "8.1.0",
         "eslint-visitor-keys": "^3.4.3"
       },
       "engines": {
@@ -1666,16 +1666,16 @@
       }
     },
     "node_modules/eslint": {
-      "version": "9.8.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz",
-      "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==",
+      "version": "9.9.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.0.tgz",
+      "integrity": "sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.11.0",
         "@eslint/config-array": "^0.17.1",
         "@eslint/eslintrc": "^3.1.0",
-        "@eslint/js": "9.8.0",
+        "@eslint/js": "9.9.0",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@humanwhocodes/retry": "^0.3.0",
         "@nodelib/fs.walk": "^1.2.8",
@@ -1714,6 +1714,14 @@
       },
       "funding": {
         "url": "https://eslint.org/donate"
+      },
+      "peerDependencies": {
+        "jiti": "*"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        }
       }
     },
     "node_modules/eslint-compat-utils": {
@@ -1753,9 +1761,9 @@
       }
     },
     "node_modules/eslint-plugin-n": {
-      "version": "17.10.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.1.tgz",
-      "integrity": "sha512-hm/q37W6efDptJXdwirsm6A257iY6ZNtpoSG0wEzFzjJ3AhL7OhEIhdSR2e4OdYfHO5EDeqlCfFrjf9q208IPw==",
+      "version": "17.10.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.2.tgz",
+      "integrity": "sha512-e+s4eAf5NtJaxPhTNu3qMO0Iz40WANS93w9LQgYcvuljgvDmWi/a3rh+OrNyMHeng6aOWGJO0rCg5lH4zi8yTw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
@@ -1802,9 +1810,9 @@
       }
     },
     "node_modules/eslint-plugin-promise": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.0.0.tgz",
-      "integrity": "sha512-wb1ECT+b90ndBdAujhIdAU8oQ3Vt5gKqP/t78KOmg0ifynrvc2jGR9f6ndbOVNFpKf6jLUBlBBDF3H3Wk0JICg==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.1.0.tgz",
+      "integrity": "sha512-8trNmPxdAy3W620WKDpaS65NlM5yAumod6XeC4LOb+jxlkG4IVcp68c6dXY2ev+uT4U1PtG57YDV6EGAXN0GbQ==",
       "dev": true,
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2083,9 +2091,9 @@
       }
     },
     "node_modules/foreground-child": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
-      "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+      "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
       "dev": true,
       "dependencies": {
         "cross-spawn": "^7.0.0",
@@ -2480,9 +2488,9 @@
       }
     },
     "node_modules/ignore": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
-      "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
       "dev": true,
       "engines": {
         "node": ">= 4"
@@ -3660,9 +3668,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.40",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz",
-      "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==",
+      "version": "8.4.41",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
+      "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
       "dev": true,
       "funding": [
         {
@@ -3694,9 +3702,9 @@
       "dev": true
     },
     "node_modules/postcss-resolve-nested-selector": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.4.tgz",
-      "integrity": "sha512-R6vHqZWgVnTAPq0C+xjyHfEZqfIYboCBVSy24MjxEDm+tIh1BU4O6o7DP7AA7kHzf136d+Qc5duI4tlpHjixDw==",
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz",
+      "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==",
       "dev": true
     },
     "node_modules/postcss-safe-parser": {
@@ -3752,9 +3760,9 @@
       }
     },
     "node_modules/postcss-selector-parser": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
-      "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
       "dev": true,
       "dependencies": {
         "cssesc": "^3.0.0",
@@ -4522,15 +4530,17 @@
       }
     },
     "node_modules/stylelint-scss": {
-      "version": "6.4.1",
-      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.4.1.tgz",
-      "integrity": "sha512-+clI2bQC2FPOt06ZwUlXZZ95IO2C5bKTP0GLN1LNQPVvISfSNcgMKv/VTwym1mK9vnqhHbOk8lO4rj4nY7L9pw==",
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.5.0.tgz",
+      "integrity": "sha512-yOnYlr71wrTPT3rYyUurgTj6Rw7JUtzsZQsiPEjvs+k/yqoYHdweqpw6XN/ARpxjAuvJpddoMUvV8aAIpvUwTg==",
       "dev": true,
       "dependencies": {
+        "css-tree": "2.3.1",
+        "is-plain-object": "5.0.0",
         "known-css-properties": "^0.34.0",
         "postcss-media-query-parser": "^0.2.3",
-        "postcss-resolve-nested-selector": "^0.1.1",
-        "postcss-selector-parser": "^6.1.0",
+        "postcss-resolve-nested-selector": "^0.1.4",
+        "postcss-selector-parser": "^6.1.1",
         "postcss-value-parser": "^4.2.0"
       },
       "engines": {
@@ -4879,14 +4889,14 @@
       }
     },
     "node_modules/typescript-eslint": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0.tgz",
-      "integrity": "sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.1.0.tgz",
+      "integrity": "sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/eslint-plugin": "8.0.0",
-        "@typescript-eslint/parser": "8.0.0",
-        "@typescript-eslint/utils": "8.0.0"
+        "@typescript-eslint/eslint-plugin": "8.1.0",
+        "@typescript-eslint/parser": "8.1.0",
+        "@typescript-eslint/utils": "8.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"

+ 2 - 2
package.json

@@ -34,8 +34,8 @@
     "fix": "npm run rtlcss && npm run stylelint_fix && npm run eslint_fix && npm run markdownlint_fix"
   },
   "devDependencies": {
-    "eslint": "^9.8.0",
-    "@eslint/js": "^9.8.0",
+    "eslint": "^9.9.0",
+    "@eslint/js": "^9.9.0",
     "globals": "^15.9.0",
     "markdownlint-cli": "^0.41.0",
     "neostandard": "^0.11.2",