mediawiki/extensions/GlobalWatchlist: main (log #2469031)

sourcepatches

This run took 140 seconds.

From d738fe916d943ca33c809054ad15a48de890f2b8 Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Thu, 7 May 2026 07:11:45 +0000
Subject: [PATCH] build: Updating dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4
* basic-ftp: 5.3.0 → 5.3.1
  * https://github.com/advisories/GHSA-rpmf-866q-6p89
* ip-address: 9.0.5 → 10.2.0
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g
* socks: 2.8.5 → 2.8.8
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g

Change-Id: Ibb846942c6ccc271a6fc1134a7c7dd2791c10d14
---
 composer.json                                 |   2 +-
 modules/specialglobalwatchlist/SiteDisplay.js |   1 +
 package-lock.json                             | 971 ++++++++++--------
 package.json                                  |   2 +-
 4 files changed, 551 insertions(+), 425 deletions(-)

diff --git a/composer.json b/composer.json
index ea87f4b..0c86e21 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
 {
 	"require-dev": {
-		"mediawiki/mediawiki-codesniffer": "50.0.0",
+		"mediawiki/mediawiki-codesniffer": "51.0.0",
 		"mediawiki/mediawiki-phan-config": "0.20.0",
 		"mediawiki/minus-x": "2.0.1",
 		"php-parallel-lint/php-console-highlighter": "1.0.0",
diff --git a/modules/specialglobalwatchlist/SiteDisplay.js b/modules/specialglobalwatchlist/SiteDisplay.js
index 649748b..ed594a2 100644
--- a/modules/specialglobalwatchlist/SiteDisplay.js
+++ b/modules/specialglobalwatchlist/SiteDisplay.js
@@ -373,6 +373,7 @@ GlobalWatchlistSiteDisplay.prototype.afterMarkAllAsSeen = function () {
 
 /**
  * Update display after marking a page as seen
+ *
  * @param {string} pageTitle the marked page
  */
 GlobalWatchlistSiteBase.prototype.afterMarkPageAsSeen = function ( pageTitle ) {
diff --git a/package-lock.json b/package-lock.json
index 93c12be..170418d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
 				"@wdio/local-runner": "9.23.0",
 				"@wdio/mocha-framework": "9.15.0",
 				"@wdio/spec-reporter": "9.20.0",
-				"eslint-config-wikimedia": "0.32.3",
+				"eslint-config-wikimedia": "0.32.4",
 				"grunt-banana-checker": "0.13.0",
 				"jsdoc": "4.0.5",
 				"jsdoc-wmf-theme": "1.2.0",
@@ -24,6 +24,7 @@
 			"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
 			"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -138,19 +139,32 @@
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
+			}
+		},
+		"node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
+			"version": "8.59.2",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+			"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
+			"dev": true,
+			"engines": {
+				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
 			}
 		},
 		"node_modules/@es-joy/resolve.exports": {
@@ -563,9 +577,9 @@
 			}
 		},
 		"node_modules/@eslint-community/eslint-utils": {
-			"version": "4.7.0",
-			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
-			"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+			"version": "4.9.1",
+			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+			"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
 			"dev": true,
 			"dependencies": {
 				"eslint-visitor-keys": "^3.4.3"
@@ -581,9 +595,9 @@
 			}
 		},
 		"node_modules/@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true,
 			"engines": {
 				"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -594,6 +608,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
 			"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
@@ -617,6 +632,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
 			"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 			}
@@ -627,6 +643,7 @@
 			"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
 			"deprecated": "Use @eslint/config-array instead",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@humanwhocodes/object-schema": "^2.0.3",
 				"debug": "^4.3.1",
@@ -641,6 +658,7 @@
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
 			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=12.22"
 			},
@@ -654,7 +672,8 @@
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
 			"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
 			"deprecated": "Use @eslint/object-schema instead",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/@inquirer/checkbox": {
 			"version": "4.2.0",
@@ -1194,9 +1213,9 @@
 			}
 		},
 		"node_modules/@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"node_modules/@nodable/entities": {
@@ -1477,9 +1496,9 @@
 			"dev": true
 		},
 		"node_modules/@types/estree": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-			"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+			"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
 			"dev": true
 		},
 		"node_modules/@types/istanbul-lib-coverage": {
@@ -1608,20 +1627,19 @@
 			}
 		},
 		"node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1631,7 +1649,7 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"@typescript-eslint/parser": "^8.46.0",
+				"@typescript-eslint/parser": "^8.54.0",
 				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
@@ -1646,16 +1664,16 @@
 			}
 		},
 		"node_modules/@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1670,14 +1688,14 @@
 			}
 		},
 		"node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1691,13 +1709,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1708,9 +1726,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1724,16 +1742,16 @@
 			}
 		},
 		"node_modules/@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1748,9 +1766,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1761,21 +1779,20 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1789,9 +1806,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-			"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+			"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 			"dev": true,
 			"dependencies": {
 				"balanced-match": "^1.0.0"
@@ -1813,15 +1830,15 @@
 			}
 		},
 		"node_modules/@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1836,12 +1853,12 @@
 			}
 		},
 		"node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"engines": {
@@ -1868,7 +1885,8 @@
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
 			"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/@vitest/pretty-format": {
 			"version": "2.1.9",
@@ -3205,9 +3223,9 @@
 			}
 		},
 		"node_modules/acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true,
 			"bin": {
 				"acorn": "bin/acorn"
@@ -3525,6 +3543,12 @@
 				"@mdn/browser-compat-data": "^5.6.19"
 			}
 		},
+		"node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": {
+			"version": "5.7.6",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"dev": true
+		},
 		"node_modules/ast-types": {
 			"version": "0.13.4",
 			"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
@@ -3699,9 +3723,9 @@
 			}
 		},
 		"node_modules/basic-ftp": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
-			"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+			"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
 			"dev": true,
 			"engines": {
 				"node": ">=10.0.0"
@@ -4147,9 +4171,9 @@
 			}
 		},
 		"node_modules/comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true,
 			"engines": {
 				"node": ">= 12.0.0"
@@ -4804,7 +4828,8 @@
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
 			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/deepmerge-ts": {
 			"version": "7.1.5",
@@ -4886,6 +4911,7 @@
 			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
 			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"esutils": "^2.0.2"
 			},
@@ -5198,13 +5224,13 @@
 			}
 		},
 		"node_modules/enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"dependencies": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			},
 			"engines": {
 				"node": ">=10.13.0"
@@ -5335,6 +5361,7 @@
 			"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
 			"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.2.0",
 				"@eslint-community/regexpp": "^4.6.1",
@@ -5401,46 +5428,47 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"dependencies": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			},
 			"engines": {
 				"node": ">=20 <25"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"dependencies": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -5450,7 +5478,7 @@
 				"node": ">=18.x"
 			},
 			"peerDependencies": {
-				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/globals": {
@@ -5516,31 +5544,31 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"dependencies": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"peerDependencies": {
-				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
@@ -5556,29 +5584,29 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": {
-			"version": "4.2.1",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-			"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+			"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 			"dev": true,
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/espree": {
-			"version": "10.4.0",
-			"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-			"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+			"version": "11.2.0",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+			"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 			"dev": true,
 			"dependencies": {
-				"acorn": "^8.15.0",
+				"acorn": "^8.16.0",
 				"acorn-jsx": "^5.3.2",
-				"eslint-visitor-keys": "^4.2.1"
+				"eslint-visitor-keys": "^5.0.1"
 			},
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
@@ -5608,9 +5636,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"dependencies": {
 				"upath": "^2.0.1"
@@ -5637,9 +5665,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -5711,31 +5739,34 @@
 			}
 		},
 		"node_modules/eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"peerDependencies": {
-				"eslint": ">=8.0.0"
+				"eslint": ">=8.0.0 <9.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"dependencies": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			},
 			"engines": {
 				"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
+			},
+			"peerDependencies": {
+				"eslint": ">=8.38.0"
 			}
 		},
 		"node_modules/eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"dependencies": {
 				"safe-regex": "^2.1.1"
@@ -5815,9 +5846,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.20.0"
@@ -5918,6 +5949,7 @@
 			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 			"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"ansi-styles": "^4.1.0",
 				"supports-color": "^7.1.0"
@@ -5934,6 +5966,7 @@
 			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
 			"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=10"
 			},
@@ -5946,6 +5979,7 @@
 			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"is-glob": "^4.0.3"
 			},
@@ -5984,9 +6018,9 @@
 			}
 		},
 		"node_modules/esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"dependencies": {
 				"estraverse": "^5.1.0"
@@ -6270,7 +6304,8 @@
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/fast-uri": {
 			"version": "3.0.5",
@@ -6406,6 +6441,7 @@
 			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
 			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"flat-cache": "^3.0.4"
 			},
@@ -6485,6 +6521,7 @@
 			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
 			"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"flatted": "^3.2.9",
 				"keyv": "^4.5.3",
@@ -6714,6 +6751,7 @@
 			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
@@ -6830,7 +6868,8 @@
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
 			"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/grunt-banana-checker": {
 			"version": "0.13.0",
@@ -7186,24 +7225,14 @@
 			}
 		},
 		"node_modules/ip-address": {
-			"version": "9.0.5",
-			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
-			"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+			"version": "10.2.0",
+			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+			"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
 			"dev": true,
-			"dependencies": {
-				"jsbn": "1.1.0",
-				"sprintf-js": "^1.1.3"
-			},
 			"engines": {
 				"node": ">= 12"
 			}
 		},
-		"node_modules/ip-address/node_modules/jsbn": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
-			"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
-			"dev": true
-		},
 		"node_modules/is-arrayish": {
 			"version": "0.2.1",
 			"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -7296,6 +7325,7 @@
 			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
 			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -7633,9 +7663,9 @@
 			"dev": true
 		},
 		"node_modules/jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true,
 			"engines": {
 				"node": ">=20.0.0"
@@ -7718,7 +7748,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
 			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/json-stringify-safe": {
 			"version": "5.0.1",
@@ -7865,6 +7896,7 @@
 			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
 			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"prelude-ls": "^1.2.1",
 				"type-check": "~0.4.0"
@@ -7973,7 +8005,8 @@
 			"version": "4.6.2",
 			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
 			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/lodash.pickby": {
 			"version": "4.6.0",
@@ -8614,6 +8647,7 @@
 			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
 			"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@aashutoshrathi/word-wrap": "^1.2.3",
 				"deep-is": "^0.1.3",
@@ -8844,6 +8878,7 @@
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -9046,6 +9081,7 @@
 			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
 			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">= 0.8.0"
 			}
@@ -9615,6 +9651,7 @@
 			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
 			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"glob": "^7.1.3"
 			},
@@ -9904,12 +9941,12 @@
 			}
 		},
 		"node_modules/socks": {
-			"version": "2.8.5",
-			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
-			"integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
+			"version": "2.8.8",
+			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz",
+			"integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==",
 			"dev": true,
 			"dependencies": {
-				"ip-address": "^9.0.5",
+				"ip-address": "^10.1.1",
 				"smart-buffer": "^4.2.0"
 			},
 			"engines": {
@@ -10006,12 +10043,6 @@
 				"node": ">= 10.x"
 			}
 		},
-		"node_modules/sprintf-js": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
-			"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
-			"dev": true
-		},
 		"node_modules/sshpk": {
 			"version": "1.18.0",
 			"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -10560,9 +10591,9 @@
 			"dev": true
 		},
 		"node_modules/tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true,
 			"engines": {
 				"node": ">=6"
@@ -10610,7 +10641,53 @@
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
-			"dev": true
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/tinyglobby": {
+			"version": "0.2.16",
+			"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+			"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+			"dev": true,
+			"dependencies": {
+				"fdir": "^6.5.0",
+				"picomatch": "^4.0.4"
+			},
+			"engines": {
+				"node": ">=12.0.0"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/SuperchupuDev"
+			}
+		},
+		"node_modules/tinyglobby/node_modules/fdir": {
+			"version": "6.5.0",
+			"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+			"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+			"dev": true,
+			"engines": {
+				"node": ">=12.0.0"
+			},
+			"peerDependencies": {
+				"picomatch": "^3 || ^4"
+			},
+			"peerDependenciesMeta": {
+				"picomatch": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/tinyglobby/node_modules/picomatch": {
+			"version": "4.0.4",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+			"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+			"dev": true,
+			"engines": {
+				"node": ">=12"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/jonschlinkert"
+			}
 		},
 		"node_modules/tinyrainbow": {
 			"version": "1.2.0",
@@ -10663,9 +10740,9 @@
 			}
 		},
 		"node_modules/ts-api-utils": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
-			"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+			"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.12"
@@ -10756,6 +10833,7 @@
 			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
 			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"prelude-ls": "^1.2.1"
 			},
@@ -11620,7 +11698,8 @@
 			"version": "1.2.6",
 			"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
 			"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@babel/code-frame": {
 			"version": "7.27.1",
@@ -11672,16 +11751,24 @@
 			"dev": true
 		},
 		"@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"requires": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
+			},
+			"dependencies": {
+				"@typescript-eslint/types": {
+					"version": "8.59.2",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+					"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
+					"dev": true
+				}
 			}
 		},
 		"@es-joy/resolve.exports": {
@@ -11866,18 +11953,18 @@
 			"optional": true
 		},
 		"@eslint-community/eslint-utils": {
-			"version": "4.7.0",
-			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
-			"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+			"version": "4.9.1",
+			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+			"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
 			"dev": true,
 			"requires": {
 				"eslint-visitor-keys": "^3.4.3"
 			}
 		},
 		"@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true
 		},
 		"@eslint/eslintrc": {
@@ -11885,6 +11972,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
 			"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
@@ -11901,13 +11989,15 @@
 			"version": "8.57.1",
 			"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
 			"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@humanwhocodes/config-array": {
 			"version": "0.13.0",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
 			"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@humanwhocodes/object-schema": "^2.0.3",
 				"debug": "^4.3.1",
@@ -11918,13 +12008,15 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
 			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@humanwhocodes/object-schema": {
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
 			"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@inquirer/checkbox": {
 			"version": "4.2.0",
@@ -12256,9 +12348,9 @@
 			}
 		},
 		"@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"@nodable/entities": {
@@ -12452,9 +12544,9 @@
 			"dev": true
 		},
 		"@types/estree": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-			"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+			"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
 			"dev": true
 		},
 		"@types/istanbul-lib-coverage": {
@@ -12583,20 +12675,19 @@
 			}
 		},
 		"@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"requires": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"dependencies": {
 				"ignore": {
@@ -12608,87 +12699,86 @@
 			}
 		},
 		"@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			}
 		},
 		"@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			}
 		},
 		"@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			}
 		},
 		"@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
 			"requires": {}
 		},
 		"@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			}
 		},
 		"@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true
 		},
 		"@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
 			},
 			"dependencies": {
 				"brace-expansion": {
-					"version": "2.0.3",
-					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-					"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+					"version": "2.1.0",
+					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+					"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 					"dev": true,
 					"requires": {
 						"balanced-match": "^1.0.0"
@@ -12706,24 +12796,24 @@
 			}
 		},
 		"@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"requires": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			}
 		},
 		"@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"dependencies": {
@@ -12739,7 +12829,8 @@
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
 			"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@vitest/pretty-format": {
 			"version": "2.1.9",
@@ -13701,9 +13792,9 @@
 			}
 		},
 		"acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true
 		},
 		"acorn-jsx": {
@@ -13935,6 +14026,14 @@
 			"dev": true,
 			"requires": {
 				"@mdn/browser-compat-data": "^5.6.19"
+			},
+			"dependencies": {
+				"@mdn/browser-compat-data": {
+					"version": "5.7.6",
+					"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+					"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+					"dev": true
+				}
 			}
 		},
 		"ast-types": {
@@ -14053,9 +14152,9 @@
 			"dev": true
 		},
 		"basic-ftp": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
-			"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+			"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
 			"dev": true
 		},
 		"bcrypt-pbkdf": {
@@ -14353,9 +14452,9 @@
 			"dev": true
 		},
 		"comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true
 		},
 		"compress-commons": {
@@ -14827,7 +14926,8 @@
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
 			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"deepmerge-ts": {
 			"version": "7.1.5",
@@ -14888,6 +14988,7 @@
 			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
 			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"esutils": "^2.0.2"
 			}
@@ -15125,13 +15226,13 @@
 			}
 		},
 		"enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"requires": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			}
 		},
 		"entities": {
@@ -15226,6 +15327,7 @@
 			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
 			"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@eslint-community/eslint-utils": "^4.2.0",
 				"@eslint-community/regexpp": "^4.6.1",
@@ -15272,6 +15374,7 @@
 					"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 					"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 					"dev": true,
+					"peer": true,
 					"requires": {
 						"ansi-styles": "^4.1.0",
 						"supports-color": "^7.1.0"
@@ -15281,13 +15384,15 @@
 					"version": "4.0.0",
 					"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
 					"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-					"dev": true
+					"dev": true,
+					"peer": true
 				},
 				"glob-parent": {
 					"version": "6.0.2",
 					"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 					"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
 					"dev": true,
+					"peer": true,
 					"requires": {
 						"is-glob": "^4.0.3"
 					}
@@ -15304,43 +15409,41 @@
 			}
 		},
 		"eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"requires": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			}
 		},
 		"eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"requires": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -15376,23 +15479,23 @@
 			}
 		},
 		"eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"requires": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
@@ -15404,20 +15507,20 @@
 					"dev": true
 				},
 				"eslint-visitor-keys": {
-					"version": "4.2.1",
-					"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-					"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+					"version": "5.0.1",
+					"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+					"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 					"dev": true
 				},
 				"espree": {
-					"version": "10.4.0",
-					"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-					"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+					"version": "11.2.0",
+					"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+					"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 					"dev": true,
 					"requires": {
-						"acorn": "^8.15.0",
+						"acorn": "^8.16.0",
 						"acorn-jsx": "^5.3.2",
-						"eslint-visitor-keys": "^4.2.1"
+						"eslint-visitor-keys": "^5.0.1"
 					}
 				},
 				"spdx-expression-parse": {
@@ -15443,9 +15546,9 @@
 			}
 		},
 		"eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"requires": {
 				"upath": "^2.0.1"
@@ -15463,9 +15566,9 @@
 			}
 		},
 		"eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"requires": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -15508,26 +15611,26 @@
 			}
 		},
 		"eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"requires": {}
 		},
 		"eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"requires": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			}
 		},
 		"eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"requires": {
 				"safe-regex": "^2.1.1"
@@ -15582,9 +15685,9 @@
 			}
 		},
 		"eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true
 		},
 		"eslint-plugin-yml": {
@@ -15660,9 +15763,9 @@
 			"dev": true
 		},
 		"esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"requires": {
 				"estraverse": "^5.1.0"
@@ -15865,7 +15968,8 @@
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"fast-uri": {
 			"version": "3.0.5",
@@ -15950,6 +16054,7 @@
 			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
 			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"flat-cache": "^3.0.4"
 			}
@@ -16013,6 +16118,7 @@
 			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
 			"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"flatted": "^3.2.9",
 				"keyv": "^4.5.3",
@@ -16177,6 +16283,7 @@
 			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
 			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
@@ -16266,7 +16373,8 @@
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
 			"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"grunt-banana-checker": {
 			"version": "0.13.0",
@@ -16509,22 +16617,10 @@
 			}
 		},
 		"ip-address": {
-			"version": "9.0.5",
-			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
-			"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
-			"dev": true,
-			"requires": {
-				"jsbn": "1.1.0",
-				"sprintf-js": "^1.1.3"
-			},
-			"dependencies": {
-				"jsbn": {
-					"version": "1.1.0",
-					"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
-					"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
-					"dev": true
-				}
-			}
+			"version": "10.2.0",
+			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+			"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+			"dev": true
 		},
 		"is-arrayish": {
 			"version": "0.2.1",
@@ -16590,7 +16686,8 @@
 			"version": "3.0.3",
 			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
 			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"is-plain-obj": {
 			"version": "2.1.0",
@@ -16855,9 +16952,9 @@
 			"dev": true
 		},
 		"jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true
 		},
 		"jsdoc-wmf-theme": {
@@ -16918,7 +17015,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
 			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"json-stringify-safe": {
 			"version": "5.0.1",
@@ -17057,6 +17155,7 @@
 			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
 			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"prelude-ls": "^1.2.1",
 				"type-check": "~0.4.0"
@@ -17142,7 +17241,8 @@
 			"version": "4.6.2",
 			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
 			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"lodash.pickby": {
 			"version": "4.6.0",
@@ -17606,6 +17706,7 @@
 			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
 			"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@aashutoshrathi/word-wrap": "^1.2.3",
 				"deep-is": "^0.1.3",
@@ -17771,7 +17872,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"path-key": {
 			"version": "3.1.1",
@@ -17916,7 +18018,8 @@
 			"version": "1.2.1",
 			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
 			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"pretty-format": {
 			"version": "30.2.0",
@@ -18352,6 +18455,7 @@
 			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
 			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"glob": "^7.1.3"
 			}
@@ -18551,12 +18655,12 @@
 			"dev": true
 		},
 		"socks": {
-			"version": "2.8.5",
-			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
-			"integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
+			"version": "2.8.8",
+			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz",
+			"integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==",
 			"dev": true,
 			"requires": {
-				"ip-address": "^9.0.5",
+				"ip-address": "^10.1.1",
 				"smart-buffer": "^4.2.0"
 			}
 		},
@@ -18627,12 +18731,6 @@
 			"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
 			"dev": true
 		},
-		"sprintf-js": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
-			"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
-			"dev": true
-		},
 		"sshpk": {
 			"version": "1.18.0",
 			"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -18994,9 +19092,9 @@
 			}
 		},
 		"tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true
 		},
 		"tar-fs": {
@@ -19035,7 +19133,33 @@
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
-			"dev": true
+			"dev": true,
+			"peer": true
+		},
+		"tinyglobby": {
+			"version": "0.2.16",
+			"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+			"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+			"dev": true,
+			"requires": {
+				"fdir": "^6.5.0",
+				"picomatch": "^4.0.4"
+			},
+			"dependencies": {
+				"fdir": {
+					"version": "6.5.0",
+					"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+					"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+					"dev": true,
+					"requires": {}
+				},
+				"picomatch": {
+					"version": "4.0.4",
+					"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+					"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+					"dev": true
+				}
+			}
 		},
 		"tinyrainbow": {
 			"version": "1.2.0",
@@ -19073,9 +19197,9 @@
 			}
 		},
 		"ts-api-utils": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
-			"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+			"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
 			"dev": true,
 			"requires": {}
 		},
@@ -19133,6 +19257,7 @@
 			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
 			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"prelude-ls": "^1.2.1"
 			}
diff --git a/package.json b/package.json
index 12979eb..48b6472 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
 		"@wdio/local-runner": "9.23.0",
 		"@wdio/mocha-framework": "9.15.0",
 		"@wdio/spec-reporter": "9.20.0",
-		"eslint-config-wikimedia": "0.32.3",
+		"eslint-config-wikimedia": "0.32.4",
 		"grunt-banana-checker": "0.13.0",
 		"jsdoc": "4.0.5",
 		"jsdoc-wmf-theme": "1.2.0",
-- 
2.47.3

$ date
--- stdout ---
Thu May  7 07:09:49 UTC 2026

--- end ---
$ git clone file:///srv/git/mediawiki-extensions-GlobalWatchlist.git /src/repo --depth=1 -b master
--- stderr ---
Cloning into '/src/repo'...
--- stdout ---

--- end ---
$ git config user.name libraryupgrader
--- stdout ---

--- end ---
$ git config user.email tools.libraryupgrader@tools.wmflabs.org
--- stdout ---

--- end ---
$ git submodule update --init
--- stdout ---

--- end ---
$ grr init
--- stdout ---
Installed commit-msg hook.

--- end ---
$ git show-ref refs/heads/master
--- stdout ---
ea7c86f4713dab284bdca67275240302595d8bf6 refs/heads/master

--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "@wdio/mocha-framework": {
      "name": "@wdio/mocha-framework",
      "severity": "high",
      "isDirect": true,
      "via": [
        "mocha"
      ],
      "effects": [],
      "range": ">=6.1.19",
      "nodes": [
        "node_modules/@wdio/mocha-framework"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "basic-ftp": {
      "name": "basic-ftp",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1117726,
          "name": "basic-ftp",
          "dependency": "basic-ftp",
          "title": "basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering",
          "url": "https://github.com/advisories/GHSA-rpmf-866q-6p89",
          "severity": "high",
          "cwe": [
            "CWE-400",
            "CWE-770"
          ],
          "cvss": {
            "score": 7.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
          },
          "range": "<=5.3.0"
        }
      ],
      "effects": [],
      "range": "<=5.3.0",
      "nodes": [
        "node_modules/basic-ftp"
      ],
      "fixAvailable": true
    },
    "form-data": {
      "name": "form-data",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1109540,
          "name": "form-data",
          "dependency": "form-data",
          "title": "form-data uses unsafe random function in form-data for choosing boundary",
          "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4",
          "severity": "critical",
          "cwe": [
            "CWE-330"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<2.5.4"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<2.5.4",
      "nodes": [
        "node_modules/form-data"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "ip-address": {
      "name": "ip-address",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1117683,
          "name": "ip-address",
          "dependency": "ip-address",
          "title": "ip-address has XSS in Address6 HTML-emitting methods",
          "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g",
          "severity": "moderate",
          "cwe": [
            "CWE-79"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<=10.1.0"
        }
      ],
      "effects": [
        "socks"
      ],
      "range": "<=10.1.0",
      "nodes": [
        "node_modules/ip-address"
      ],
      "fixAvailable": true
    },
    "mocha": {
      "name": "mocha",
      "severity": "high",
      "isDirect": false,
      "via": [
        "serialize-javascript"
      ],
      "effects": [
        "@wdio/mocha-framework"
      ],
      "range": "8.0.0 - 12.0.0-beta-2",
      "nodes": [
        "node_modules/mocha"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "mwbot": {
      "name": "mwbot",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        "request"
      ],
      "effects": [
        "wdio-mediawiki"
      ],
      "range": ">=0.1.6",
      "nodes": [
        "node_modules/mwbot"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "qs": {
      "name": "qs",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1113719,
          "name": "qs",
          "dependency": "qs",
          "title": "qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion",
          "url": "https://github.com/advisories/GHSA-6rw7-vpxm-498p",
          "severity": "moderate",
          "cwe": [
            "CWE-20"
          ],
          "cvss": {
            "score": 3.7,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": "<6.14.1"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<6.14.1",
      "nodes": [
        "node_modules/qs"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "request": {
      "name": "request",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1096727,
          "name": "request",
          "dependency": "request",
          "title": "Server-Side Request Forgery in Request",
          "url": "https://github.com/advisories/GHSA-p8p7-x288-28g6",
          "severity": "moderate",
          "cwe": [
            "CWE-918"
          ],
          "cvss": {
            "score": 6.1,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"
          },
          "range": "<=2.88.2"
        },
        "form-data",
        "qs",
        "tough-cookie"
      ],
      "effects": [
        "mwbot"
      ],
      "range": "*",
      "nodes": [
        "node_modules/request"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "serialize-javascript": {
      "name": "serialize-javascript",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1113686,
          "name": "serialize-javascript",
          "dependency": "serialize-javascript",
          "title": "Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString()",
          "url": "https://github.com/advisories/GHSA-5c6j-r48x-rmvq",
          "severity": "high",
          "cwe": [
            "CWE-96"
          ],
          "cvss": {
            "score": 8.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"
          },
          "range": "<=7.0.2"
        },
        {
          "source": 1115723,
          "name": "serialize-javascript",
          "dependency": "serialize-javascript",
          "title": "Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects",
          "url": "https://github.com/advisories/GHSA-qj8w-gfj5-8c6v",
          "severity": "moderate",
          "cwe": [
            "CWE-400",
            "CWE-834"
          ],
          "cvss": {
            "score": 5.9,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"
          },
          "range": "<7.0.5"
        }
      ],
      "effects": [
        "mocha"
      ],
      "range": "<=7.0.4",
      "nodes": [
        "node_modules/serialize-javascript"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "socks": {
      "name": "socks",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        "ip-address"
      ],
      "effects": [],
      "range": "2.7.2 - 2.8.6",
      "nodes": [
        "node_modules/socks"
      ],
      "fixAvailable": true
    },
    "tough-cookie": {
      "name": "tough-cookie",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1097682,
          "name": "tough-cookie",
          "dependency": "tough-cookie",
          "title": "tough-cookie Prototype Pollution vulnerability",
          "url": "https://github.com/advisories/GHSA-72xf-g2v4-qvf3",
          "severity": "moderate",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 6.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"
          },
          "range": "<4.1.3"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<4.1.3",
      "nodes": [
        "node_modules/tough-cookie"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "wdio-mediawiki": {
      "name": "wdio-mediawiki",
      "severity": "moderate",
      "isDirect": true,
      "via": [
        "mwbot"
      ],
      "effects": [],
      "range": "<=5.1.0",
      "nodes": [
        "node_modules/wdio-mediawiki"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 0,
      "moderate": 6,
      "high": 4,
      "critical": 2,
      "total": 12
    },
    "dependencies": {
      "prod": 1,
      "dev": 902,
      "optional": 37,
      "peer": 1,
      "peerOptional": 0,
      "total": 902
    }
  }
}

--- end ---
$ /usr/bin/composer install
--- stderr ---
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 37 installs, 0 updates, 0 removals
  - Locking composer/pcre (3.3.2)
  - Locking composer/semver (3.4.4)
  - Locking composer/spdx-licenses (1.5.10)
  - Locking composer/xdebug-handler (3.0.5)
  - Locking danog/advanced-json-rpc (v3.2.3)
  - Locking dealerdirect/phpcodesniffer-composer-installer (v1.2.1)
  - Locking doctrine/deprecations (1.1.6)
  - Locking mediawiki/mediawiki-codesniffer (v50.0.0)
  - Locking mediawiki/mediawiki-phan-config (0.20.0)
  - Locking mediawiki/minus-x (2.0.1)
  - Locking mediawiki/phan-taint-check-plugin (9.1.0)
  - Locking netresearch/jsonmapper (v5.0.1)
  - Locking phan/phan (6.0.2)
  - Locking phan/tolerant-php-parser (v0.2.0)
  - Locking phan/var_representation_polyfill (0.1.4)
  - Locking php-parallel-lint/php-console-color (v1.0.1)
  - Locking php-parallel-lint/php-console-highlighter (v1.0.0)
  - Locking php-parallel-lint/php-parallel-lint (v1.4.0)
  - Locking phpcsstandards/phpcsextra (1.4.0)
  - Locking phpcsstandards/phpcsutils (1.2.2)
  - Locking phpdocumentor/reflection-common (2.2.0)
  - Locking phpdocumentor/reflection-docblock (6.0.3)
  - Locking phpdocumentor/type-resolver (2.0.0)
  - Locking phpstan/phpdoc-parser (2.3.2)
  - Locking psr/container (2.0.2)
  - Locking psr/log (3.0.2)
  - Locking sabre/event (6.1.0)
  - Locking squizlabs/php_codesniffer (3.13.5)
  - Locking symfony/console (v8.0.9)
  - Locking symfony/deprecation-contracts (v3.7.0)
  - Locking symfony/polyfill-ctype (v1.37.0)
  - Locking symfony/polyfill-intl-grapheme (v1.37.0)
  - Locking symfony/polyfill-intl-normalizer (v1.37.0)
  - Locking symfony/polyfill-mbstring (v1.37.0)
  - Locking symfony/service-contracts (v3.7.0)
  - Locking symfony/string (v8.0.8)
  - Locking webmozart/assert (2.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 37 installs, 0 updates, 0 removals
    0 [>---------------------------]    0 [->--------------------------]
  - Installing squizlabs/php_codesniffer (3.13.5): Extracting archive
  - Installing dealerdirect/phpcodesniffer-composer-installer (v1.2.1): Extracting archive
  - Installing composer/pcre (3.3.2): Extracting archive
  - Installing phpcsstandards/phpcsutils (1.2.2): Extracting archive
  - Installing phpcsstandards/phpcsextra (1.4.0): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.37.0): Extracting archive
  - Installing composer/spdx-licenses (1.5.10): Extracting archive
  - Installing composer/semver (3.4.4): Extracting archive
  - Installing mediawiki/mediawiki-codesniffer (v50.0.0): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.37.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.37.0): Extracting archive
  - Installing symfony/polyfill-ctype (v1.37.0): Extracting archive
  - Installing symfony/string (v8.0.8): Extracting archive
  - Installing symfony/deprecation-contracts (v3.7.0): Extracting archive
  - Installing psr/container (2.0.2): Extracting archive
  - Installing symfony/service-contracts (v3.7.0): Extracting archive
  - Installing symfony/console (v8.0.9): Extracting archive
  - Installing sabre/event (6.1.0): Extracting archive
  - Installing phan/var_representation_polyfill (0.1.4): Extracting archive
  - Installing phan/tolerant-php-parser (v0.2.0): Extracting archive
  - Installing netresearch/jsonmapper (v5.0.1): Extracting archive
  - Installing webmozart/assert (2.3.0): Extracting archive
  - Installing phpstan/phpdoc-parser (2.3.2): Extracting archive
  - Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
  - Installing doctrine/deprecations (1.1.6): Extracting archive
  - Installing phpdocumentor/type-resolver (2.0.0): Extracting archive
  - Installing phpdocumentor/reflection-docblock (6.0.3): Extracting archive
  - Installing danog/advanced-json-rpc (v3.2.3): Extracting archive
  - Installing psr/log (3.0.2): Extracting archive
  - Installing composer/xdebug-handler (3.0.5): Extracting archive
  - Installing phan/phan (6.0.2): Extracting archive
  - Installing mediawiki/phan-taint-check-plugin (9.1.0): Extracting archive
  - Installing mediawiki/mediawiki-phan-config (0.20.0): Extracting archive
  - Installing mediawiki/minus-x (2.0.1): Extracting archive
  - Installing php-parallel-lint/php-console-color (v1.0.1): Extracting archive
  - Installing php-parallel-lint/php-console-highlighter (v1.0.0): Extracting archive
  - Installing php-parallel-lint/php-parallel-lint (v1.4.0): Extracting archive
  0/35 [>---------------------------]   0%
 28/35 [======================>-----]  80%
 34/35 [===========================>]  97%
 35/35 [============================] 100%
1 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
16 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
--- stdout ---
PHP CodeSniffer Config installed_paths set to ../../mediawiki/mediawiki-codesniffer,../../phpcsstandards/phpcsextra,../../phpcsstandards/phpcsutils

--- end ---
Upgrading n:eslint-config-wikimedia from 0.32.3 -> 0.32.4
$ /usr/bin/npm install
--- stderr ---
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated glob@7.2.3: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
--- stdout ---

added 882 packages, and audited 883 packages in 18s

199 packages are looking for funding
  run `npm fund` for details

12 vulnerabilities (6 moderate, 4 high, 2 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
$ ./node_modules/.bin/eslint . --fix
--- stdout ---

/src/repo/modules/specialglobalwatchlist/EntryBase.js
  50:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types
  56:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/MultiSiteWrapper.js
   7:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined  jsdoc/no-undefined-types
  10:1  warning  The type 'GlobalWatchlistDebugger' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteBase.js
    8:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
    9:1  warning  The type 'GlobalWatchlistLinker' is undefined          jsdoc/no-undefined-types
   12:1  warning  The type 'GlobalWatchlistWatchlistUtils' is undefined  jsdoc/no-undefined-types
  318:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  443:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  445:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  457:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  506:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  514:1  warning  This line has a length of 103. Maximum allowed is 100  max-len
  557:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  567:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteDisplay.js
   14:1   warning  The type 'GlobalWatchlistDebugger' is undefined                                    jsdoc/no-undefined-types
   15:1   warning  The type 'GlobalWatchlistLinker' is undefined                                      jsdoc/no-undefined-types
   18:1   warning  The type 'GlobalWatchlistWatchlistUtils' is undefined                              jsdoc/no-undefined-types
   48:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types
  105:1   warning  This line has a length of 111. Maximum allowed is 100                              max-len
  248:1   warning  This line has a length of 107. Maximum allowed is 100                              max-len
  261:26  warning  All possible CSS classes should be documented. See https://w.wiki/PS2 for details  mediawiki/class-doc
  296:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/WatchlistUtils.js
    7:1  warning  The type 'GlobalWatchlistLinker' is undefined               jsdoc/no-undefined-types
   72:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  113:1  warning  This line has a length of 101. Maximum allowed is 100       max-len
  167:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  313:1  warning  The type 'GlobalWatchlistSiteBase.getTagList' is undefined  jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  325:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  408:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  429:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  429:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  432:1  warning  This line has a length of 110. Maximum allowed is 100       max-len
  446:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  548:1  warning  This line has a length of 105. Maximum allowed is 100       max-len

/src/repo/modules/specialglobalwatchlist/WikibaseHandler.js
    9:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
   13:1  warning  This line has a length of 104. Maximum allowed is 100  max-len
   15:1  warning  This line has a length of 101. Maximum allowed is 100  max-len
  207:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  239:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/getSettings.js
  24:1  warning  The type 'GlobalWatchlistDebugger' is undefined  jsdoc/no-undefined-types

✖ 47 problems (0 errors, 47 warnings)


--- end ---
$ ./node_modules/.bin/eslint . -f json
--- stdout ---
[{"filePath":"/src/repo/.eslintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/.stylelintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/composer.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/extension.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/i18n/en.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/i18n/qqq.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/jsdoc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/.eslintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/getsettingserror/getSettings.error.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/Debug.js","messages":[],"suppressedMessages":[{"ruleId":"no-console","severity":2,"message":"Unexpected console statement.","line":25,"column":3,"nodeType":"MemberExpression","messageId":"unexpected","endLine":25,"endColumn":14,"suggestions":[{"messageId":"removeConsole","data":{"propertyName":"log"},"fix":{"range":[717,757],"text":""},"desc":"Remove the console.log()."}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-console","severity":2,"message":"Unexpected console statement.","line":29,"column":4,"nodeType":"MemberExpression","messageId":"unexpected","endLine":29,"endColumn":15,"suggestions":[{"messageId":"removeConsole","data":{"propertyName":"log"},"fix":{"range":[828,853],"text":""},"desc":"Remove the console.log()."}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-console","severity":2,"message":"Unexpected console statement.","line":62,"column":2,"nodeType":"MemberExpression","messageId":"unexpected","endLine":62,"endColumn":15,"suggestions":[{"messageId":"removeConsole","data":{"propertyName":"error"},"fix":{"range":[1718,1748],"text":""},"desc":"Remove the console.error()."}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/EntryBase.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistWikibaseHandler' is undefined.","line":50,"column":1,"nodeType":"Block","endLine":50,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistWikibaseHandler' is undefined.","line":56,"column":1,"nodeType":"Block","endLine":56,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Represents a base entry of any type that is shown\n *\n * @class GlobalWatchlistEntryBase\n * @abstract\n *\n * @constructor\n * @param {Object} info Should have all of the properties that are documented below\n */\nfunction GlobalWatchlistEntryBase( info ) {\n\t/**\n\t * @property {string} entryType Either 'edit' or 'log'\n\t */\n\tthis.entryType = info.entryType;\n\n\t/**\n\t * @property {string|boolean} timestamp Either `false` or a string to display\n\t */\n\tthis.timestamp = info.timestamp;\n\n\t/**\n\t * @property {string|null} timestampTitle Either `null` for single changes, or\n\t *   a string to display as a tooltip for grouped edits\n\t */\n\tthis.timestampTitle = info.timestampTitle;\n\n\t/**\n\t * @property {string|boolean} expiry Either `false` or a string explaining when the\n\t *   watchlist entry expires\n\t */\n\tthis.expiry = info.expiry;\n\n\t/**\n\t * @property {string|boolean} flags Either `false` or a string of flags to show\n\t */\n\tthis.flags = info.flags;\n\n\t/**\n\t * @property {string} userDisplay Raw HTML to show for the user(s) that made this entry\n\t */\n\tthis.userDisplay = info.userDisplay;\n\n\t/**\n\t * @property {string} title Title of the entry\n\t */\n\tthis.title = info.title;\n\n\t/**\n\t * @property {jQuery} $titleMsg Display text for the title of this entry, might be\n\t *   changed by {@link GlobalWatchlistWikibaseHandler}\n\t */\n\tthis.$titleMsg = $( document.createTextNode( info.title ) );\n\n\t/**\n\t * @property {number} ns Namespace for this entry, can be used by\n\t *   {@link GlobalWatchlistWikibaseHandler} to decide if a label should be added.\n\t */\n\tthis.ns = info.ns;\n\n\t/**\n\t * @property {string|boolean} commentDisplay Either `false` or a raw HTML string for\n\t *   the parsed comment that should be shown\n\t */\n\tthis.commentDisplay = info.commentDisplay;\n\n\t/**\n\t * @property {jQuery|boolean} tagsDisplay Either `false` or a jQuery object for the\n\t *   parsed tags information that should be shown\n\t */\n\tthis.tagsDisplay = info.tagsDisplay;\n}\n\nmodule.exports = GlobalWatchlistEntryBase;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/EntryEdits.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/EntryLog.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/Linker.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/MultiSiteWrapper.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":7,"column":1,"nodeType":"Block","endLine":7,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistDebugger' is undefined.","line":10,"column":1,"nodeType":"Block","endLine":10,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Shared helper for Special:GlobalWatchlist\n *\n * @class GlobalWatchlistMultiSiteWrapper\n * @constructor\n *\n * @param {Function} SiteClass {@link GlobalWatchlistSiteDisplay}, used to create\n *    the individual site objects\n * @param {Object} config User configuration to use\n * @param {GlobalWatchlistDebugger} globalWatchlistDebug Shared debugger instance\n */\nfunction GlobalWatchlistMultiSiteWrapper( SiteClass, config, globalWatchlistDebug ) {\n\tconst GlobalWatchlistLinker = require( './Linker.js' );\n\tconst GlobalWatchlistWatchlistUtils = require( './WatchlistUtils.js' );\n\n\t// Set the Access-Control-Max-Age header - T268267\n\t// Set the Api-User-Agent header - T262177\n\tconst apiConfig = {\n\t\tajax: {\n\t\t\theaders: {\n\t\t\t\t'Access-Control-Max-Age': 300,\n\t\t\t\t'Api-User-Agent': 'GlobalWatchlist-MediaWiki/' + mw.config.get( 'wgVersion' )\n\t\t\t}\n\t\t}\n\t};\n\n\tlet linker;\n\t/**\n\t * @property {Array} siteList The individual sites\n\t */\n\tthis.siteList = config.siteList.map( ( site ) => {\n\t\tlinker = new GlobalWatchlistLinker( site );\n\t\treturn new SiteClass(\n\t\t\tglobalWatchlistDebug,\n\t\t\tlinker,\n\t\t\tconfig,\n\t\t\tnew mw.ForeignApi( '//' + site + mw.util.wikiScript( 'api' ), apiConfig ),\n\t\t\tnew GlobalWatchlistWatchlistUtils( linker ),\n\t\t\tsite\n\t\t);\n\t} );\n\n\t/**\n\t * @property {boolean} whether to ask the user to confirm their decision when\n\t * marking all sites as seen\n\t */\n\tthis.confirmMarkAllSitesSeen = config.confirmAllSites;\n}\n\n/**\n * Promise that all of the sites have retrieved their watchlists\n *\n * @param {Object} config User configuration to use. Needs to be passed rather\n *   than using the configuration we got in the constructor because some parts\n *   of it can change (specifically whether to group results by page, and the\n *   timestamp of the start of the call that is used when marking sites as seen).\n * @return {Promise} Promise that all watchlists were retrieved\n */\nGlobalWatchlistMultiSiteWrapper.prototype.getAllWatchlists = function ( config ) {\n\treturn Promise.all(\n\t\tthis.siteList.map( ( site ) => {\n\t\t\t// Reset in case it failed earlier\n\t\t\tsite.apiError = false;\n\n\t\t\treturn site.getWatchlist( config );\n\t\t} )\n\t);\n};\n\n/**\n * Promise that all of the sites have called markAllAsSeen\n *\n * @return {Promise} Promise that all sites were marked as seen\n */\nGlobalWatchlistMultiSiteWrapper.prototype.markAllSitesSeen = function () {\n\tconst that = this;\n\n\treturn new Promise( ( resolve, reject ) => {\n\t\tlet getConfirmation;\n\n\t\tif ( that.confirmMarkAllSitesSeen ) {\n\t\t\tgetConfirmation = OO.ui.confirm(\n\t\t\t\tmw.msg( 'globalwatchlist-markseen-allconfirm' )\n\t\t\t);\n\t\t} else {\n\t\t\tgetConfirmation = Promise.resolve( true );\n\t\t}\n\n\t\t/**\n\t\t * If the user opted to require confirmation, getConfirmation is the Promise\n\t\t * returned by OO.ui.confirm that resolves to the user's decision (boolean value,\n\t\t * true means that the user confirmed the intention to mark all sites as seen,\n\t\t * false means user cancelled). If the user didn't opt to require confirmation,\n\t\t * we didn't check, but to avoid code duplication we just pretend we checked and\n\t\t * that the answer was confirming the decision to mark all sites as seen, and so\n\t\t * getConfirmation is a Promise that just always resolves to true.\n\t\t */\n\t\tgetConfirmation.then(\n\t\t\t( confirmed ) => {\n\t\t\t\tif ( confirmed ) {\n\t\t\t\t\tPromise.all(\n\t\t\t\t\t\tthat.siteList.map( ( site ) => site.markAllAsSeen() )\n\t\t\t\t\t).then( () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\treject();\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t} );\n};\n\nmodule.exports = GlobalWatchlistMultiSiteWrapper;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/SettingsTour.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/SiteBase.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistDebugger' is undefined.","line":8,"column":1,"nodeType":"Block","endLine":8,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistLinker' is undefined.","line":9,"column":1,"nodeType":"Block","endLine":9,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistWatchlistUtils' is undefined.","line":12,"column":1,"nodeType":"Block","endLine":12,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":318,"column":1,"nodeType":"Block","endLine":318,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":443,"column":1,"nodeType":"Block","endLine":443,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":445,"column":1,"nodeType":"Block","endLine":445,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":457,"column":1,"nodeType":"Block","endLine":457,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":506,"column":1,"nodeType":"Block","endLine":506,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 103. Maximum allowed is 100.","line":514,"column":1,"nodeType":"Program","messageId":"max","endLine":514,"endColumn":104},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":557,"column":1,"nodeType":"Block","endLine":557,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteDisplay' is undefined.","line":567,"column":1,"nodeType":"Block","endLine":567,"endColumn":1}],"suppressedMessages":[{"ruleId":"no-unused-vars","severity":2,"message":"'reject' is defined but never used.","line":87,"column":33,"nodeType":"Identifier","messageId":"unusedVar","endLine":87,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'pageTitle' is defined but never used.","line":322,"column":68,"nodeType":"Identifier","messageId":"unusedVar","endLine":322,"endColumn":77,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'summary' is defined but never used.","line":450,"column":64,"nodeType":"Identifier","messageId":"unusedVar","endLine":450,"endColumn":71,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'siteinfo' is defined but never used.","line":450,"column":73,"nodeType":"Identifier","messageId":"unusedVar","endLine":450,"endColumn":81,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'pageTitle' is defined but never used.","line":562,"column":69,"nodeType":"Identifier","messageId":"unusedVar","endLine":562,"endColumn":78,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'unwatched' is defined but never used.","line":562,"column":80,"nodeType":"Identifier","messageId":"unusedVar","endLine":562,"endColumn":89,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":11,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* eslint-disable no-unused-vars */\n/**\n * Represents a specific site\n *\n * @class GlobalWatchlistSiteBase\n * @abstract\n *\n * @param {GlobalWatchlistDebugger} globalWatchlistDebug Debugger instance to log to\n * @param {GlobalWatchlistLinker} linker Linker instance to use\n * @param {Object} config User configuration\n * @param {mw.ForeignApi} api Instance of mw.ForeignApi for this site\n * @param {GlobalWatchlistWatchlistUtils} watchlistUtils WatchlistUtils instance for this site\n * @param {string} urlFragment string for which site this represents\n */\nfunction GlobalWatchlistSiteBase(\n\tglobalWatchlistDebug,\n\tlinker,\n\tconfig,\n\tapi,\n\twatchlistUtils,\n\turlFragment\n) {\n\t// Logger to send debug info to\n\tthis.debugLogger = globalWatchlistDebug;\n\n\t// User config and other settings, retrieved from getSettings\n\tthis.config = config;\n\n\t// The api object to interact with\n\tthis.apiObject = api;\n\n\t// Utility methods (GlobalWatchlistWatchlistUtils)\n\tthis.watchlistUtils = watchlistUtils;\n\n\t// Site identifier in url format\n\tthis.site = urlFragment;\n\n\t// Linker utility (GlobalWatchlistLinker)\n\tthis.linker = linker;\n\n\t// Site identifier in format that can be used for element attributes\n\tthis.siteID = encodeURIComponent( urlFragment.replace( /\\./g, '_' ) );\n\n\t// Whether this site had any changes to show\n\tthis.isEmpty = false;\n\n\t// Cached information about the tags of a site\n\tthis.tags = {};\n\n\t// Whether there was an error when trying to use the API. To be able to use Promise.all,\n\t// API failures still resolve the Promise rather than rejecting it. If Promise.allSettled\n\t// becomes available for use, this should no longer be needed\n\tthis.apiError = false;\n}\n\n/**\n * Shortcut for sending information to the debug logger\n *\n * @param {string} msg Message for debug entry\n * @param {string} [extraInfo] Extra information for debug entry\n */\nGlobalWatchlistSiteBase.prototype.debug = function ( msg, extraInfo ) {\n\tthis.debugLogger.info( this.site + ':' + msg, extraInfo );\n};\n\n/**\n * Shortcut for sending errors to the debug logger\n *\n * @param {string} msg Message for error entry\n * @param {Object} data Extra information for error entry\n */\nGlobalWatchlistSiteBase.prototype.error = function ( msg, data ) {\n\tthis.debugLogger.error( this.site + ':' + msg, data );\n};\n\n/**\n * API handler for debugging and avoiding actual important actions when testing client-side\n *\n * @param {string} func Function name\n * @param {Object} content Content to send to the api\n * @param {string} name Name, for logging purposes\n * @return {Promise} Result of the api call\n */\nGlobalWatchlistSiteBase.prototype.api = function ( func, content, name ) {\n\tconst that = this;\n\n\treturn new Promise( ( resolve, reject ) => {\n\t\tthat.debug( 'API.' + name + ' (called), with func & content:', [ func, content ] );\n\t\tthat.apiObject[ func ]( content ).then( ( response ) => {\n\t\t\tthat.debug(\n\t\t\t\t'API.' + name + ' (result); func, content, & response',\n\t\t\t\t[ func, content, response ]\n\t\t\t);\n\t\t\tresolve( response );\n\t\t} ).catch( ( code, data ) => {\n\t\t\tthat.error( 'API.' + name + ' ' + code, data );\n\t\t\tthat.apiError = true;\n\n\t\t\tconst $userNotification = $( '<div>' )\n\t\t\t\t.append(\n\t\t\t\t\tmw.message( 'globalwatchlist-api-error', that.site ).escaped(),\n\t\t\t\t\tthat.apiObject.getErrorMessage( data )\n\t\t\t\t);\n\n\t\t\tmw.notify(\n\t\t\t\t$userNotification,\n\t\t\t\t{\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tautoHide: false\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// See above on apiError for why this resolves instead of rejecting\n\t\t\t// since we don't know what exactly the caller was expected, just\n\t\t\t// resolve \"error\" and leave the handling for the caller\n\t\t\tresolve( 'ERROR' );\n\t\t} );\n\t} );\n};\n\n/**\n * Get the changes on a user's watchlist\n *\n * This method calls itself recursively until there are no remaining changes to retrieve,\n * using the `continue` functionality.\n *\n * @param {number} iteration iteration count\n * @param {string} continueFrom value of wlcontinue in the previous call\n * @return {Promise} Promise of api result\n */\nGlobalWatchlistSiteBase.prototype.actuallyGetWatchlist = function ( iteration, continueFrom ) {\n\tconst that = this;\n\n\treturn new Promise( ( resolve ) => {\n\t\tconst query = {\n\t\t\taction: 'query',\n\t\t\tformatversion: 2,\n\t\t\tlist: 'watchlist',\n\t\t\twllimit: 'max',\n\t\t\twlprop: that.config.watchlistQueryProps,\n\t\t\twlshow: that.config.watchlistQueryShow,\n\t\t\twltype: that.config.watchlistQueryTypes,\n\t\t\tresponselanginfo: 1\n\t\t};\n\t\tif ( iteration > 1 ) {\n\t\t\tquery.wlcontinue = continueFrom;\n\t\t} else {\n\t\t\tquery.meta = 'siteinfo';\n\t\t\tquery.siprop = that.isWikibase === undefined ?\n\t\t\t\t// the check for Wikibase Handler is needed only once for the site\n\t\t\t\t'general|namespaces' :\n\t\t\t\t'general';\n\t\t\tif ( !that.config.languageData ) {\n\t\t\t\tquery.meta += '|languageinfo';\n\t\t\t\tquery.liprop = 'dir';\n\t\t\t}\n\t\t\tif ( !that.labelsData ) {\n\t\t\t\tquery.meta += '|userinfo';\n\t\t\t\tquery.uiprop = 'watchlistlabels';\n\t\t\t}\n\t\t}\n\t\tif ( !that.config.fastMode ) {\n\t\t\tquery.wlallrev = true;\n\t\t}\n\n\t\tthat.api( 'get', query, 'actuallyGetWatchlist #' + iteration ).then( ( response ) => {\n\t\t\tif ( response === 'ERROR' ) {\n\t\t\t\tresolve( {\n\t\t\t\t\twlraw: [],\n\t\t\t\t\trtl: undefined\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst wlraw = response.query.watchlist;\n\t\t\tconst langinfo = response.query.languageinfo;\n\t\t\tif ( langinfo ) {\n\t\t\t\tthat.config.languageData = langinfo;\n\t\t\t\tthat.debug( 'language data', langinfo );\n\t\t\t\tif ( that.config.lang && !langinfo[ that.config.lang ] ) {\n\t\t\t\t\tthat.config.lang = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( response.query.userinfo ) {\n\t\t\t\tconst labelinfo = response.query.userinfo.watchlistlabels;\n\t\t\t\tif ( labelinfo ) {\n\t\t\t\t\tthat.labelsData = [];\n\t\t\t\t\tlabelinfo.forEach( ( item ) => {\n\t\t\t\t\t\tthis.labelsData[ item.id ] = item.name;\n\t\t\t\t\t} );\n\t\t\t\t\tthat.debug( 'user labels', labelinfo );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( response.query.namespaces ) {\n\t\t\t\tconst wbdefaultmodels = [ 'wikibase-item', 'wikibase-property', 'wikibase-lexeme', 'EntitySchema' ];\n\t\t\t\tconst wbns = { wikibase: [], entity: [] };\n\t\t\t\tconst wbnsNames = { wikibase: [], entity: [] };\n\t\t\t\tObject.values( response.query.namespaces ).forEach( ( ns ) => {\n\t\t\t\t\tconst index = ns.defaultcontentmodel === 'EntitySchema' ? 'entity' : 'wikibase';\n\t\t\t\t\tif ( wbdefaultmodels.includes( ns.defaultcontentmodel ) ) {\n\t\t\t\t\t\twbns[ index ].push( ns.id );\n\t\t\t\t\t\tif ( ns.name ) {\n\t\t\t\t\t\t\twbnsNames[ index ].push( ns.name );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( ns.canonical && ns.canonical !== ns.name ) {\n\t\t\t\t\t\t\twbnsNames[ index ].push( ns.canonical );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tthat.isWikibase = wbns.wikibase.length + wbns.entity.length > 0;\n\t\t\t\tif ( that.isWikibase && response.uselang ) {\n\t\t\t\t\tthat.direction = that.config.languageData[ response.uselang ].dir;\n\t\t\t\t\tthat.debug( 'changing direction', that.direction );\n\t\t\t\t}\n\n\t\t\t\tif ( that.isWikibase && !that.wikibaseHandler ) {\n\t\t\t\t\t// Instance of GlobalWatchlistWikibaseHandler, only used for wikibase\n\t\t\t\t\t// Don't create it if it will never be needed\n\t\t\t\t\tconst GlobalWatchlistWikibaseHandler = require( './WikibaseHandler.js' );\n\t\t\t\t\tconst wikibaseLang = that.config.lang || response.uselang || mw.config.get( 'wgUserLanguage' );\n\t\t\t\t\tthat.debug( 'config lang', that.config.lang );\n\t\t\t\t\tthat.debug( 'response uselang', response.uselang );\n\t\t\t\t\tthat.debug( 'wgUserLanguage', mw.config.get( 'wgUserLanguage' ) );\n\t\t\t\t\tthat.debug( 'wikibaseLang', wikibaseLang );\n\t\t\t\t\tthat.wikibaseHandler = new GlobalWatchlistWikibaseHandler(\n\t\t\t\t\t\tthat.debugLogger,\n\t\t\t\t\t\tthat.apiObject,\n\t\t\t\t\t\twikibaseLang,\n\t\t\t\t\t\twbns,\n\t\t\t\t\t\twbnsNames\n\t\t\t\t\t);\n\t\t\t\t\tthat.debug( 'Wikibase handler created', that.site );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rtl = that.direction === 'rtl' || response.query.general && response.query.general.rtl;\n\n\t\t\tif ( response.continue && response.continue.wlcontinue ) {\n\t\t\t\tthat.actuallyGetWatchlist(\n\t\t\t\t\titeration + 1,\n\t\t\t\t\tresponse.continue.wlcontinue\n\t\t\t\t).then( ( innerResponse ) => {\n\t\t\t\t\tresolve( {\n\t\t\t\t\t\t// If there was an error in the recursive call, this just\n\t\t\t\t\t\t// adds an empty array. getWatchlist checks this.apiError\n\t\t\t\t\t\t// before assuming that an empty response means nothing to show\n\t\t\t\t\t\twlraw: wlraw.concat( innerResponse.wlraw ),\n\t\t\t\t\t\t// `rtl` is present only in the outermost call, `innerResponse.rtl`\n\t\t\t\t\t\t// will always be `undefined`\n\t\t\t\t\t\trtl: rtl\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tresolve( { wlraw, rtl } );\n\t\t\t}\n\t\t} );\n\t} );\n};\n\n/**\n * Update the strikethrough and text for entries being watched/unwatched\n *\n * Calls the API to actually unwatch/rewatch a page\n *\n * Calls `processUpdateWatched` to update the display (either add or remove the strikethrough,\n *   and update the text shown)\n *\n * If fast mode is not enabled, calls `getAssociatedTalkPage` to determine the talk/subject page\n *   associated with the one that was unwatched/rewatched, and then uses `processUpdateWatched`\n *   to update the display of any entries for the associated page\n *\n * @param {string} pageTitle Title of the page to watch or unwatch\n * @param {string} func Either 'watch' or 'unwatch'\n */\nGlobalWatchlistSiteBase.prototype.changeWatched = function ( pageTitle, func ) {\n\tthis.debug( 'changeWatched - Going to ' + func + ': ' + pageTitle );\n\tconst that = this;\n\tthis.api( func, pageTitle, 'updateWatched' );\n\tthis.processUpdateWatched( pageTitle, func === 'unwatch' );\n\tif ( !this.config.fastMode ) {\n\t\tthis.getAssociatedPageTitle( pageTitle ).then( ( associatedTitle ) => {\n\t\t\tthat.processUpdateWatched( associatedTitle, func === 'unwatch' );\n\t\t\t// TODO re-add functionality for old checkChangesShown\n\t\t} );\n\t}\n};\n\n/**\n * Mark page as read\n *\n * Calls the API to reset notification timestamp for a page\n *\n * @param {string} pageTitle Title of the page to mark as read\n * @return {Promise} that resolves after the api call is made and after `afterMarkPageAsSeen`\n * is called, not necessarily after the api call is finished.\n */\nGlobalWatchlistSiteBase.prototype.markPageAsSeen = function ( pageTitle ) {\n\tconst that = this;\n\n\treturn new Promise( ( resolve ) => {\n\t\tconst setter = {\n\t\t\taction: 'setnotificationtimestamp',\n\t\t\ttitles: pageTitle,\n\t\t\ttimestamp: that.config.time.toISOString()\n\t\t};\n\t\tthat.api( 'postWithEditToken', setter );\n\n\t\tthat.afterMarkPageAsSeen( pageTitle );\n\n\t\t// Done within a promise so that display can ensure re-rendering occurs after\n\t\t// entries are updated\n\t\tresolve();\n\t} );\n};\n\n/**\n * Update display after marking a page as read\n *\n * Overriden in {@link GlobalWatchlistSiteDisplay}\n *\n * @param {string} pageTitle Page that was marked as read\n */\nGlobalWatchlistSiteBase.prototype.afterMarkPageAsSeen = function ( pageTitle ) {\n\t// STUB\n};\n\n/**\n * Returns the talk/subject page associated with a given page, since entries for the associated page\n *   also need to have their text and strikethrough updated on unwatching/rewatching\n *\n * @param {string} pageTitle Title of the page for which to retrieve the associated page\n * @return {Promise} Promise of api result\n */\nGlobalWatchlistSiteBase.prototype.getAssociatedPageTitle = function ( pageTitle ) {\n\tconst that = this;\n\treturn new Promise( ( resolve ) => {\n\t\tconst query = {\n\t\t\taction: 'query',\n\t\t\tprop: 'info',\n\t\t\ttitles: pageTitle,\n\t\t\tinprop: 'associatedpage',\n\t\t\tformatversion: 2\n\t\t};\n\t\tthat.api( 'get', query, 'getAssociatedPageTitle' ).then( ( response ) => {\n\t\t\tresolve( response.query.pages[ 0 ].associatedpage );\n\t\t} );\n\t} );\n};\n\n/**\n * Get the tags for a wiki, loading them if not already available (in fast mode we don't retrieve\n * tags information for the watchlist, so this returns an empty object)\n *\n * Once this is called once, the tag info is stored in this.tags and future calls with return early\n *\n * @return {Promise} Resolves with the tags that where retrieved, or an empty object if we are\n *   in fast mode\n */\nGlobalWatchlistSiteBase.prototype.getTagList = function () {\n\tconst that = this;\n\treturn new Promise( ( resolve ) => {\n\t\tif ( that.config.fastMode || Object.keys( that.tags ).length > 0 ) {\n\t\t\t// Either we are in fast mode, and we should return an empty object, which\n\t\t\t// is the default value of that.tags, or we already fetched the tags info\n\t\t\t// and its already available in that.tags\n\t\t\tresolve( that.tags );\n\t\t} else {\n\t\t\tconst query = {\n\t\t\t\taction: 'query',\n\t\t\t\tlist: 'tags',\n\t\t\t\ttglimit: 'max',\n\t\t\t\ttgprop: 'displayname'\n\t\t\t};\n\t\t\tthat.api( 'get', query, 'getTags' ).then( ( response ) => {\n\t\t\t\tconst asObject = {};\n\t\t\t\tresponse.query.tags.forEach( ( tag ) => {\n\t\t\t\t\tasObject[ tag.name ] = ( tag.displayname || false ) ?\n\t\t\t\t\t\tthat.linker.fixLocalLinks( tag.displayname ) :\n\t\t\t\t\t\ttag.name;\n\t\t\t\t} );\n\t\t\t\tthat.debug( 'getTagList', asObject );\n\t\t\t\t// Save for future calls (eg on refresh)\n\t\t\t\tthat.tags = asObject;\n\t\t\t\tresolve( asObject );\n\t\t\t} );\n\t\t}\n\t} );\n};\n\n/**\n * Get the rendered changes for a user's watchlist\n *\n * @param {Object} latestConfig config, can change\n * @return {Promise} Promise that the watchlist was retrieved\n */\nGlobalWatchlistSiteBase.prototype.getWatchlist = function ( latestConfig ) {\n\tthis.config = latestConfig;\n\tconst that = this;\n\treturn new Promise( ( resolve ) => {\n\t\tthat.actuallyGetWatchlist( 1, 0 ).then( ( { wlraw, rtl } ) => {\n\t\t\tif ( !( wlraw && wlraw[ 0 ] ) ) {\n\t\t\t\tif ( that.apiError ) {\n\t\t\t\t\tthat.debug( 'getWatchlist - error' );\n\n\t\t\t\t\t// Include in the normal display section\n\t\t\t\t\tthat.isEmpty = false;\n\n\t\t\t\t\tthat.renderApiFailure();\n\t\t\t\t} else {\n\t\t\t\t\tthat.debug( 'getWatchlist - empty' );\n\t\t\t\t\tthat.isEmpty = true;\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In case it was previously set to true\n\t\t\tthat.isEmpty = false;\n\n\t\t\tthat.debug( 'getWatchlist wlraw', wlraw );\n\n\t\t\tthat.getTagList().then( ( tagsInfo ) => {\n\t\t\t\tconst prelimSummary = that.watchlistUtils.rawToSummary(\n\t\t\t\t\twlraw,\n\t\t\t\t\tthat.config.groupPage,\n\t\t\t\t\ttagsInfo,\n\t\t\t\t\tthat.labelsData || []\n\t\t\t\t);\n\t\t\t\tthat.debug( 'getWatchlist prelimSummary', prelimSummary );\n\n\t\t\t\tthat.makeWikidataList( prelimSummary ).then( ( summary ) => {\n\t\t\t\t\tthat.debug( 'getWatchlist summary', summary );\n\t\t\t\t\tthat.renderWatchlist( summary, { rtl } );\n\t\t\t\t\tresolve();\n\t\t\t\t} );\n\t\t\t} );\n\t\t} );\n\t} );\n};\n\n/**\n * Display the watchlist\n *\n * Overriden in {@link GlobalWatchlistSiteDisplay}\n *\n * @param {GlobalWatchlistEntryBase[]} summary What should be rendered\n * @param {Object} siteinfo Extra site information read live from the wiki\n * @param {boolean|undefined} siteinfo.rtl Whether the site is right-to-left;\n *  `undefined` if unknown\n */\nGlobalWatchlistSiteBase.prototype.renderWatchlist = function ( summary, siteinfo ) {\n\t// STUB\n};\n\n/**\n * Fetch and process wikibase labels when the watchlist is for wikidata\n *\n * @param {GlobalWatchlistEntryBase[]} summary Original summary, with page titles (Q1, P2, L3, etc.)\n * @return {Promise<Array>} Updated summary array, with labels\n */\nGlobalWatchlistSiteBase.prototype.makeWikidataList = function ( summary ) {\n\tconst that = this;\n\n\tif ( !summary || summary.length === 0 ) {\n\t\treturn Promise.resolve( [] );\n\t}\n\n\tif ( !that.isWikibase || that.config.fastMode ) {\n\t\treturn Promise.resolve( summary );\n\t}\n\n\t// Not efficient for now\n\treturn Promise.all(\n\t\tsummary.map( ( item ) => that.wikibaseHandler.addWikibaseLabels( item ) )\n\t);\n};\n\n/**\n * Mark a site as seen\n *\n * @return {Promise} that resolves after the api call is made and after `afterMarkAllAsSeen`\n *   is called, not necessarily after the api call is finished.\n */\nGlobalWatchlistSiteBase.prototype.markAllAsSeen = function () {\n\tthis.debug( 'markSiteAsSeen - marking' );\n\tconst that = this;\n\n\treturn new Promise( ( resolve ) => {\n\t\tconst setter = {\n\t\t\taction: 'setnotificationtimestamp',\n\t\t\tentirewatchlist: true,\n\t\t\ttimestamp: that.config.time.toISOString()\n\t\t};\n\t\tthat.api( 'postWithEditToken', setter, 'actuallyMarkSiteAsSeen' );\n\n\t\tthat.afterMarkAllAsSeen();\n\n\t\t// Done within a promise so that display can ensure re-rendering occurs after\n\t\t// entries are updated\n\t\tresolve();\n\t} );\n};\n\n/**\n * Update display after making a site as seen\n *\n * Overriden in {@link GlobalWatchlistSiteDisplay}\n */\nGlobalWatchlistSiteBase.prototype.afterMarkAllAsSeen = function () {\n\t// STUB\n};\n\n/**\n * Mark a set of pages as seen.\n * This function is not efficient for now, and it will be very improved after T417357 will be resolved.\n *\n * @param {string[]} pageTitles - Array of page titles to mark as seen\n * @return {Promise} resolves when all pages are marked\n */\nGlobalWatchlistSiteBase.prototype.markSectionAsSeen = function ( pageTitles ) {\n\tthis.debug( 'markSectionAsSeen - marking', pageTitles );\n\tconst that = this;\n\n\tif ( !pageTitles || pageTitles.length === 0 ) {\n\t\treturn Promise.resolve();\n\t}\n\n\t// Take first 50 titles (or all if <=50)\n\tconst batch = pageTitles.slice( 0, 50 );\n\tconst remaining = pageTitles.slice( 50 );\n\n\treturn new Promise( ( resolve, reject ) => {\n\t\tconst setter = {\n\t\t\taction: 'setnotificationtimestamp',\n\t\t\ttitles: batch,\n\t\t\ttimestamp: that.config.time.toISOString()\n\t\t};\n\n\t\tthat.api( 'postWithEditToken', setter, 'actuallyMarkSectionAsSeen' )\n\t\t\t.then( () => {\n\t\t\t\t// Update the display immediately for this batch\n\t\t\t\tbatch.forEach( ( title ) => that.afterMarkPageAsSeen( title ) );\n\n\t\t\t\tif ( remaining.length > 0 ) {\n\t\t\t\t\t// Recursively process the next batch\n\t\t\t\t\tthat.markSectionAsSeen( remaining ).then( resolve ).catch( reject );\n\t\t\t\t} else {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( reject );\n\t} );\n};\n\n/**\n * Update entry click handlers, text, and strikethrough for a specific title\n *\n * Overriden in {@link GlobalWatchlistSiteDisplay}\n *\n * @param {string} pageTitle Title of the page that was unwatched/rewatched.\n * @param {boolean} unwatched Whether the page was unwatched\n */\nGlobalWatchlistSiteBase.prototype.processUpdateWatched = function ( pageTitle, unwatched ) {\n\t// STUB\n};\n\n/**\n * Used by {@link GlobalWatchlistSiteDisplay} to still include an output for api failures\n */\nGlobalWatchlistSiteBase.prototype.renderApiFailure = function () {\n\t// STUB\n};\n\nmodule.exports = GlobalWatchlistSiteBase;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/SiteDisplay.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistDebugger' is undefined.","line":14,"column":1,"nodeType":"Block","endLine":14,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistLinker' is undefined.","line":15,"column":1,"nodeType":"Block","endLine":15,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistWatchlistUtils' is undefined.","line":18,"column":1,"nodeType":"Block","endLine":18,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":48,"column":1,"nodeType":"Block","endLine":48,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 111. Maximum allowed is 100.","line":105,"column":1,"nodeType":"Program","messageId":"max","endLine":105,"endColumn":103},{"ruleId":"max-len","severity":1,"message":"This line has a length of 107. Maximum allowed is 100.","line":248,"column":1,"nodeType":"Program","messageId":"max","endLine":248,"endColumn":108},{"ruleId":"mediawiki/class-doc","severity":1,"message":"All possible CSS classes should be documented. See https://w.wiki/PS2 for details.","line":261,"column":26,"nodeType":"CallExpression","endLine":264,"endColumn":62},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":296,"column":1,"nodeType":"Block","endLine":296,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":8,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*\n * Extended version of SiteBase.js for use in jQuery version of Special:GlobalWatchlist\n */\n\nconst GlobalWatchlistSiteBase = require( './SiteBase.js' );\n\n/**\n * Represents a specific site, including the display (used in jQuery display)\n *\n * @class GlobalWatchlistSiteDisplay\n * @extends GlobalWatchlistSiteBase\n *\n * @constructor\n * @param {GlobalWatchlistDebugger} globalWatchlistDebug Debugger instance to log to\n * @param {GlobalWatchlistLinker} linker Linker instance to use\n * @param {Object} config User configuration\n * @param {mw.ForeignApi} api Instance of mw.ForeignApi for this site\n * @param {GlobalWatchlistWatchlistUtils} watchlistUtils WatchlistUtils instance for this site\n * @param {string} urlFragment string for which site this represents\n */\nfunction GlobalWatchlistSiteDisplay(\n\tglobalWatchlistDebug,\n\tlinker,\n\tconfig,\n\tapi,\n\twatchlistUtils,\n\turlFragment\n) {\n\tGlobalWatchlistSiteDisplay.super.call(\n\t\tthis,\n\t\tglobalWatchlistDebug,\n\t\tlinker,\n\t\tconfig,\n\t\tapi,\n\t\twatchlistUtils,\n\t\turlFragment\n\t);\n\n\t// Actual output for this site\n\tthis.$feedDiv = [];\n}\n\nOO.inheritClass( GlobalWatchlistSiteDisplay, GlobalWatchlistSiteBase );\n\n/**\n * Make the links for a row in the watchlist\n *\n * @param {GlobalWatchlistEntryBase} entry Details of the list entry to create\n * @return {jQuery} list item\n */\nGlobalWatchlistSiteDisplay.prototype.makePageLink = function ( entry ) {\n\tconst pageTitle = encodeURIComponent( entry.title ).replace( /'/g, '%27' );\n\tlet $titleMsg = entry.$titleMsg;\n\tif ( !$titleMsg || !$titleMsg.length ) {\n\t\t$titleMsg = $( '<bdi>' ).text( entry.title );\n\t} else if ( !$titleMsg.html() ) {\n\t\t$titleMsg.text( mw.html.escape( entry.title ) );\n\t}\n\tconst $pageLink = $( '<a>' )\n\t\t.attr( 'href', this.linker.linkQuery( 'title=' + pageTitle + '&redirect=no' ) )\n\t\t.attr( 'target', '_blank' )\n\t\t.addClass( 'mw-title ext-globalwatchlist-pagetitle' )\n\t\t.append( $titleMsg );\n\tconst that = this;\n\n\t// Actually set up the $row to be returned\n\tconst $row = $( '<li>' );\n\n\t$row.attr( 'data-site', encodeURIComponent( this.siteID ) );\n\t$row.attr( 'data-title', encodeURIComponent( entry.title ) );\n\n\tif ( entry.timestamp ) {\n\t\t// entry.timestampTitle is either a string explaining grouped changes, or null to ignore\n\t\tconst $timestamp = $( '<span>' )\n\t\t\t.text( entry.timestamp )\n\t\t\t.addClass( 'ext-globalwatchlist-timestamp' )\n\t\t\t.attr( 'title', entry.timestampTitle );\n\t\t$row.append( $timestamp )\n\t\t\t.append( ' ' );\n\t}\n\tif ( entry.expiry ) {\n\t\tconst clockIcon = new OO.ui.IconWidget( {\n\t\t\tclasses: [ 'ext-globalwatchlist-expiry-icon' ],\n\t\t\ticon: 'clock',\n\t\t\ttitle: entry.expiry\n\t\t} );\n\t\t$row.append( clockIcon.$element )\n\t\t\t.append( ' ' );\n\t}\n\tif ( entry.flags ) {\n\t\t// New page / minor edit / bot flag\n\t\t$row.append( $( '<b>' )\n\t\t\t.addClass( 'ext-globalwatchlist-flags' )\n\t\t\t.text( entry.flags ) )\n\t\t\t.append( ' ' );\n\t}\n\tif ( entry.entryType === 'log' ) {\n\t\t// log action description outside fast mode\n\t\tconst $logEntry = $( '<em>' );\n\t\tconst $logAction = $( '<span>' )\n\t\t\t.addClass( 'ext-globalwatchlist-logtype' )\n\t\t\t.text( 'Log: ' + entry.logtype + '/' + entry.logaction );\n\t\t$logEntry.append( $logAction );\n\t\tif ( entry.logdisplay && entry.logdisplay !== '' && this.config.fastMode === false ) {\n\t\t\t// remove HTML links, which can have wrong local URLs, preserving the plain text with bdi tags only\n\t\t\tconst wrapper = document.createElement( 'span' );\n\t\t\twrapper.className = 'ext-globalwatchlist-logdisplay';\n\t\t\twrapper.innerHTML = entry.logdisplay;\n\t\t\t[ ...wrapper.querySelectorAll( '*' ) ].forEach( ( el ) => {\n\t\t\t\tif ( el.tagName.toLowerCase() !== 'bdi' ) {\n\t\t\t\t\tel.replaceWith( ...el.childNodes );\n\t\t\t\t}\n\t\t\t} );\n\t\t\t$logEntry.append( ' (' ).append( $( '<bdi>' ).append( wrapper ) ).append( ')' );\n\t\t}\n\t\t$logEntry.append( ': ' );\n\t\t$row.append( $logEntry ).append( ' ' );\n\t}\n\t$row.append( $pageLink )\n\t\t.append( ' (' );\n\n\tif ( entry.entryType !== 'log' ) {\n\t\t// No history link for log entries, T273691\n\t\tconst $historyLink = $( '<a>' )\n\t\t\t.attr( 'href', this.linker.linkQuery( 'title=' + pageTitle + '&action=history' ) )\n\t\t\t.attr( 'target', '_blank' )\n\t\t\t.addClass( 'ext-globalwatchlist-history' )\n\t\t\t.text( mw.msg( 'globalwatchlist-history' ) );\n\t\t$row.append( $historyLink )\n\t\t\t.append( ', ' );\n\t}\n\n\t// flag for the permalink creation\n\tlet newEdit = false;\n\tif ( entry.entryType === 'edit' && entry.newPage === true && this.config.fastMode === false ) {\n\t\tconst permrev = entry.editCount === 1 ? entry.toRev : entry.fromRev;\n\t\tconst $diffLink = $( '<a>' )\n\t\t\t.attr( 'href', this.linker.linkQuery( 'oldid=' + permrev ) )\n\t\t\t.attr( 'target', '_blank' )\n\t\t\t.addClass( 'ext-globalwatchlist-permalink' )\n\t\t\t.text( mw.msg( 'globalwatchlist-permalink' ) );\n\t\t$row.append( $diffLink );\n\t\tnewEdit = true;\n\t}\n\t// No diff links in fast mode, see T269728\n\tif ( entry.entryType === 'edit' && ( entry.newPage === false || entry.editCount > 1 ) && this.config.fastMode === false ) {\n\t\tconst $diffLink = $( '<a>' )\n\t\t\t.attr( 'href', this.linker.linkQuery( 'diff=' + entry.toRev + '&oldid=' + entry.fromRev ) )\n\t\t\t.attr( 'target', '_blank' )\n\t\t\t.attr( 'dir', 'auto' )\n\t\t\t.addClass( 'ext-globalwatchlist-diff' );\n\t\t// case when there is more than just the creation\n\t\tif ( newEdit ) {\n\t\t\t$row.append( '+' );\n\t\t\t$diffLink.text(\n\t\t\t\tentry.editCount === 2 ? mw.msg( 'diff' ) : mw.msg( 'nchanges', entry.editCount - 1 )\n\t\t\t);\n\t\t// case when there is no creation\n\t\t} else {\n\t\t\t$diffLink.text(\n\t\t\t\tentry.editCount === 1 ? mw.msg( 'diff' ) : mw.msg( 'nchanges', entry.editCount )\n\t\t\t);\n\t\t}\n\t\t$row.append( $diffLink )\n\t\t\t.append( ', ' );\n\t// case when there is just the creation\n\t} else if ( newEdit ) {\n\t\t$row.append( ', ' );\n\t}\n\tif ( entry.entryType === 'log' ) {\n\t\tconst $logPageLink = $( '<a>' )\n\t\t\t.attr( 'href', this.linker.linkQuery( 'title=Special:Log&page=' + pageTitle ) )\n\t\t\t.attr( 'target', '_blank' )\n\t\t\t.addClass( 'ext-globalwatchlist-logpage' )\n\t\t\t.text( mw.msg( 'globalwatchlist-log-page' ) );\n\t\t$row.append( $logPageLink )\n\t\t\t.append( ', ' );\n\n\t\tconst $logEntryLink = $( '<a>' )\n\t\t\t.attr( 'href', this.linker.linkQuery( 'title=Special:Log&logid=' + entry.logid ) )\n\t\t\t.attr( 'target', '_blank' )\n\t\t\t.addClass( 'ext-globalwatchlist-logentry' )\n\t\t\t.text( mw.msg( 'globalwatchlist-log-entry' ) );\n\t\t$row.append( $logEntryLink )\n\t\t\t.append( ', ' );\n\t}\n\n\tconst $unwatchLink = $( '<a>' )\n\t\t.addClass( 'ext-globalwatchlist-watchunwatch' )\n\t\t.text( mw.msg( 'globalwatchlist-unwatch' ) )\n\t\t.on( 'click', () => {\n\t\t\tthat.changeWatched( entry.title, 'unwatch' );\n\t\t} );\n\t$row.append( $unwatchLink )\n\t\t.append( ', ' );\n\n\tconst $markAsReadLink = $( '<a>' )\n\t\t.addClass( 'ext-globalwatchlist-markpageseen' )\n\t\t.text( mw.msg( 'globalwatchlist-markpageseen' ) )\n\t\t.on( 'click', () => {\n\t\t\tthat.markPageAsSeen( entry.title );\n\t\t} );\n\t$row.append( $markAsReadLink );\n\n\t$row.append( ')' );\n\n\tconst $user = this.config.fastMode ?\n\t\t$() :\n\t\t$( $.parseHTML( entry.userDisplay ) )\n\t\t\t.addClass( 'ext-globalwatchlist-user' );\n\tconst $comment = entry.commentDisplay ?\n\t\t// Need to process links in the parsed comments as raw HTML\n\t\t$( '<span>' )\n\t\t\t.addClass( 'ext-globalwatchlist-comment' )\n\t\t\t.append( $( '<bdi>' ).html( entry.commentDisplay ) ) :\n\t\t$();\n\tif ( $user.length || $comment.length ) {\n\t\t$row.append( ' (' )\n\t\t\t.append( $user );\n\t\tif ( $comment.length ) {\n\t\t\t$row.append( ': ' ).append( $comment );\n\t\t}\n\t\t$row.append( ')' );\n\t}\n\n\tif ( entry.tagsDisplay ) {\n\t\tconst $tags = $( '<em>' )\n\t\t\t.addClass( 'ext-globalwatchlist-tags' )\n\t\t\t.append( entry.tagsDisplay );\n\t\t$row.append( ' ' )\n\t\t\t.append( $tags );\n\t}\n\n\treturn $row;\n};\n/* end GlobalWatchlistSiteDisplay.prototype.makePageLink */\n\n/**\n * Create the output for this.$feedDiv, either for success (via renderWatchlist) or\n * failure (via renderApiFailure)\n *\n * @param {jQuery} $content Content to show\n * @param {Object} siteinfo Extra site information read live from the wiki\n * @param {boolean|undefined} siteinfo.rtl Whether the site is right-to-left;\n *  `undefined` if unknown\n * @param {string} labelname The name of the Watchlist label\n */\nGlobalWatchlistSiteDisplay.prototype.actuallyRenderWatchlist = function ( $content, siteinfo, labelname ) {\n\tconst headerTemplate = mw.template.get(\n\t\t'ext.globalwatchlist.specialglobalwatchlist',\n\t\t'templates/siteRowHeader.mustache'\n\t);\n\tconst headerParams = {\n\t\t'special-watchlist-url': this.linker.linkPage( 'Special:Watchlist' ),\n\t\t'site-name': this.site,\n\t\t'special-edit-watchlist-url': this.linker.linkPage( 'Special:EditWatchlist' ),\n\t\t'edit-watchlist-msg': mw.msg( 'globalwatchlist-editwatchlist' ),\n\t\t'site-label': labelname ? mw.msg( 'quotation-marks', labelname ) : ''\n\t};\n\n\tconst $currentFeedDiv = $( '<div>' )\n\t\t.attr( 'id', 'ext-globalwatchlist-feed-site-' + this.siteID +\n\t\t\t( labelname ? '-label-' + labelname : '' ) )\n\t\t.addClass( 'ext-globalwatchlist-feed-site-' + this.siteID )\n\t\t.addClass( 'ext-globalwatchlist-feed-site' )\n\t\t.append(\n\t\t\theaderTemplate.render( headerParams ),\n\t\t\t$content\n\t\t);\n\n\tif ( siteinfo.rtl !== undefined ) {\n\t\t// mw-content-ltr and -rtl classes are not enough to ensure that the text is formatted\n\t\t// in the correct direction, so add a manual direction attribute. See T287649\n\t\t// We still add those classes because they are also used by jQuery.makeCollapsible\n\t\t// to know if the collapse button should be on the right or left.\n\t\t$currentFeedDiv.attr( 'dir', siteinfo.rtl ? 'rtl' : 'ltr' );\n\t\t$currentFeedDiv.addClass( siteinfo.rtl ? 'mw-content-rtl' : 'mw-content-ltr' );\n\t}\n\tthis.$feedDiv.push( $currentFeedDiv );\n};\n\n/**\n * Alert on API failures\n */\nGlobalWatchlistSiteDisplay.prototype.renderApiFailure = function () {\n\tconst $siteContent = $( '<p>' ).text(\n\t\tmw.msg( 'globalwatchlist-fetch-site-failure' )\n\t);\n\n\tthis.actuallyRenderWatchlist( $siteContent, { rtl: undefined }, '' );\n};\n\n/**\n * Display the watchlist\n *\n * @param {Array<Array<GlobalWatchlistEntryBase>>} summaryArray What should be rendered\n * @param {Object} siteinfo Extra site information read live from the wiki\n * @param {boolean|undefined} siteinfo.rtl Whether the site is right-to-left;\n *  `undefined` if unknown\n */\nGlobalWatchlistSiteDisplay.prototype.renderWatchlist = function ( summaryArray, siteinfo ) {\n\tconst that = this;\n\tsummaryArray.forEach( ( summary, key ) => {\n\t\tif ( !summary ) {\n\t\t\treturn;\n\t\t}\n\t\tconst $ul = $( '<ul>' );\n\t\tsummary.forEach( ( element ) => {\n\t\t\t$ul.append( that.makePageLink( element ) );\n\t\t} );\n\n\t\tconst markSeenButton = new OO.ui.ButtonInputWidget( {\n\t\t\tclasses: [ 'ext-globalwatchlist-feed-markseen' ],\n\t\t\tflags: [ 'destructive' ],\n\t\t\ticon: 'check',\n\t\t\tlabel: mw.msg( 'globalwatchlist-markseen' )\n\t\t} );\n\n\t\tmarkSeenButton.on( 'click', () => {\n\t\t\tconst hasLabels =\n\t\t\t\tArray.isArray( that.labelsData ) &&\n\t\t\t\tthat.labelsData.length > 0;\n\n\t\t\tif ( !hasLabels ) {\n\t\t\t\tthat.debug( 'Mark all' );\n\t\t\t\tthat.markAllAsSeen();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Find the closest collapsible container\n\t\t\tconst $container = markSeenButton.$element.closest( '.mw-collapsible' );\n\t\t\t// Collect all data-title attributes inside the container\n\t\t\tconst titles = [];\n\t\t\t$container.find( '[data-title]' ).each( function () {\n\t\t\t\tconst title = $( this ).attr( 'data-title' );\n\t\t\t\tif ( title ) {\n\t\t\t\t\ttitles.push( decodeURIComponent( title ) );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthat.debug( 'Mark section', titles );\n\t\t\tthat.markSectionAsSeen( Array.from( new Set( titles ) ) ).then( () => $( markSeenButton\n\t\t\t\t.$element.closest( '.ext-globalwatchlist-feed-site' ).children()[ 1 ] ).hide() );\n\t\t} );\n\n\t\tconst $outputContent = $( '<div>' )\n\t\t\t.addClass( 'ext-globalwatchlist-site' )\n\t\t\t.append(\n\t\t\t\tmarkSeenButton.$element,\n\t\t\t\t$ul\n\t\t\t)\n\t\t\t.makeCollapsible();\n\t\tconst labelname = that.labelsData && that.labelsData[ key ];\n\t\tthis.actuallyRenderWatchlist( $outputContent, siteinfo, labelname );\n\t} );\n};\n/* end GlobalWatchlistSiteDisplay.prototype.renderWatchlist */\n\n/**\n * Update display after marking a site as seen\n */\nGlobalWatchlistSiteDisplay.prototype.afterMarkAllAsSeen = function () {\n\tthis.debug( 'markSiteAsSeen - hiding site' );\n\tif ( this.$feedDiv && this.$feedDiv[ 0 ] ) {\n\t\t// Don't call .children() on the default empty string, T275078\n\t\t$( this.$feedDiv[ 0 ].children()[ 1 ] ).hide();\n\t}\n\n\t// FIXME\n\t// GlobalWatchlist.watchlists.checkChangesShown( true );\n};\n/* end GlobalWatchlistSiteDisplay.prototype.afterMarkAllAsSeen */\n\n/**\n * Update display after marking a page as seen\n *\n * @param {string} pageTitle the marked page\n */\nGlobalWatchlistSiteBase.prototype.afterMarkPageAsSeen = function ( pageTitle ) {\n\tthis.debug( 'markPageAsSeen - hiding page' );\n\tconst dataTitle = encodeURIComponent( pageTitle );\n\tif ( this.$feedDiv ) {\n\t\tthis.$feedDiv.forEach( ( item ) => {\n\t\t\t$( item ).find( '[data-title=\"' + dataTitle + '\"]' ).hide();\n\t\t} );\n\t}\n};\n/* end GlobalWatchlistSiteDisplay.prototype.afterMarkPageAsSeen */\n\n/**\n * Update entry click handlers, text, and strikethrough for a specific title\n *\n * @param {string} pageTitle Title of the page that was unwatched/rewatched.\n * @param {boolean} unwatched Whether the page was unwatched\n */\nGlobalWatchlistSiteDisplay.prototype.processUpdateWatched = function ( pageTitle, unwatched ) {\n\tthis.debug(\n\t\t'Processing after ' + ( unwatched ? 'unwatching' : 'rewatching' ) + ': ' + pageTitle\n\t);\n\n\tconst encodedSite = encodeURIComponent( this.siteID );\n\tconst encodedTitle = encodeURIComponent( pageTitle );\n\tconst $entries = $( 'li[data-site=\"' + encodedSite + '\"][data-title=\"' + encodedTitle + '\"]' );\n\t$entries[ unwatched ? 'addClass' : 'removeClass' ]( 'ext-globalwatchlist-strike' );\n\n\t$entries.children( '.ext-globalwatchlist-expiry-icon' ).remove();\n\n\tconst $links = $entries.children( 'a.ext-globalwatchlist-watchunwatch' );\n\tconst newText = mw.msg( unwatched ? 'globalwatchlist-rewatch' : 'globalwatchlist-unwatch' );\n\tconst that = this;\n\n\t$links.each( function () {\n\t\t$( this ).off( 'click' );\n\t\t$( this ).on( 'click', () => {\n\t\t\tthat.changeWatched( pageTitle, unwatched ? 'watch' : 'unwatch' );\n\t\t} );\n\t\t$( this ).text( newText );\n\t} );\n};\n/* end GlobalWatchlistSiteDisplay.prototype.processUpdateWatched */\n\nmodule.exports = GlobalWatchlistSiteDisplay;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/SpecialGlobalWatchlist.display.js","messages":[],"suppressedMessages":[{"ruleId":"no-console","severity":2,"message":"Unexpected console statement.","line":178,"column":5,"nodeType":"MemberExpression","messageId":"unexpected","endLine":178,"endColumn":16,"suggestions":[{"messageId":"removeConsole","data":{"propertyName":"log"},"fix":{"range":[5554,5575],"text":""},"desc":"Remove the console.log()."}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-global-selector","severity":2,"message":"Avoid queries which search the entire DOM. Keep DOM nodes in memory where possible.","line":255,"column":3,"nodeType":"CallExpression","endLine":255,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/WatchlistUtils.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistLinker' is undefined.","line":7,"column":1,"nodeType":"Block","endLine":7,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 105. Maximum allowed is 100.","line":72,"column":1,"nodeType":"Program","messageId":"max","endLine":72,"endColumn":100},{"ruleId":"max-len","severity":1,"message":"This line has a length of 101. Maximum allowed is 100.","line":113,"column":1,"nodeType":"Program","messageId":"max","endLine":113,"endColumn":102},{"ruleId":"max-len","severity":1,"message":"This line has a length of 103. Maximum allowed is 100.","line":167,"column":1,"nodeType":"Program","messageId":"max","endLine":167,"endColumn":104},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistSiteBase.getTagList' is undefined.","line":313,"column":1,"nodeType":"Block","endLine":313,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryEdits' is undefined.","line":323,"column":1,"nodeType":"Block","endLine":323,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryLog' is undefined.","line":323,"column":1,"nodeType":"Block","endLine":323,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":325,"column":1,"nodeType":"Block","endLine":325,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryEdits' is undefined.","line":326,"column":1,"nodeType":"Block","endLine":326,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryLog' is undefined.","line":326,"column":1,"nodeType":"Block","endLine":326,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 105. Maximum allowed is 100.","line":408,"column":1,"nodeType":"Program","messageId":"max","endLine":408,"endColumn":97},{"ruleId":"max-len","severity":1,"message":"This line has a length of 103. Maximum allowed is 100.","line":429,"column":1,"nodeType":"Program","messageId":"max","endLine":429,"endColumn":104},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":429,"column":1,"nodeType":"Block","endLine":429,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryEdits' is undefined.","line":430,"column":1,"nodeType":"Block","endLine":430,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryLog' is undefined.","line":430,"column":1,"nodeType":"Block","endLine":430,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 110. Maximum allowed is 100.","line":432,"column":1,"nodeType":"Program","messageId":"max","endLine":432,"endColumn":111},{"ruleId":"max-len","severity":1,"message":"This line has a length of 105. Maximum allowed is 100.","line":446,"column":1,"nodeType":"Program","messageId":"max","endLine":446,"endColumn":103},{"ruleId":"max-len","severity":1,"message":"This line has a length of 105. Maximum allowed is 100.","line":548,"column":1,"nodeType":"Program","messageId":"max","endLine":548,"endColumn":100}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":18,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * General helper for converting the api response data into the form we use to display\n *\n * @class GlobalWatchlistWatchlistUtils\n * @constructor\n *\n * @param {GlobalWatchlistLinker} linker Linker for the relevant site, used for\n *    Links to user pages for registered users\n *    Links to contributions pages for anonymous users and temporary accounts\n *    Converting links in edit summaries to not be relative to the current site\n */\nfunction GlobalWatchlistWatchlistUtils( linker ) {\n\tthis.linker = linker;\n}\n\n/**\n * Convert an array of two or more objects for specific edits to the same page to one object\n * with the information grouped\n *\n * @param {Array} edits Edits to merge\n * @return {Object} Merged information\n */\nGlobalWatchlistWatchlistUtils.prototype.mergePageEdits = function ( edits ) {\n\tconst mergedEditInfo = {};\n\n\t// No comments are shown for the grouped changes\n\tmergedEditInfo.comment = false;\n\n\tmergedEditInfo.bot = edits\n\t\t.map( ( edit ) => edit.bot )\n\t\t.reduce(\n\t\t\t// The combined edits are only tagged as bot if all of the edits where bot edits\n\t\t\t( bot1, bot2 ) => bot1 && bot2\n\t\t);\n\n\tmergedEditInfo.editCount = edits.length;\n\n\t// Should all be the same\n\tmergedEditInfo.expiry = edits[ 0 ].expiry;\n\n\tmergedEditInfo.fromRev = edits\n\t\t// filter out creation version\n\t\t.filter( ( edit ) => edit.old_revid !== 0 )\n\t\t.map( ( edit ) => edit.old_revid )\n\t\t.reduce(\n\t\t\t// Get the lower rev id, corresponding to the older revision\n\t\t\t( edit1, edit2 ) => ( edit1 > edit2 ? edit2 : edit1 )\n\t\t);\n\n\tmergedEditInfo.minor = edits\n\t\t.map( ( edit ) => edit.minor )\n\t\t.reduce(\n\t\t\t// The combined edits are only tagged as minor if all of the edits where minor\n\t\t\t( minor1, minor2 ) => minor1 && minor2\n\t\t);\n\n\tmergedEditInfo.newPage = edits\n\t\t.map( ( edit ) => edit.newPage )\n\t\t.reduce(\n\t\t\t// Page creation is stored as a flag on edit entries, instead of as\n\t\t\t// its own type of entry. If any of the entries are creations, the\n\t\t\t// overall group was a page creation\n\t\t\t( newPage1, newPage2 ) => newPage1 || newPage2\n\t\t);\n\n\t// No tags\n\tmergedEditInfo.tags = [];\n\n\t// Per T262176, and like the core watchlist, use the latest timestamp\n\tmergedEditInfo.timestamp = edits\n\t\t.map( ( edit ) => edit.timestamp )\n\t\t.reduce( ( time1, time2 ) => ( ( new Date( time1 ) ) > ( new Date( time2 ) ) ? time1 : time2 ) );\n\n\t// When there are multiple edits grouped, the timestamp has a tooltip (title attribute)\n\t// explaining that its the timestamp of the latest change. If it's not set here, it's\n\t// null, and the display ignores null attribute values. See T286268 and\n\t// * https://api.jquery.com/attr/#attr-attributeName-value\n\tmergedEditInfo.timestampTitle = mw.msg( 'globalwatchlist-grouped-timestamp' );\n\n\tmergedEditInfo.toRev = edits\n\t\t.map( ( edit ) => edit.revid )\n\t\t.reduce(\n\t\t\t// Get the higher rev id, corresponding to the newer revision\n\t\t\t( edit1, edit2 ) => ( edit1 > edit2 ? edit1 : edit2 )\n\t\t);\n\n\treturn mergedEditInfo;\n};\n\n/**\n * Create links based on one-or-more editors\n *\n * editsByUser has the information for the links to create. It is a map in the following format:\n *\n *   ⧼user name/ip address⧽\n *       ->\n *   {\n *       editCount: ⧼count⧽\n *       temp: ⧼true/false⧽\n *       anon: ⧼true/false⧽\n *   }\n *\n * For edits where the user was hidden, the key is: ##hidden##\n *\n * WARNING: This method returns RAW HTML that is the displayed. jQuery isn't used because we need\n *          to handle creating multiple links and returning the same way a single link does, since\n *          the caller doesn't know if the entry row is for a single edit or multiple edits grouped\n * For each entry in editsByUser:\n *  - if the user was hidden, the output is hard-coded as the core message `rev-deleted-user`\n *      wrapped in a span for styling\n *  - if the user wasn't hidden, a link is shown. The text for the link is the username, and\n *      the target is the user page (for users) or the contributions page (for anonymous editors\n *      and temporary accounts), just like at Special:Watchlist. See RCCacheEntryFactory::getUserLink\n *      and Linker::userLink.\n *  - if the user made multiple edits, or multiple edits were made by hidden users, the number of\n *      edits is appended after the link, using the `ntimes` core message. This is only the case\n *      when grouping results by page. See EnhancedChangesList::recentChangesBlockGroup\n *\n * @param {Object} editsByUser Edit information\n * @return {string} the raw HTML to display\n */\nGlobalWatchlistWatchlistUtils.prototype.makeUserLinks = function ( editsByUser ) {\n\tconst users = Object.keys( editsByUser );\n\n\tconst allLinks = [];\n\tlet userLink = '',\n\t\tuserLinkBase = '',\n\t\tuserLinkURL = '';\n\n\tconst that = this;\n\tusers.forEach( ( userMessage ) => {\n\t\tif ( userMessage === '##hidden##' ) {\n\t\t\t// Edits by hidden user(s)\n\t\t\tuserLink = '<span class=\"history-deleted\">' +\n\t\t\t\tmw.message( 'rev-deleted-user' ).escaped() +\n\t\t\t\t'</span>';\n\t\t} else {\n\t\t\tuserLinkBase = editsByUser[ userMessage ].anon || editsByUser[ userMessage ].temp ?\n\t\t\t\t'Special:Contributions/' :\n\t\t\t\t'User:';\n\t\t\tuserLinkURL = that.linker.linkPage( userLinkBase + userMessage );\n\t\t\tuserLink = mw.html.element( 'a', {\n\t\t\t\thref: userLinkURL,\n\t\t\t\ttarget: '_blank',\n\t\t\t\tclass: 'mw-userlink' + ( editsByUser[ userMessage ].temp ? ' mw-tempuserlink' : '' )\n\t\t\t}, new mw.html.Raw( mw.html.element( 'bdi', {}, userMessage ) ) );\n\t\t}\n\t\tif ( editsByUser[ userMessage ].editCount > 1 ) {\n\t\t\tuserLink = userLink + ' ' +\n\t\t\t\tmw.message( 'ntimes', editsByUser[ userMessage ].editCount ).escaped();\n\t\t}\n\t\tallLinks.push( userLink );\n\t} );\n\n\treturn allLinks.join( ', ' );\n};\n\n/**\n * Shortcut for makeUserLinks when there is only one user (single edits, ungrouped edits,\n * or log entries) and no need for showing a message for the edit count\n *\n * @param {string} userMessage either name or ip address\n * @param {boolean} isAnon Whether the link is for an anonymous user\n * @param {boolean} isTemp Whether the link is for a temporary account\n * @return {string}\n */\nGlobalWatchlistWatchlistUtils.prototype.makeSingleUserLink = function ( userMessage, isAnon, isTemp ) {\n\tif ( userMessage === '' ) {\n\t\t// Didn't fetch due to fast mode\n\t\treturn '';\n\t}\n\n\tconst editsByUser = {};\n\teditsByUser[ userMessage ] = {\n\t\teditCount: 1,\n\t\ttemp: isTemp,\n\t\tanon: isAnon\n\t};\n\n\treturn this.makeUserLinks( editsByUser );\n};\n\n/**\n * Convert edit info, including adding links to user pages / temporary accounts' / anonymous users'\n * contributions and grouping results by page when called for\n *\n * @param {Object} editInfo\n * @param {boolean} groupPage Whether to group results by page\n * @return {Array} Converted edits\n */\nGlobalWatchlistWatchlistUtils.prototype.convertEdits = function ( editInfo, groupPage ) {\n\tconst finalEdits = [];\n\n\tconst edits = [];\n\tfor ( const key in editInfo ) {\n\t\tedits.push( editInfo[ key ] );\n\t}\n\n\tconst that = this;\n\tedits.forEach( ( page ) => {\n\t\tconst pagebase = {\n\t\t\tentryType: 'edit',\n\t\t\tns: page.ns,\n\t\t\ttitle: page.title\n\t\t};\n\t\tif ( !groupPage || page.each.length === 1 ) {\n\t\t\tpage.each.forEach( ( entry ) => {\n\t\t\t\tfinalEdits.push( Object.assign( {}, pagebase, {\n\t\t\t\t\tbot: entry.bot,\n\t\t\t\t\tcomment: entry.parsedcomment,\n\t\t\t\t\teditCount: 1,\n\t\t\t\t\texpiry: entry.expiry,\n\t\t\t\t\tfromRev: entry.old_revid,\n\t\t\t\t\tminor: entry.minor,\n\t\t\t\t\tnewPage: entry.newPage,\n\t\t\t\t\ttags: entry.tags,\n\t\t\t\t\ttimestamp: entry.timestamp,\n\t\t\t\t\ttimestampTitle: null,\n\t\t\t\t\ttoRev: entry.revid,\n\t\t\t\t\tuserDisplay: that.makeSingleUserLink(\n\t\t\t\t\t\tentry.user,\n\t\t\t\t\t\tentry.anon,\n\t\t\t\t\t\tentry.temp\n\t\t\t\t\t)\n\t\t\t\t} ) );\n\t\t\t} );\n\t\t} else {\n\t\t\tconst mergedEditInfo = that.mergePageEdits( page.each );\n\n\t\t\t// Map of edit counts\n\t\t\t// ⧼user name/ip address⧽\n\t\t\t//     ->\n\t\t\t// {\n\t\t\t//     editCount: ⧼count⧽\n\t\t\t//     temp: ⧼true/false⧽\n\t\t\t//     anon: ⧼true/false⧽\n\t\t\t// }\n\t\t\t//\n\t\t\t// For edits where the user was hidden, the key is: ##hidden##\n\t\t\tconst editsByUser = {};\n\n\t\t\tpage.each.forEach( ( specificEdit ) => {\n\t\t\t\tif ( !( specificEdit.user in editsByUser ) ) {\n\t\t\t\t\teditsByUser[ specificEdit.user ] = {\n\t\t\t\t\t\teditCount: 0,\n\t\t\t\t\t\ttemp: specificEdit.temp,\n\t\t\t\t\t\tanon: specificEdit.anon\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\teditsByUser[ specificEdit.user ].editCount =\n\t\t\t\t\teditsByUser[ specificEdit.user ].editCount + 1;\n\t\t\t} );\n\n\t\t\tmergedEditInfo.userDisplay = that.makeUserLinks( editsByUser );\n\n\t\t\tfinalEdits.push( Object.assign( {}, pagebase, mergedEditInfo ) );\n\t\t}\n\t} );\n\n\treturn finalEdits;\n};\n\n/**\n * @param {Array} entries Entries in the format returned by the api\n * @return {Array} Entries in a \"normalized\" format\n */\nGlobalWatchlistWatchlistUtils.prototype.normalizeEntries = function ( entries ) {\n\tentries.forEach( ( entry ) => {\n\t\tif ( entry.userhidden ) {\n\t\t\t// # is in wgLegalTitleChars so no conflict\n\t\t\tentry.user = '##hidden##';\n\t\t} else if ( typeof entry.user === 'undefined' ) {\n\t\t\t// Not fetching, fast mode\n\t\t\tentry.user = '';\n\t\t}\n\n\t\tif ( typeof entry.parsedcomment === 'undefined' ) {\n\t\t\tentry.parsedcomment = '';\n\t\t}\n\t\tif ( typeof entry.tags === 'undefined' ) {\n\t\t\tentry.tags = [];\n\t\t}\n\t\tif ( entry.type === 'new' ) {\n\t\t\t// Treat page creations as edits with a flag, so that they can be\n\t\t\t// grouped together when needed\n\t\t\tentry.type = 'edit';\n\t\t\tentry.newPage = true;\n\t\t} else {\n\t\t\tentry.newPage = false;\n\t\t}\n\n\t\tif ( typeof entry.timestamp === 'undefined' ) {\n\t\t\t// Not fetched in fast mode\n\t\t\tentry.timestamp = false;\n\t\t}\n\t} );\n\treturn entries;\n};\n\n/**\n * Do various cleanup of entries that goes after merging grouped edits and splitting\n * edits and log entries. This is where we will convert the plain objects to the new\n * classes in T288385.\n *\n * - Convert raw expiration strings into the tooltip to be shown.\n * - Add a \"flags\" property to each entry that will either be `false` or a string with the flags\n *     to show next to the entry (new page, minor edit, bot action).\n * - Truncate the timestamp to only show details down to the minute, see T262176. This needs to\n *     be done *after* the sorting of edits and log entries by timestamp, which should be done\n *     using the full untruncated version, see T286977.\n * - Create the HTML to show for the tags associated with an entry. For each tag, if there is\n *     a display configured onwiki, that is shown, otherwise its just the name. See\n *     {@link GlobalWatchlistSiteBase#getTagList SiteBase#getTagList} for where the info is\n *     retrieved.\n * - Set the comment display to include the updated links in edit summaries/log entries.\n *     In fast mode, or for grouped changes, there is no comment display. The commentDisplay\n *     set here is treated as raw html by the display. We use the `parsedcomment` result from\n *     the api, and MediaWiki core takes care of escaping.\n *\n * @param {Array} entries Entries to update\n * @param {Object} tagsInfo Keys are tag names, values are the html to display (either the\n *    display text with local links updated, or just the name)\n * @param {Function} EntryClass either {@link GlobalWatchlistEntryEdits} or\n *    {@link GlobalWatchlistEntryLog} to convert entries to\n * @return {GlobalWatchlistEntryBase[]} updated entries, each entry converted to either\n *    {@link GlobalWatchlistEntryEdits} or {@link GlobalWatchlistEntryLog}\n */\nGlobalWatchlistWatchlistUtils.prototype.getFinalEntries = function (\n\tentries,\n\ttagsInfo,\n\tEntryClass\n) {\n\t// Watchlist expiry\n\tlet expirationDate, daysLeft;\n\n\t// New page / minor / bot flags\n\t// Optimization: only fetch the messages a single time\n\t// Order to match the display of core\n\tconst newPageFlag = mw.msg( 'newpageletter' );\n\tconst minorFlag = mw.msg( 'minoreditletter' );\n\tconst botFlag = mw.msg( 'boteditletter' );\n\tlet entryFlags;\n\n\t// Tags display\n\tconst noTagsDisplay = Object.keys( tagsInfo ).length === 0;\n\tlet $tagDescriptions, $tagsWithLabel;\n\n\t// Comment display\n\tconst that = this;\n\n\treturn entries.map( ( entry ) => {\n\t\t// Watchlist expiry\n\t\tif ( entry.expiry ) {\n\t\t\texpirationDate = new Date( entry.expiry );\n\t\t\tdaysLeft = Math.ceil( ( expirationDate - Date.now() ) / 1000 / 86400 ) + 0;\n\t\t\tif ( daysLeft === 0 ) {\n\t\t\t\tentry.expiry = mw.msg( 'watchlist-expiring-hours-full-text' );\n\t\t\t} else {\n\t\t\t\tentry.expiry = mw.msg( 'watchlist-expiring-days-full-text', daysLeft );\n\t\t\t}\n\t\t}\n\n\t\t// New page / minor / bot flags\n\t\tentryFlags = '';\n\t\tif ( entry.newPage === true ) {\n\t\t\tentryFlags += newPageFlag;\n\t\t}\n\t\tif ( entry.minor ) {\n\t\t\tentryFlags += minorFlag;\n\t\t}\n\t\tif ( entry.bot ) {\n\t\t\tentryFlags += botFlag;\n\t\t}\n\t\tif ( entryFlags === '' ) {\n\t\t\tentry.flags = false;\n\t\t} else {\n\t\t\tentry.flags = entryFlags;\n\t\t}\n\n\t\t// Timestamp normalization\n\t\t// We set the timestamp to false in normalizeEntries if its not available\n\t\tif ( entry.timestamp ) {\n\t\t\t// Per T262176, display as\n\t\t\t// YYYY-MM-DD HH:MM\n\t\t\tentry.timestamp = entry.timestamp.replace( /T(\\d+:\\d+):\\d+Z/, ' $1' );\n\t\t}\n\n\t\t// Tags display\n\t\t// In fast mode no tag info was retrieved, so tagsInfo should be an empty object\n\t\t// and none of the entries should have tags that need displaying. We still need to\n\t\t// set the `tagsDisplay` property for each entry though, the display code checks it.\n\t\tif ( noTagsDisplay || entry.tags.length === 0 ) {\n\t\t\tentry.tagsDisplay = false;\n\t\t} else {\n\t\t\t// This is the actual building of the display\n\t\t\t$tagDescriptions = entry.tags.reduce( ( $acc, tagName, index ) => {\n\t\t\t\tif ( index > 0 ) {\n\t\t\t\t\t$acc.append( ', ' );\n\t\t\t\t}\n\t\t\t\treturn $acc.append( $( '<bdi>' ).html( that.linker.newTabLinks( tagsInfo[ tagName ] ) ) );\n\t\t\t}, $( '<span>' ) );\n\t\t\t$tagsWithLabel = mw.message( 'globalwatchlist-tags', entry.tags.length, $tagDescriptions ).parseDom();\n\t\t\tentry.tagsDisplay = mw.message( 'parentheses', $tagsWithLabel ).parseDom();\n\t\t}\n\n\t\t// Comment display\n\t\tif ( entry.comment && entry.comment !== '' ) {\n\t\t\tentry.commentDisplay = that.linker.newTabLinks( that.linker.fixLocalLinks( entry.comment ) );\n\t\t} else {\n\t\t\tentry.commentDisplay = false;\n\t\t}\n\n\t\t// Convert to relevant entry class, T288385\n\t\treturn new EntryClass( entry );\n\t} );\n};\n\n/**\n * Convert result from the API to format used by this extension\n *\n * This is the entry point for the JavaScript controlling Special:GlobalWatchlist and the\n * display of each site's changes.\n *\n * @param {Array} entries Entries to convert\n * @param {boolean} groupPage Whether to group results by page\n * @param {Object} tagsInfo See details at\n *    {@link GlobalWatchlistWatchlistUtils#getFinalEntries #getFinalEntries}\n * @param {Object} labelsInfo list of user's Watchlist labels\n * @return {Array<Array<GlobalWatchlistEntryBase>>} list of summaries of changes, each change converted\n *    to either {@link GlobalWatchlistEntryEdits} or {@link GlobalWatchlistEntryLog}\n */\nGlobalWatchlistWatchlistUtils.prototype.rawToSummary = function ( entries, groupPage, tagsInfo, labelsInfo ) {\n\tconst buckets = [];\n\tlet maxLabelId = -1;\n\tObject.keys( labelsInfo ).forEach( ( key ) => {\n\t\tconst index = Number( key );\n\t\tbuckets[ index ] = {\n\t\t\tedits: {},\n\t\t\tlogEntries: [],\n\t\t\tid: index\n\t\t};\n\t\tif ( index > maxLabelId ) {\n\t\t\tmaxLabelId = index;\n\t\t}\n\t} );\n\t// extra bucket for every page that does not labels that were existed at the browser load of the page\n\tbuckets[ maxLabelId + 1 ] = {\n\t\tedits: {},\n\t\tlogEntries: [],\n\t\tid: maxLabelId + 1\n\t};\n\n\tconst cleanedEntries = this.normalizeEntries( entries );\n\tconst that = this;\n\tcleanedEntries.forEach( ( entry ) => {\n\t\tlet targetBuckets = ( entry.labels || [] )\n\t\t\t.map( ( label ) => buckets[ label.id ] ).filter( Boolean );\n\t\tif ( targetBuckets.length === 0 ) {\n\t\t\ttargetBuckets = [ buckets[ maxLabelId + 1 ] ];\n\t\t}\n\n\t\tlet entryObject;\n\t\tif ( entry.type === 'log' ) {\n\t\t\tentryObject = {\n\t\t\t\tbot: entry.bot,\n\t\t\t\tcomment: entry.parsedcomment,\n\t\t\t\tentryType: entry.type,\n\t\t\t\texpiry: entry.expiry,\n\t\t\t\tns: entry.ns,\n\t\t\t\ttags: entry.tags,\n\t\t\t\ttimestamp: entry.timestamp,\n\t\t\t\ttimestampTitle: null,\n\t\t\t\ttitle: entry.title,\n\t\t\t\tlogaction: entry.logaction,\n\t\t\t\tlogid: entry.logid,\n\t\t\t\tlogtype: entry.logtype,\n\t\t\t\tlogdisplay: entry.logdisplay,\n\t\t\t\tuserDisplay: that.makeSingleUserLink(\n\t\t\t\t\tentry.user,\n\t\t\t\t\tentry.anon,\n\t\t\t\t\tentry.temp\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\ttargetBuckets.forEach( ( bucket ) => {\n\t\t\tif ( entry.type === 'edit' ) {\n\t\t\t\t// Also includes new pages\n\t\t\t\tif ( !bucket.edits[ entry.pageid ] ) {\n\t\t\t\t\tbucket.edits[ entry.pageid ] = {\n\t\t\t\t\t\teach: [ entry ],\n\t\t\t\t\t\tns: entry.ns,\n\t\t\t\t\t\ttitle: entry.title\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tbucket.edits[ entry.pageid ].each.push( entry );\n\t\t\t\t}\n\t\t\t} else if ( entry.type === 'log' ) {\n\t\t\t\tbucket.logEntries.push( entryObject );\n\t\t\t}\n\t\t} );\n\t} );\n\n\tconst GlobalWatchlistEntryEdits = require( './EntryEdits.js' );\n\tconst GlobalWatchlistEntryLog = require( './EntryLog.js' );\n\tconst summaryArray = [];\n\n\tbuckets.forEach( ( bucket ) => {\n\t\tif ( !bucket ) {\n\t\t\treturn;\n\t\t}\n\n\t\tbucket.edits = this.convertEdits( bucket.edits, groupPage );\n\n\t\t// Sorting: we want the newest edits and log entries at the top. But, the api\n\t\t// only tells us what minute the edit/log entry was made. So, if the timestamps\n\t\t// are the same, go by the revid and logid - we assume that newer edits have higher\n\t\t// revision ids, and newer log entries have higher log ids. Sort functions should\n\t\t// return negative if the order should not change, and positive if they should.\n\t\t// See T275303\n\t\tbucket.edits.sort(\n\t\t\t( editA, editB ) => {\n\t\t\t\tif ( editA.timestamp !== editB.timestamp ) {\n\t\t\t\t\treturn ( ( new Date( editA.timestamp ) ) > ( new Date( editB.timestamp ) ) ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t1\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// fallback to revision ids\n\t\t\t\treturn ( ( editA.toRev > editB.toRev ) ? -1 : 1 );\n\t\t\t}\n\t\t);\n\n\t\tbucket.logEntries.sort(\n\t\t\t( logA, logB ) => {\n\t\t\t\tif ( logA.timestamp !== logB.timestamp ) {\n\t\t\t\t\treturn ( ( new Date( logA.timestamp ) ) > ( new Date( logB.timestamp ) ) ?\n\t\t\t\t\t\t-1 :\n\t\t\t\t\t\t1\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// fallback to log ids\n\t\t\t\treturn ( ( logA.logid > logB.logid ) ? -1 : 1 );\n\t\t\t}\n\t\t);\n\n\t\tbucket.edits = this.getFinalEntries( bucket.edits, tagsInfo, GlobalWatchlistEntryEdits );\n\t\tbucket.logEntries = this.getFinalEntries( bucket.logEntries, tagsInfo, GlobalWatchlistEntryLog );\n\t\tsummaryArray[ bucket.id ] = bucket.edits.concat( bucket.logEntries );\n\t\tif ( summaryArray[ bucket.id ].length === 0 ) {\n\t\t\tsummaryArray[ bucket.id ] = null;\n\t\t}\n\t} );\n\n\treturn summaryArray;\n};\n\nmodule.exports = GlobalWatchlistWatchlistUtils;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/WikibaseHandler.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistDebugger' is undefined.","line":9,"column":1,"nodeType":"Block","endLine":9,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 104. Maximum allowed is 100.","line":13,"column":1,"nodeType":"Program","messageId":"max","endLine":13,"endColumn":105},{"ruleId":"max-len","severity":1,"message":"This line has a length of 101. Maximum allowed is 100.","line":15,"column":1,"nodeType":"Program","messageId":"max","endLine":15,"endColumn":102},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":207,"column":1,"nodeType":"Block","endLine":207,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistEntryBase' is undefined.","line":239,"column":1,"nodeType":"Block","endLine":239,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Handle getting labels for wikibase items\n *\n * Caller is responsible for determining if this should be used\n *\n * @class GlobalWatchlistWikibaseHandler\n * @constructor\n *\n * @param {GlobalWatchlistDebugger} globalWatchlistDebug Debugger instance to log to\n * @param {mw.ForeignApi} api Instance of mw.ForeignApi to use\n * @param {string} userLang Language to fetch labels in\n * @param {Array<Array<number>>} namespaces All the namespaces with wikibase default content model\n * @param {Array<Array<string>>} nsNames All the names of namespaces with wikibase default content model\n */\nfunction GlobalWatchlistWikibaseHandler( globalWatchlistDebug, api, userLang, namespaces, nsNames ) {\n\t// Logger to send debug info to\n\tthis.debugLogger = globalWatchlistDebug;\n\n\t// api for the wikibase repo site\n\tthis.api = api;\n\n\t// Language to fetch the labels in\n\tthis.userLang = userLang;\n\n\t// Wikibase namespaces\n\tthis.namespaces = namespaces.wikibase;\n\n\t// Wikibase namespaces names\n\tthis.nsNames = nsNames.wikibase;\n\n\t// Entity Schema namespaces\n\tthis.esNamespaces = namespaces.entity;\n\n\t// EntitySchema namespaces names\n\tthis.esNsNames = nsNames.entity;\n\n\t// EntitySchema caches\n\tthis.esCache = {};\n\tthis.esPromiseCache = {};\n}\n\n/**\n * Shortcut for sending information to the debug logger\n *\n * @param {string} msg Message for debug entry\n * @param {string} [extraInfo] Extra information for the debug entry\n */\nGlobalWatchlistWikibaseHandler.prototype.debug = function ( msg, extraInfo ) {\n\tthis.debugLogger.info( 'wikibase:' + msg, extraInfo );\n};\n\n/**\n * Fetch the labels for all of the ids given\n *\n * Since the api is usually limited to 50 ids at a time, called recursively\n * until all ids are processed. No special handling for users with `apihighlimits`,\n * still only fetch 50 at a time\n *\n * The returned promise resolves to an object with each of the entity ids being a key\n * to the relevant information. To help visualize, below is a partial result of the\n * wbgetentities query[1] performed on wikidata for Q5, P10, and L2, with the exception\n * that the `forms` and `senses` for L2 are not included.\n *\n * ```json\n *    {\n *        \"Q5\": {\n *            \"type\": \"item\",\n *            \"id\": \"Q5\",\n *            \"labels\": {\n *                \"en\": {\n *                    \"language\": \"en\",\n *                    \"value\": \"human\"\n *                }\n *            }\n *        },\n *        \"P10\": {\n *            \"type\": \"property\",\n *            \"datatype\": \"commonsMedia\",\n *            \"id\": \"P10\",\n *            \"labels\": {\n *                \"en\": {\n *                    \"language\": \"en\",\n *                    \"value\": \"video\"\n *                }\n *            }\n *        },\n *        \"L2\": {\n *            \"type\": \"lexeme\",\n *            \"id\": \"L2\",\n *            \"lemmas\": {\n *                \"en\": {\n *                    \"language\": \"en\",\n *                    \"value\": \"first\"\n *                }\n *            },\n *            \"lexicalCategory\": \"Q1084\",\n *            \"language\": \"Q1860\",\n *            \"forms\": [ ... ],\n *            \"senses\": [ ... ]\n *        }\n *    }\n * ```\n *\n *\n * [1] See:\n * https://www.wikidata.org/w/api.php?action=wbgetentities&ids=Q5|P10|L2&languages=en&props=labels&formatversion=2\n *\n * @see {@link GlobalWatchlistWikibaseHandler#cleanupRawLabels #cleanupRawLabels} for converting\n * to a more usable form\n *\n * @param {Array} entityIds The ids to get labels for\n * @return {Promise} Promise of api result\n */\nGlobalWatchlistWikibaseHandler.prototype.getRawLabels = function ( entityIds ) {\n\tconst that = this;\n\n\tif ( !entityIds || entityIds.length === 0 ) {\n\t\treturn Promise.resolve( {} );\n\t}\n\n\treturn new Promise( ( resolve ) => {\n\t\tconst query = {\n\t\t\taction: 'wbgetentities',\n\t\t\tformatversion: 2,\n\t\t\tids: entityIds.slice( 0, 50 ),\n\t\t\tlanguages: that.userLang,\n\t\t\tprops: 'labels',\n\t\t\tlanguagefallback: 1\n\t\t};\n\t\tthat.api.get( query ).then( ( response ) => {\n\t\t\tthat.debug( 'getRawLabels - api response', response );\n\t\t\tconst labels = response.entities;\n\t\t\tif ( entityIds.length > 50 ) {\n\t\t\t\t// Recursive processing\n\t\t\t\tthat.getRawLabels( entityIds.slice( 50 ) ).then( ( extraLabels ) => {\n\t\t\t\t\tconst bothLabels = Object.assign( {}, labels, extraLabels );\n\t\t\t\t\tthat.debug( 'getRawLabels - bothLabels', bothLabels );\n\t\t\t\t\tresolve( bothLabels );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t// No need for further processing, either had less than 50 to\n\t\t\t\t// begin with or this was the final recursive call\n\t\t\t\tthat.debug( 'getRawLabels - last', labels );\n\t\t\t\tresolve( labels );\n\t\t\t}\n\t\t} );\n\t} );\n};\n\n/**\n * Convert the messy object returned from getRawLabels to something clearer\n *\n * Resulting object has the following form (see documentation in\n * {@link GlobalWatchlistWikibaseHandler#getRawLabels #getRawLabels} for the original)\n *\n *```json\n *    {\n *        \"Q5\": \"human\",\n *        \"P10\": \"video\",\n *        \"L2\": \"first\"\n *    }\n *```\n *\n * @param {Object} rawLabels Labels in the format returns from the api\n * @return {Object} Labels in a more usable format\n */\nGlobalWatchlistWikibaseHandler.prototype.cleanupRawLabels = function ( rawLabels ) {\n\tthis.debug( 'cleanupRawLabels - starting (raw)', rawLabels );\n\n\tif ( !rawLabels || Object.keys( rawLabels ).length === 0 ) {\n\t\treturn {};\n\t}\n\n\tconst cleanedLabels = {};\n\tconst entityIds = Object.keys( rawLabels );\n\tconst that = this;\n\tlet entityInfo,\n\t\tlabelKey;\n\n\tentityIds.forEach( ( entityId ) => {\n\t\t// Object.keys -> known to be a valid key\n\t\tentityInfo = rawLabels[ entityId ];\n\n\t\t// Lexemes have `lemmas`, items and properties have `labels`\n\t\tif ( entityInfo.type === 'lexeme' ) {\n\t\t\tlabelKey = 'lemmas';\n\t\t} else {\n\t\t\tlabelKey = 'labels';\n\t\t}\n\n\t\tif ( entityInfo[ labelKey ] &&\n\t\t\tentityInfo[ labelKey ][ that.userLang ] &&\n\t\t\tentityInfo[ labelKey ][ that.userLang ].value\n\t\t) {\n\t\t\tcleanedLabels[ entityId ] = entityInfo[ labelKey ][ that.userLang ].value;\n\t\t}\n\t} );\n\tthis.debug( 'cleanupRawLabels - ending (clean)', cleanedLabels );\n\n\treturn cleanedLabels;\n};\n\n/**\n * Set entities' $titleMsg (title without the `Property:` or `Lexeme:` prefix) and\n * get a list of the ids to fetch in the form of Q1/P2/L3\n *\n * @param {GlobalWatchlistEntryBase[]} entries Original summary entries\n * @return {Object} updated entries and ids\n */\nGlobalWatchlistWikibaseHandler.prototype.getEntityIds = function ( entries ) {\n\tconst ids = [];\n\n\tentries.forEach( ( entry ) => {\n\t\tif ( this.namespaces.includes( entry.ns ) || this.esNamespaces.includes( entry.ns ) ) {\n\t\t\tconst prefixw = this.nsNames.find( ( name ) => entry.title.startsWith( name + ':' ) );\n\t\t\tconst prefixe = prefixw ? null : this.esNsNames.find( ( name ) => entry.title.startsWith( name + ':' ) );\n\t\t\tconst titleMsgRaw = prefixw ? entry.title.slice( prefixw.length + 1 ) :\n\t\t\t\t( prefixe ? entry.title.slice( prefixe.length + 1 ) : entry.title );\n\t\t\tentry.$titleMsg = $( document.createTextNode( titleMsgRaw ) );\n\t\t\tif ( !ids.includes( titleMsgRaw ) ) {\n\t\t\t\tids.push( titleMsgRaw );\n\t\t\t}\n\t\t} else {\n\t\t\tentry.$titleMsg = $( document.createTextNode( entry.title ) );\n\t\t}\n\t} );\n\n\treturn {\n\t\tentries: entries,\n\t\tids: ids\n\t};\n};\n\n/**\n * Entry point - alter the entities given to have $titleMsg that reflects the labels\n *\n * Promise resolves to the summary entries with updated info\n *\n * @param {GlobalWatchlistEntryBase[]} summaryEntries Original summary, entries have $titleMsg as\n *   just the plain title (Q1, P2, L3, etc.)\n * @return {Promise} Promise of updated summary, with labels\n */\nGlobalWatchlistWikibaseHandler.prototype.addWikibaseLabels = function ( summaryEntries ) {\n\tconst that = this;\n\n\treturn new Promise( ( resolve ) => {\n\t\tconst extractedInfo = that.getEntityIds( summaryEntries );\n\t\tthat.debug( 'addLabels - extractedInfo', extractedInfo );\n\n\t\tconst updatedEntries = extractedInfo.entries;\n\t\tconst entityIds = extractedInfo.ids.filter( ( id ) => !id.startsWith( 'E' ) );\n\n\t\tthat.getRawLabels( entityIds ).then( ( rawLabels ) => {\n\t\t\tconst cleanedLabels = that.cleanupRawLabels( rawLabels );\n\n\t\t\tupdatedEntries.forEach( ( entry ) => {\n\t\t\t\tconst cleanedLabelsData = cleanedLabels[ mw.html.escape( entry.$titleMsg.text() ) ];\n\t\t\t\tif ( cleanedLabelsData ) {\n\t\t\t\t\tentry.$titleMsg = $( '<span>' ).append(\n\t\t\t\t\t\tentry.$titleMsg,\n\t\t\t\t\t\t[ ' (', $( '<bdi>' ).text( cleanedLabelsData ), ')' ] );\n\t\t\t\t} else {\n\t\t\t\t\tconst titleEs = entry.$titleMsg.text();\n\t\t\t\t\tconst $esElem = $( '<bdi>' );\n\t\t\t\t\tif ( that.esCache[ titleEs ] ) {\n\t\t\t\t\t\t$esElem.text( that.esCache[ titleEs ] );\n\t\t\t\t\t\tentry.$titleMsg = $( '<span>' ).append( entry.$titleMsg, ' (', $esElem, ')' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet promise = that.esPromiseCache[ titleEs ];\n\t\t\t\t\t\tentry.$titleMsg = $( '<span>' ).append( entry.$titleMsg, $esElem );\n\t\t\t\t\t\tif ( !promise ) {\n\t\t\t\t\t\t\tpromise = that.calculateRealTextAsync( titleEs )\n\t\t\t\t\t\t\t\t.then( ( realText ) => {\n\t\t\t\t\t\t\t\t\tdelete that.esPromiseCache[ titleEs ];\n\t\t\t\t\t\t\t\t\tif ( realText && realText !== '' ) {\n\t\t\t\t\t\t\t\t\t\tthat.esCache[ titleEs ] = realText;\n\t\t\t\t\t\t\t\t\t\tthat.debug( 'new cache', that.esCache );\n\t\t\t\t\t\t\t\t\t\treturn realText;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t\t.catch( () => {\n\t\t\t\t\t\t\t\t\tdelete that.esPromiseCache[ titleEs ];\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\tthat.esPromiseCache[ titleEs ] = promise;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpromise.then( ( realText ) => {\n\t\t\t\t\t\t\tthat.debug( 'saving realText to', $esElem );\n\t\t\t\t\t\t\tif ( realText && realText !== '' ) {\n\t\t\t\t\t\t\t\t$esElem.text( that.esCache[ titleEs ] );\n\t\t\t\t\t\t\t\tentry.$titleMsg.append( ' (', $esElem, ')' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tresolve( updatedEntries );\n\t\t} );\n\t} );\n};\n\nGlobalWatchlistWikibaseHandler.prototype.calculateRealTextAsync = function ( id ) {\n\tthis.debug( 'Calculating', id );\n\n\treturn this.api.get( {\n\t\taction: 'wbsearchentities',\n\t\tsearch: id,\n\t\tlanguage: this.userLang,\n\t\tuselang: this.userLang,\n\t\ttype: 'entity-schema',\n\t\tformatversion: 2\n\t} ).then( ( data ) => {\n\t\tconst match = data.search.find( ( result ) => this.esNsNames\n\t\t\t.some( ( ns ) => result.title === `${ ns }:${ id }` )\n\t\t);\n\n\t\treturn match ? match.label : false;\n\t} ).catch( () => false );\n};\n\nmodule.exports = GlobalWatchlistWikibaseHandler;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/specialglobalwatchlist/getSettings.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'GlobalWatchlistDebugger' is undefined.","line":24,"column":1,"nodeType":"Block","endLine":24,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*\n * Retrieve current user settings to use, or the defaults\n *\n * Used for both versions of Special:GlobalWatchlist\n */\n/**\n * @private\n * @param {number} setting Current stored level\n * @param {string} flag\n * @return {string}\n */\nfunction getQueryFlag( setting, flag ) {\n\tif ( setting === 1 ) {\n\t\treturn ( '|' + flag );\n\t}\n\tif ( setting === 2 ) {\n\t\treturn ( '|!' + flag );\n\t}\n\treturn '';\n}\n\n/**\n * @private\n * @param {GlobalWatchlistDebugger} globalWatchlistDebug\n * @return {Object}\n */\nfunction globalWatchlistGetSettings( globalWatchlistDebug ) {\n\t// Note: this must be the same key as SettingsManager::PREFERENCE_NAME\n\tconst userOptions = mw.user.options.get( 'global-watchlist-options' ),\n\t\tdefaultConfig = {\n\t\t\tsiteList: [\n\t\t\t\tmw.config.get( 'wgServer' ).replace( /.*?\\/\\//, '' )\n\t\t\t],\n\t\t\tanon: 0,\n\t\t\tbot: 0,\n\t\t\tminor: 0,\n\t\t\tconfirmAllSites: true,\n\t\t\tfastMode: false,\n\t\t\tgroupPage: true,\n\t\t\tshowEdits: true,\n\t\t\tshowLogEntries: true,\n\t\t\tshowNewPages: true\n\t\t};\n\n\tlet config;\n\tif ( userOptions === null ) {\n\t\tconfig = defaultConfig;\n\t} else {\n\t\ttry {\n\t\t\tconst userSettings = JSON.parse( userOptions );\n\t\t\tconfig = {\n\t\t\t\tsiteList: userSettings.sites,\n\t\t\t\tanon: userSettings.anonfilter,\n\t\t\t\tbot: userSettings.botfilter,\n\t\t\t\tminor: userSettings.minorfilter,\n\t\t\t\tconfirmAllSites: userSettings.confirmallsites,\n\t\t\t\tfastMode: userSettings.fastmode,\n\t\t\t\tgroupPage: userSettings.grouppage,\n\t\t\t\tshowEdits: userSettings.showtypes.includes( 'edit' ),\n\t\t\t\tshowLogEntries: userSettings.showtypes.includes( 'log' ),\n\t\t\t\tshowNewPages: userSettings.showtypes.includes( 'new' )\n\t\t\t};\n\t\t} catch ( e ) {\n\t\t\t// Not using .error since it can be recovered from, and the user notice\n\t\t\t// should be the one in getsettingserror rather than a plain `alert` call\n\t\t\tglobalWatchlistDebug.info( 'GetSettings - error', e );\n\n\t\t\t// Alert the user\n\t\t\tmw.loader.load( 'ext.globalwatchlist.getsettingserror' );\n\n\t\t\tconfig = defaultConfig;\n\t\t}\n\t}\n\n\t// Get the uselang URL parameter if provided, leave null otherwise\n\t// The language code is checked for existing later after the languageinfo API call\n\tconfig.lang = mw.util.getParamValue( 'uselang' );\n\n\t// The following settings are extracted from the user's set configuration or the defaults\n\t// or are not set in the options\n\tconfig.watchlistQueryProps = config.fastMode ?\n\t\t'ids|title|flags|loginfo' :\n\t\t'ids|title|flags|loginfo|parsedcomment|timestamp|user|tags|expiry|labels';\n\n\tconfig.watchlistQueryTypes = (\n\t\t( config.showEdits ? 'edit|' : '' ) +\n\t\t( config.showNewPages ? 'new|' : '' ) +\n\t\t( config.showLogEntries ? 'log|' : '' )\n\t).replace( /\\|+$/, '' );\n\n\tconfig.watchlistQueryShow = [\n\t\t'unread',\n\t\tgetQueryFlag( config.anon, 'anon' ),\n\t\tgetQueryFlag( config.bot, 'bot' ),\n\t\tgetQueryFlag( config.minor, 'minor' )\n\t].join( '' ).replace( /^\\|+/, '' );\n\n\treturn config;\n}\n\nmodule.exports = globalWatchlistGetSettings;\n","usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/package-lock.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/package.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/.eslintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/qunit/Debug.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/qunit/Linker.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/qunit/WatchlistUtils.test.js","messages":[],"suppressedMessages":[{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":57,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":57,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_a' is not in camel case.","line":63,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":63,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":67,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":67,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_b' is not in camel case.","line":73,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":73,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":77,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":77,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_c' is not in camel case.","line":83,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":83,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":87,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":87,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_d' is not in camel case.","line":93,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":93,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":97,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":97,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_e' is not in camel case.","line":103,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":103,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'old_revid' is not in camel case.","line":107,"column":4,"nodeType":"Identifier","messageId":"notCamelCase","endLine":107,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'mergedEdits_a' is not in camel case.","line":114,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":114,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'mergedEdits_b' is not in camel case.","line":128,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":128,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'mergedEdits_c' is not in camel case.","line":142,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":142,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'mergedEdits_d' is not in camel case.","line":156,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":156,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'mergedEdits_e' is not in camel case.","line":170,"column":9,"nodeType":"Identifier","messageId":"notCamelCase","endLine":170,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_a' is not in camel case.","line":186,"column":44,"nodeType":"Identifier","messageId":"notCamelCase","endLine":186,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_b' is not in camel case.","line":191,"column":44,"nodeType":"Identifier","messageId":"notCamelCase","endLine":191,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_c' is not in camel case.","line":196,"column":44,"nodeType":"Identifier","messageId":"notCamelCase","endLine":196,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_d' is not in camel case.","line":201,"column":44,"nodeType":"Identifier","messageId":"notCamelCase","endLine":201,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"camelcase","severity":2,"message":"Identifier 'edit2_e' is not in camel case.","line":206,"column":44,"nodeType":"Identifier","messageId":"notCamelCase","endLine":206,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":349,"column":18,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":349,"endColumn":25,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":350,"column":16,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":350,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":351,"column":14,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":351,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":364,"column":12,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":364,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":365,"column":12,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":365,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '&'.","line":366,"column":12,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":366,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/qunit/getSettings.test.js","messages":[],"suppressedMessages":[{"ruleId":"no-unused-vars","severity":2,"message":"'unused' is defined but never used.","line":8,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-unused-vars","severity":2,"message":"'alsoUnused' is defined but never used.","line":8,"column":34,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"valid-jsdoc","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/selenium/.eslintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/selenium/package.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/selenium/pageobjects/GlobalWatchlist.page.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/selenium/specs/SpecialGlobalWatchlist.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/selenium/wdio.conf.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-spacing","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"indent","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-len","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multi-spaces","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"spaced-comment","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"wrap-iife","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]}]

--- end ---
$ /usr/bin/npm ci
--- stderr ---
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated glob@7.2.3: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
--- stdout ---

added 882 packages, and audited 883 packages in 18s

199 packages are looking for funding
  run `npm fund` for details

12 vulnerabilities (6 moderate, 4 high, 2 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ /usr/bin/npm test
--- stdout ---

> test
> npm run lint


> lint
> npm run lint:eslint && npm run lint:styles && npm run lint:i18n


> lint:eslint
> eslint --cache .


/src/repo/modules/specialglobalwatchlist/EntryBase.js
  50:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types
  56:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/MultiSiteWrapper.js
   7:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined  jsdoc/no-undefined-types
  10:1  warning  The type 'GlobalWatchlistDebugger' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteBase.js
    8:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
    9:1  warning  The type 'GlobalWatchlistLinker' is undefined          jsdoc/no-undefined-types
   12:1  warning  The type 'GlobalWatchlistWatchlistUtils' is undefined  jsdoc/no-undefined-types
  318:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  443:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  445:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  457:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  506:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  514:1  warning  This line has a length of 103. Maximum allowed is 100  max-len
  557:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  567:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteDisplay.js
   14:1   warning  The type 'GlobalWatchlistDebugger' is undefined                                    jsdoc/no-undefined-types
   15:1   warning  The type 'GlobalWatchlistLinker' is undefined                                      jsdoc/no-undefined-types
   18:1   warning  The type 'GlobalWatchlistWatchlistUtils' is undefined                              jsdoc/no-undefined-types
   48:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types
  105:1   warning  This line has a length of 111. Maximum allowed is 100                              max-len
  248:1   warning  This line has a length of 107. Maximum allowed is 100                              max-len
  261:26  warning  All possible CSS classes should be documented. See https://w.wiki/PS2 for details  mediawiki/class-doc
  296:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/WatchlistUtils.js
    7:1  warning  The type 'GlobalWatchlistLinker' is undefined               jsdoc/no-undefined-types
   72:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  113:1  warning  This line has a length of 101. Maximum allowed is 100       max-len
  167:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  313:1  warning  The type 'GlobalWatchlistSiteBase.getTagList' is undefined  jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  325:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  408:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  429:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  429:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  432:1  warning  This line has a length of 110. Maximum allowed is 100       max-len
  446:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  548:1  warning  This line has a length of 105. Maximum allowed is 100       max-len

/src/repo/modules/specialglobalwatchlist/WikibaseHandler.js
    9:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
   13:1  warning  This line has a length of 104. Maximum allowed is 100  max-len
   15:1  warning  This line has a length of 101. Maximum allowed is 100  max-len
  207:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  239:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/getSettings.js
  24:1  warning  The type 'GlobalWatchlistDebugger' is undefined  jsdoc/no-undefined-types

✖ 47 problems (0 errors, 47 warnings)


> lint:styles
> stylelint --cache "**/*.{css,less}"


> lint:i18n
> banana-checker --requireLowerCase=0 i18n/

Checked 1 message directory.

--- end ---
Upgrading c:mediawiki/mediawiki-codesniffer from 50.0.0 -> 51.0.0
$ /usr/bin/composer update
--- stderr ---
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 3 updates, 0 removals
  - Upgrading composer/spdx-licenses (1.5.10 => 1.6.0)
  - Upgrading mediawiki/mediawiki-codesniffer (v50.0.0 => v51.0.0)
  - Upgrading phpcsstandards/phpcsextra (1.4.0 => 1.5.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 3 updates, 0 removals
    0 [>---------------------------]    0 [->--------------------------]
  - Upgrading phpcsstandards/phpcsextra (1.4.0 => 1.5.0): Extracting archive
  - Upgrading composer/spdx-licenses (1.5.10 => 1.6.0): Extracting archive
  - Upgrading mediawiki/mediawiki-codesniffer (v50.0.0 => v51.0.0): Extracting archive
 0/3 [>---------------------------]   0%
 3/3 [============================] 100%
Generating autoload files
16 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
--- stdout ---

--- end ---
$ vendor/bin/phpcs --report=json
--- stdout ---
{"totals":{"errors":0,"warnings":0,"fixable":0},"files":{"\/src\/repo\/includes\/GlobalWatchlistGuidedTourHooks.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/.phan\/config.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/GlobalWatchlist.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/integration\/ServiceWiringTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/unit\/GlobalWatchlistGuidedTourHooksTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/SpecialGlobalWatchlist.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/.phan\/stubs\/CentralAuthUser.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/ServiceWiring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/GlobalWatchlistHooks.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/SettingsFormValidator.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/SettingsManager.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/integration\/SpecialGlobalWatchlistTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/unit\/SettingsManagerTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/unit\/GlobalWatchlistHooksTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/unit\/SettingsFormValidatorTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/SpecialGlobalWatchlistSettings.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/integration\/SpecialGlobalWatchlistSettingsTest.php":{"errors":0,"warnings":0,"messages":[]}}}

--- end ---
$ /usr/bin/composer install
--- stderr ---
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating autoload files
16 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
--- stdout ---

--- end ---
$ /usr/bin/composer test
--- stderr ---
> parallel-lint . --exclude vendor --exclude node_modules
> phpcs -sp --cache
> minus-x check .
--- stdout ---
PHP 8.4.18 | 10 parallel jobs
.................                                            17/17 (100%)


Checked 17 files in 0.1 seconds
No syntax error found
................. 17 / 17 (100%)


Time: 194ms; Memory: 8MB

MinusX
======
Processing /src/repo...
.............................................................
.............................................................
.............................................................
...........
All good!

--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "@wdio/mocha-framework": {
      "name": "@wdio/mocha-framework",
      "severity": "high",
      "isDirect": true,
      "via": [
        "mocha"
      ],
      "effects": [],
      "range": ">=6.1.19",
      "nodes": [
        "node_modules/@wdio/mocha-framework"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "basic-ftp": {
      "name": "basic-ftp",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1117726,
          "name": "basic-ftp",
          "dependency": "basic-ftp",
          "title": "basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering",
          "url": "https://github.com/advisories/GHSA-rpmf-866q-6p89",
          "severity": "high",
          "cwe": [
            "CWE-400",
            "CWE-770"
          ],
          "cvss": {
            "score": 7.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
          },
          "range": "<=5.3.0"
        }
      ],
      "effects": [],
      "range": "<=5.3.0",
      "nodes": [
        "node_modules/basic-ftp"
      ],
      "fixAvailable": true
    },
    "form-data": {
      "name": "form-data",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1109540,
          "name": "form-data",
          "dependency": "form-data",
          "title": "form-data uses unsafe random function in form-data for choosing boundary",
          "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4",
          "severity": "critical",
          "cwe": [
            "CWE-330"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<2.5.4"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<2.5.4",
      "nodes": [
        "node_modules/form-data"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "ip-address": {
      "name": "ip-address",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1117683,
          "name": "ip-address",
          "dependency": "ip-address",
          "title": "ip-address has XSS in Address6 HTML-emitting methods",
          "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g",
          "severity": "moderate",
          "cwe": [
            "CWE-79"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<=10.1.0"
        }
      ],
      "effects": [
        "socks"
      ],
      "range": "<=10.1.0",
      "nodes": [
        "node_modules/ip-address"
      ],
      "fixAvailable": true
    },
    "mocha": {
      "name": "mocha",
      "severity": "high",
      "isDirect": false,
      "via": [
        "serialize-javascript"
      ],
      "effects": [
        "@wdio/mocha-framework"
      ],
      "range": "8.0.0 - 12.0.0-beta-2",
      "nodes": [
        "node_modules/mocha"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "mwbot": {
      "name": "mwbot",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        "request"
      ],
      "effects": [
        "wdio-mediawiki"
      ],
      "range": ">=0.1.6",
      "nodes": [
        "node_modules/mwbot"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "qs": {
      "name": "qs",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1113719,
          "name": "qs",
          "dependency": "qs",
          "title": "qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion",
          "url": "https://github.com/advisories/GHSA-6rw7-vpxm-498p",
          "severity": "moderate",
          "cwe": [
            "CWE-20"
          ],
          "cvss": {
            "score": 3.7,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": "<6.14.1"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<6.14.1",
      "nodes": [
        "node_modules/qs"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "request": {
      "name": "request",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1096727,
          "name": "request",
          "dependency": "request",
          "title": "Server-Side Request Forgery in Request",
          "url": "https://github.com/advisories/GHSA-p8p7-x288-28g6",
          "severity": "moderate",
          "cwe": [
            "CWE-918"
          ],
          "cvss": {
            "score": 6.1,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"
          },
          "range": "<=2.88.2"
        },
        "form-data",
        "qs",
        "tough-cookie"
      ],
      "effects": [
        "mwbot"
      ],
      "range": "*",
      "nodes": [
        "node_modules/request"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "serialize-javascript": {
      "name": "serialize-javascript",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1113686,
          "name": "serialize-javascript",
          "dependency": "serialize-javascript",
          "title": "Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString()",
          "url": "https://github.com/advisories/GHSA-5c6j-r48x-rmvq",
          "severity": "high",
          "cwe": [
            "CWE-96"
          ],
          "cvss": {
            "score": 8.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"
          },
          "range": "<=7.0.2"
        },
        {
          "source": 1115723,
          "name": "serialize-javascript",
          "dependency": "serialize-javascript",
          "title": "Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects",
          "url": "https://github.com/advisories/GHSA-qj8w-gfj5-8c6v",
          "severity": "moderate",
          "cwe": [
            "CWE-400",
            "CWE-834"
          ],
          "cvss": {
            "score": 5.9,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"
          },
          "range": "<7.0.5"
        }
      ],
      "effects": [
        "mocha"
      ],
      "range": "<=7.0.4",
      "nodes": [
        "node_modules/serialize-javascript"
      ],
      "fixAvailable": {
        "name": "@wdio/mocha-framework",
        "version": "6.1.17",
        "isSemVerMajor": true
      }
    },
    "socks": {
      "name": "socks",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        "ip-address"
      ],
      "effects": [],
      "range": "2.7.2 - 2.8.6",
      "nodes": [
        "node_modules/socks"
      ],
      "fixAvailable": true
    },
    "tough-cookie": {
      "name": "tough-cookie",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1097682,
          "name": "tough-cookie",
          "dependency": "tough-cookie",
          "title": "tough-cookie Prototype Pollution vulnerability",
          "url": "https://github.com/advisories/GHSA-72xf-g2v4-qvf3",
          "severity": "moderate",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 6.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"
          },
          "range": "<4.1.3"
        }
      ],
      "effects": [
        "request"
      ],
      "range": "<4.1.3",
      "nodes": [
        "node_modules/tough-cookie"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    },
    "wdio-mediawiki": {
      "name": "wdio-mediawiki",
      "severity": "moderate",
      "isDirect": true,
      "via": [
        "mwbot"
      ],
      "effects": [],
      "range": "<=5.1.0",
      "nodes": [
        "node_modules/wdio-mediawiki"
      ],
      "fixAvailable": {
        "name": "wdio-mediawiki",
        "version": "6.5.1",
        "isSemVerMajor": true
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 0,
      "moderate": 6,
      "high": 4,
      "critical": 2,
      "total": 12
    },
    "dependencies": {
      "prod": 1,
      "dev": 907,
      "optional": 37,
      "peer": 29,
      "peerOptional": 0,
      "total": 907
    }
  }
}

--- end ---
Attempting to npm audit fix
$ /usr/bin/npm audit fix --dry-run --only=dev --json
--- stderr ---
npm WARN invalid config only="dev" set in command line options
npm WARN invalid config Must be one of: null, prod, production
--- stdout ---
{
  "added": 25,
  "removed": 2,
  "changed": 3,
  "audited": 906,
  "funding": 199,
  "audit": {
    "auditReportVersion": 2,
    "vulnerabilities": {
      "@wdio/mocha-framework": {
        "name": "@wdio/mocha-framework",
        "severity": "high",
        "isDirect": true,
        "via": [
          "mocha"
        ],
        "effects": [],
        "range": ">=6.1.19",
        "nodes": [
          "node_modules/@wdio/mocha-framework"
        ],
        "fixAvailable": {
          "name": "@wdio/mocha-framework",
          "version": "6.1.17",
          "isSemVerMajor": true
        }
      },
      "basic-ftp": {
        "name": "basic-ftp",
        "severity": "high",
        "isDirect": false,
        "via": [
          {
            "source": 1117726,
            "name": "basic-ftp",
            "dependency": "basic-ftp",
            "title": "basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering",
            "url": "https://github.com/advisories/GHSA-rpmf-866q-6p89",
            "severity": "high",
            "cwe": [
              "CWE-400",
              "CWE-770"
            ],
            "cvss": {
              "score": 7.5,
              "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
            },
            "range": "<=5.3.0"
          }
        ],
        "effects": [],
        "range": "<=5.3.0",
        "nodes": [
          ""
        ],
        "fixAvailable": true
      },
      "form-data": {
        "name": "form-data",
        "severity": "critical",
        "isDirect": false,
        "via": [
          {
            "source": 1109540,
            "name": "form-data",
            "dependency": "form-data",
            "title": "form-data uses unsafe random function in form-data for choosing boundary",
            "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4",
            "severity": "critical",
            "cwe": [
              "CWE-330"
            ],
            "cvss": {
              "score": 0,
              "vectorString": null
            },
            "range": "<2.5.4"
          }
        ],
        "effects": [
          "request"
        ],
        "range": "<2.5.4",
        "nodes": [
          "node_modules/form-data"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      },
      "ip-address": {
        "name": "ip-address",
        "severity": "moderate",
        "isDirect": false,
        "via": [
          {
            "source": 1117683,
            "name": "ip-address",
            "dependency": "ip-address",
            "title": "ip-address has XSS in Address6 HTML-emitting methods",
            "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g",
            "severity": "moderate",
            "cwe": [
              "CWE-79"
            ],
            "cvss": {
              "score": 0,
              "vectorString": null
            },
            "range": "<=10.1.0"
          }
        ],
        "effects": [
          "socks"
        ],
        "range": "<=10.1.0",
        "nodes": [
          ""
        ],
        "fixAvailable": true
      },
      "mocha": {
        "name": "mocha",
        "severity": "high",
        "isDirect": false,
        "via": [
          "serialize-javascript"
        ],
        "effects": [
          "@wdio/mocha-framework"
        ],
        "range": "8.0.0 - 12.0.0-beta-2",
        "nodes": [
          "node_modules/mocha"
        ],
        "fixAvailable": {
          "name": "@wdio/mocha-framework",
          "version": "6.1.17",
          "isSemVerMajor": true
        }
      },
      "mwbot": {
        "name": "mwbot",
        "severity": "moderate",
        "isDirect": false,
        "via": [
          "request"
        ],
        "effects": [
          "wdio-mediawiki"
        ],
        "range": ">=0.1.6",
        "nodes": [
          "node_modules/mwbot"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      },
      "qs": {
        "name": "qs",
        "severity": "moderate",
        "isDirect": false,
        "via": [
          {
            "source": 1113719,
            "name": "qs",
            "dependency": "qs",
            "title": "qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion",
            "url": "https://github.com/advisories/GHSA-6rw7-vpxm-498p",
            "severity": "moderate",
            "cwe": [
              "CWE-20"
            ],
            "cvss": {
              "score": 3.7,
              "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"
            },
            "range": "<6.14.1"
          }
        ],
        "effects": [
          "request"
        ],
        "range": "<6.14.1",
        "nodes": [
          "node_modules/qs"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      },
      "request": {
        "name": "request",
        "severity": "critical",
        "isDirect": false,
        "via": [
          {
            "source": 1096727,
            "name": "request",
            "dependency": "request",
            "title": "Server-Side Request Forgery in Request",
            "url": "https://github.com/advisories/GHSA-p8p7-x288-28g6",
            "severity": "moderate",
            "cwe": [
              "CWE-918"
            ],
            "cvss": {
              "score": 6.1,
              "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"
            },
            "range": "<=2.88.2"
          },
          "form-data",
          "qs",
          "tough-cookie"
        ],
        "effects": [
          "mwbot"
        ],
        "range": "*",
        "nodes": [
          "node_modules/request"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      },
      "serialize-javascript": {
        "name": "serialize-javascript",
        "severity": "high",
        "isDirect": false,
        "via": [
          {
            "source": 1113686,
            "name": "serialize-javascript",
            "dependency": "serialize-javascript",
            "title": "Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString()",
            "url": "https://github.com/advisories/GHSA-5c6j-r48x-rmvq",
            "severity": "high",
            "cwe": [
              "CWE-96"
            ],
            "cvss": {
              "score": 8.1,
              "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"
            },
            "range": "<=7.0.2"
          },
          {
            "source": 1115723,
            "name": "serialize-javascript",
            "dependency": "serialize-javascript",
            "title": "Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects",
            "url": "https://github.com/advisories/GHSA-qj8w-gfj5-8c6v",
            "severity": "moderate",
            "cwe": [
              "CWE-400",
              "CWE-834"
            ],
            "cvss": {
              "score": 5.9,
              "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"
            },
            "range": "<7.0.5"
          }
        ],
        "effects": [
          "mocha"
        ],
        "range": "<=7.0.4",
        "nodes": [
          "node_modules/serialize-javascript"
        ],
        "fixAvailable": {
          "name": "@wdio/mocha-framework",
          "version": "6.1.17",
          "isSemVerMajor": true
        }
      },
      "socks": {
        "name": "socks",
        "severity": "moderate",
        "isDirect": false,
        "via": [
          "ip-address"
        ],
        "effects": [],
        "range": "2.7.2 - 2.8.6",
        "nodes": [
          ""
        ],
        "fixAvailable": true
      },
      "tough-cookie": {
        "name": "tough-cookie",
        "severity": "moderate",
        "isDirect": false,
        "via": [
          {
            "source": 1097682,
            "name": "tough-cookie",
            "dependency": "tough-cookie",
            "title": "tough-cookie Prototype Pollution vulnerability",
            "url": "https://github.com/advisories/GHSA-72xf-g2v4-qvf3",
            "severity": "moderate",
            "cwe": [
              "CWE-1321"
            ],
            "cvss": {
              "score": 6.5,
              "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"
            },
            "range": "<4.1.3"
          }
        ],
        "effects": [
          "request"
        ],
        "range": "<4.1.3",
        "nodes": [
          "node_modules/tough-cookie"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      },
      "wdio-mediawiki": {
        "name": "wdio-mediawiki",
        "severity": "moderate",
        "isDirect": true,
        "via": [
          "mwbot"
        ],
        "effects": [],
        "range": "<=5.1.0",
        "nodes": [
          "node_modules/wdio-mediawiki"
        ],
        "fixAvailable": {
          "name": "wdio-mediawiki",
          "version": "6.5.1",
          "isSemVerMajor": true
        }
      }
    },
    "metadata": {
      "vulnerabilities": {
        "info": 0,
        "low": 0,
        "moderate": 6,
        "high": 4,
        "critical": 2,
        "total": 12
      },
      "dependencies": {
        "prod": 1,
        "dev": 905,
        "optional": 37,
        "peer": 29,
        "peerOptional": 0,
        "total": 905
      }
    }
  }
}

--- end ---
{"added": 25, "removed": 2, "changed": 3, "audited": 906, "funding": 199, "audit": {"auditReportVersion": 2, "vulnerabilities": {"@wdio/mocha-framework": {"name": "@wdio/mocha-framework", "severity": "high", "isDirect": true, "via": ["mocha"], "effects": [], "range": ">=6.1.19", "nodes": ["node_modules/@wdio/mocha-framework"], "fixAvailable": {"name": "@wdio/mocha-framework", "version": "6.1.17", "isSemVerMajor": true}}, "basic-ftp": {"name": "basic-ftp", "severity": "high", "isDirect": false, "via": [{"source": 1117726, "name": "basic-ftp", "dependency": "basic-ftp", "title": "basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering", "url": "https://github.com/advisories/GHSA-rpmf-866q-6p89", "severity": "high", "cwe": ["CWE-400", "CWE-770"], "cvss": {"score": 7.5, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"}, "range": "<=5.3.0"}], "effects": [], "range": "<=5.3.0", "nodes": [""], "fixAvailable": true}, "form-data": {"name": "form-data", "severity": "critical", "isDirect": false, "via": [{"source": 1109540, "name": "form-data", "dependency": "form-data", "title": "form-data uses unsafe random function in form-data for choosing boundary", "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4", "severity": "critical", "cwe": ["CWE-330"], "cvss": {"score": 0, "vectorString": null}, "range": "<2.5.4"}], "effects": ["request"], "range": "<2.5.4", "nodes": ["node_modules/form-data"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}, "ip-address": {"name": "ip-address", "severity": "moderate", "isDirect": false, "via": [{"source": 1117683, "name": "ip-address", "dependency": "ip-address", "title": "ip-address has XSS in Address6 HTML-emitting methods", "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g", "severity": "moderate", "cwe": ["CWE-79"], "cvss": {"score": 0, "vectorString": null}, "range": "<=10.1.0"}], "effects": ["socks"], "range": "<=10.1.0", "nodes": [""], "fixAvailable": true}, "mocha": {"name": "mocha", "severity": "high", "isDirect": false, "via": ["serialize-javascript"], "effects": ["@wdio/mocha-framework"], "range": "8.0.0 - 12.0.0-beta-2", "nodes": ["node_modules/mocha"], "fixAvailable": {"name": "@wdio/mocha-framework", "version": "6.1.17", "isSemVerMajor": true}}, "mwbot": {"name": "mwbot", "severity": "moderate", "isDirect": false, "via": ["request"], "effects": ["wdio-mediawiki"], "range": ">=0.1.6", "nodes": ["node_modules/mwbot"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}, "qs": {"name": "qs", "severity": "moderate", "isDirect": false, "via": [{"source": 1113719, "name": "qs", "dependency": "qs", "title": "qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion", "url": "https://github.com/advisories/GHSA-6rw7-vpxm-498p", "severity": "moderate", "cwe": ["CWE-20"], "cvss": {"score": 3.7, "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"}, "range": "<6.14.1"}], "effects": ["request"], "range": "<6.14.1", "nodes": ["node_modules/qs"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}, "request": {"name": "request", "severity": "critical", "isDirect": false, "via": [{"source": 1096727, "name": "request", "dependency": "request", "title": "Server-Side Request Forgery in Request", "url": "https://github.com/advisories/GHSA-p8p7-x288-28g6", "severity": "moderate", "cwe": ["CWE-918"], "cvss": {"score": 6.1, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"}, "range": "<=2.88.2"}, "form-data", "qs", "tough-cookie"], "effects": ["mwbot"], "range": "*", "nodes": ["node_modules/request"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}, "serialize-javascript": {"name": "serialize-javascript", "severity": "high", "isDirect": false, "via": [{"source": 1113686, "name": "serialize-javascript", "dependency": "serialize-javascript", "title": "Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString()", "url": "https://github.com/advisories/GHSA-5c6j-r48x-rmvq", "severity": "high", "cwe": ["CWE-96"], "cvss": {"score": 8.1, "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"}, "range": "<=7.0.2"}, {"source": 1115723, "name": "serialize-javascript", "dependency": "serialize-javascript", "title": "Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects", "url": "https://github.com/advisories/GHSA-qj8w-gfj5-8c6v", "severity": "moderate", "cwe": ["CWE-400", "CWE-834"], "cvss": {"score": 5.9, "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"}, "range": "<7.0.5"}], "effects": ["mocha"], "range": "<=7.0.4", "nodes": ["node_modules/serialize-javascript"], "fixAvailable": {"name": "@wdio/mocha-framework", "version": "6.1.17", "isSemVerMajor": true}}, "socks": {"name": "socks", "severity": "moderate", "isDirect": false, "via": ["ip-address"], "effects": [], "range": "2.7.2 - 2.8.6", "nodes": [""], "fixAvailable": true}, "tough-cookie": {"name": "tough-cookie", "severity": "moderate", "isDirect": false, "via": [{"source": 1097682, "name": "tough-cookie", "dependency": "tough-cookie", "title": "tough-cookie Prototype Pollution vulnerability", "url": "https://github.com/advisories/GHSA-72xf-g2v4-qvf3", "severity": "moderate", "cwe": ["CWE-1321"], "cvss": {"score": 6.5, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"}, "range": "<4.1.3"}], "effects": ["request"], "range": "<4.1.3", "nodes": ["node_modules/tough-cookie"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}, "wdio-mediawiki": {"name": "wdio-mediawiki", "severity": "moderate", "isDirect": true, "via": ["mwbot"], "effects": [], "range": "<=5.1.0", "nodes": ["node_modules/wdio-mediawiki"], "fixAvailable": {"name": "wdio-mediawiki", "version": "6.5.1", "isSemVerMajor": true}}}, "metadata": {"vulnerabilities": {"info": 0, "low": 0, "moderate": 6, "high": 4, "critical": 2, "total": 12}, "dependencies": {"prod": 1, "dev": 905, "optional": 37, "peer": 29, "peerOptional": 0, "total": 905}}}}
$ /usr/bin/npm audit fix --only=dev
--- stderr ---
npm WARN invalid config only="dev" set in command line options
npm WARN invalid config Must be one of: null, prod, production
--- stdout ---

removed 2 packages, changed 3 packages, and audited 881 packages in 3s

199 packages are looking for funding
  run `npm fund` for details

# npm audit report

form-data  <2.5.4
Severity: critical
form-data uses unsafe random function in form-data for choosing boundary - https://github.com/advisories/GHSA-fjxv-7rqg-78g4
fix available via `npm audit fix --force`
Will install wdio-mediawiki@6.5.1, which is a breaking change
node_modules/form-data
  request  *
  Depends on vulnerable versions of form-data
  Depends on vulnerable versions of qs
  Depends on vulnerable versions of tough-cookie
  node_modules/request
    mwbot  >=0.1.6
    Depends on vulnerable versions of request
    node_modules/mwbot
      wdio-mediawiki  <=5.1.0
      Depends on vulnerable versions of mwbot
      node_modules/wdio-mediawiki

qs  <6.14.1
Severity: moderate
qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion - https://github.com/advisories/GHSA-6rw7-vpxm-498p
fix available via `npm audit fix --force`
Will install wdio-mediawiki@6.5.1, which is a breaking change
node_modules/qs


serialize-javascript  <=7.0.4
Severity: high
Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.toISOString() - https://github.com/advisories/GHSA-5c6j-r48x-rmvq
Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like objects - https://github.com/advisories/GHSA-qj8w-gfj5-8c6v
fix available via `npm audit fix --force`
Will install @wdio/mocha-framework@6.1.17, which is a breaking change
node_modules/serialize-javascript
  mocha  8.0.0 - 12.0.0-beta-2
  Depends on vulnerable versions of serialize-javascript
  node_modules/mocha
    @wdio/mocha-framework  >=6.1.19
    Depends on vulnerable versions of mocha
    node_modules/@wdio/mocha-framework

tough-cookie  <4.1.3
Severity: moderate
tough-cookie Prototype Pollution vulnerability - https://github.com/advisories/GHSA-72xf-g2v4-qvf3
fix available via `npm audit fix --force`
Will install wdio-mediawiki@6.5.1, which is a breaking change
node_modules/tough-cookie

9 vulnerabilities (4 moderate, 3 high, 2 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

--- end ---
Verifying that tests still pass
$ /usr/bin/npm ci
--- stderr ---
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated glob@7.2.3: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
--- stdout ---

added 880 packages, and audited 881 packages in 17s

199 packages are looking for funding
  run `npm fund` for details

9 vulnerabilities (4 moderate, 3 high, 2 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ /usr/bin/npm test
--- stdout ---

> test
> npm run lint


> lint
> npm run lint:eslint && npm run lint:styles && npm run lint:i18n


> lint:eslint
> eslint --cache .


/src/repo/modules/specialglobalwatchlist/EntryBase.js
  50:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types
  56:1  warning  The type 'GlobalWatchlistWikibaseHandler' is undefined  jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/MultiSiteWrapper.js
   7:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined  jsdoc/no-undefined-types
  10:1  warning  The type 'GlobalWatchlistDebugger' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteBase.js
    8:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
    9:1  warning  The type 'GlobalWatchlistLinker' is undefined          jsdoc/no-undefined-types
   12:1  warning  The type 'GlobalWatchlistWatchlistUtils' is undefined  jsdoc/no-undefined-types
  318:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  443:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  445:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  457:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  506:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  514:1  warning  This line has a length of 103. Maximum allowed is 100  max-len
  557:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types
  567:1  warning  The type 'GlobalWatchlistSiteDisplay' is undefined     jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/SiteDisplay.js
   14:1   warning  The type 'GlobalWatchlistDebugger' is undefined                                    jsdoc/no-undefined-types
   15:1   warning  The type 'GlobalWatchlistLinker' is undefined                                      jsdoc/no-undefined-types
   18:1   warning  The type 'GlobalWatchlistWatchlistUtils' is undefined                              jsdoc/no-undefined-types
   48:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types
  105:1   warning  This line has a length of 111. Maximum allowed is 100                              max-len
  248:1   warning  This line has a length of 107. Maximum allowed is 100                              max-len
  261:26  warning  All possible CSS classes should be documented. See https://w.wiki/PS2 for details  mediawiki/class-doc
  296:1   warning  The type 'GlobalWatchlistEntryBase' is undefined                                   jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/WatchlistUtils.js
    7:1  warning  The type 'GlobalWatchlistLinker' is undefined               jsdoc/no-undefined-types
   72:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  113:1  warning  This line has a length of 101. Maximum allowed is 100       max-len
  167:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  313:1  warning  The type 'GlobalWatchlistSiteBase.getTagList' is undefined  jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  323:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  325:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  326:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  408:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  429:1  warning  This line has a length of 103. Maximum allowed is 100       max-len
  429:1  warning  The type 'GlobalWatchlistEntryBase' is undefined            jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryEdits' is undefined           jsdoc/no-undefined-types
  430:1  warning  The type 'GlobalWatchlistEntryLog' is undefined             jsdoc/no-undefined-types
  432:1  warning  This line has a length of 110. Maximum allowed is 100       max-len
  446:1  warning  This line has a length of 105. Maximum allowed is 100       max-len
  548:1  warning  This line has a length of 105. Maximum allowed is 100       max-len

/src/repo/modules/specialglobalwatchlist/WikibaseHandler.js
    9:1  warning  The type 'GlobalWatchlistDebugger' is undefined        jsdoc/no-undefined-types
   13:1  warning  This line has a length of 104. Maximum allowed is 100  max-len
   15:1  warning  This line has a length of 101. Maximum allowed is 100  max-len
  207:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types
  239:1  warning  The type 'GlobalWatchlistEntryBase' is undefined       jsdoc/no-undefined-types

/src/repo/modules/specialglobalwatchlist/getSettings.js
  24:1  warning  The type 'GlobalWatchlistDebugger' is undefined  jsdoc/no-undefined-types

✖ 47 problems (0 errors, 47 warnings)


> lint:styles
> stylelint --cache "**/*.{css,less}"


> lint:i18n
> banana-checker --requireLowerCase=0 i18n/

Checked 1 message directory.

--- end ---
{"1117726": {"source": 1117726, "name": "basic-ftp", "dependency": "basic-ftp", "title": "basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering", "url": "https://github.com/advisories/GHSA-rpmf-866q-6p89", "severity": "high", "cwe": ["CWE-400", "CWE-770"], "cvss": {"score": 7.5, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"}, "range": "<=5.3.0"}}
Upgrading n:basic-ftp from 5.3.0 -> 5.3.1
{"1117683": {"source": 1117683, "name": "ip-address", "dependency": "ip-address", "title": "ip-address has XSS in Address6 HTML-emitting methods", "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g", "severity": "moderate", "cwe": ["CWE-79"], "cvss": {"score": 0, "vectorString": null}, "range": "<=10.1.0"}}
Upgrading n:ip-address from 9.0.5 -> 10.2.0
{"1117683": {"source": 1117683, "name": "ip-address", "dependency": "ip-address", "title": "ip-address has XSS in Address6 HTML-emitting methods", "url": "https://github.com/advisories/GHSA-v2v4-37r5-5v8g", "severity": "moderate", "cwe": ["CWE-79"], "cvss": {"score": 0, "vectorString": null}, "range": "<=10.1.0"}}
Upgrading n:socks from 2.8.5 -> 2.8.8
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
build: Updating dependencies

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4
* basic-ftp: 5.3.0 → 5.3.1
  * https://github.com/advisories/GHSA-rpmf-866q-6p89
* ip-address: 9.0.5 → 10.2.0
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g
* socks: 2.8.5 → 2.8.8
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g


$ git add .
--- stdout ---

--- end ---
$ git commit -F /tmp/tmpeclkplzo
--- stdout ---
[master d738fe9] build: Updating dependencies
 4 files changed, 551 insertions(+), 425 deletions(-)

--- end ---
$ git format-patch HEAD~1 --stdout
--- stdout ---
From d738fe916d943ca33c809054ad15a48de890f2b8 Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Thu, 7 May 2026 07:11:45 +0000
Subject: [PATCH] build: Updating dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4
* basic-ftp: 5.3.0 → 5.3.1
  * https://github.com/advisories/GHSA-rpmf-866q-6p89
* ip-address: 9.0.5 → 10.2.0
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g
* socks: 2.8.5 → 2.8.8
  * https://github.com/advisories/GHSA-v2v4-37r5-5v8g

Change-Id: Ibb846942c6ccc271a6fc1134a7c7dd2791c10d14
---
 composer.json                                 |   2 +-
 modules/specialglobalwatchlist/SiteDisplay.js |   1 +
 package-lock.json                             | 971 ++++++++++--------
 package.json                                  |   2 +-
 4 files changed, 551 insertions(+), 425 deletions(-)

diff --git a/composer.json b/composer.json
index ea87f4b..0c86e21 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
 {
 	"require-dev": {
-		"mediawiki/mediawiki-codesniffer": "50.0.0",
+		"mediawiki/mediawiki-codesniffer": "51.0.0",
 		"mediawiki/mediawiki-phan-config": "0.20.0",
 		"mediawiki/minus-x": "2.0.1",
 		"php-parallel-lint/php-console-highlighter": "1.0.0",
diff --git a/modules/specialglobalwatchlist/SiteDisplay.js b/modules/specialglobalwatchlist/SiteDisplay.js
index 649748b..ed594a2 100644
--- a/modules/specialglobalwatchlist/SiteDisplay.js
+++ b/modules/specialglobalwatchlist/SiteDisplay.js
@@ -373,6 +373,7 @@ GlobalWatchlistSiteDisplay.prototype.afterMarkAllAsSeen = function () {
 
 /**
  * Update display after marking a page as seen
+ *
  * @param {string} pageTitle the marked page
  */
 GlobalWatchlistSiteBase.prototype.afterMarkPageAsSeen = function ( pageTitle ) {
diff --git a/package-lock.json b/package-lock.json
index 93c12be..170418d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
 				"@wdio/local-runner": "9.23.0",
 				"@wdio/mocha-framework": "9.15.0",
 				"@wdio/spec-reporter": "9.20.0",
-				"eslint-config-wikimedia": "0.32.3",
+				"eslint-config-wikimedia": "0.32.4",
 				"grunt-banana-checker": "0.13.0",
 				"jsdoc": "4.0.5",
 				"jsdoc-wmf-theme": "1.2.0",
@@ -24,6 +24,7 @@
 			"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
 			"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -138,19 +139,32 @@
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
+			}
+		},
+		"node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
+			"version": "8.59.2",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+			"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
+			"dev": true,
+			"engines": {
+				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
 			}
 		},
 		"node_modules/@es-joy/resolve.exports": {
@@ -563,9 +577,9 @@
 			}
 		},
 		"node_modules/@eslint-community/eslint-utils": {
-			"version": "4.7.0",
-			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
-			"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+			"version": "4.9.1",
+			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+			"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
 			"dev": true,
 			"dependencies": {
 				"eslint-visitor-keys": "^3.4.3"
@@ -581,9 +595,9 @@
 			}
 		},
 		"node_modules/@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true,
 			"engines": {
 				"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -594,6 +608,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
 			"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
@@ -617,6 +632,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
 			"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 			}
@@ -627,6 +643,7 @@
 			"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
 			"deprecated": "Use @eslint/config-array instead",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@humanwhocodes/object-schema": "^2.0.3",
 				"debug": "^4.3.1",
@@ -641,6 +658,7 @@
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
 			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=12.22"
 			},
@@ -654,7 +672,8 @@
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
 			"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
 			"deprecated": "Use @eslint/object-schema instead",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/@inquirer/checkbox": {
 			"version": "4.2.0",
@@ -1194,9 +1213,9 @@
 			}
 		},
 		"node_modules/@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"node_modules/@nodable/entities": {
@@ -1477,9 +1496,9 @@
 			"dev": true
 		},
 		"node_modules/@types/estree": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-			"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+			"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
 			"dev": true
 		},
 		"node_modules/@types/istanbul-lib-coverage": {
@@ -1608,20 +1627,19 @@
 			}
 		},
 		"node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1631,7 +1649,7 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"@typescript-eslint/parser": "^8.46.0",
+				"@typescript-eslint/parser": "^8.54.0",
 				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
@@ -1646,16 +1664,16 @@
 			}
 		},
 		"node_modules/@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1670,14 +1688,14 @@
 			}
 		},
 		"node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1691,13 +1709,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1708,9 +1726,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1724,16 +1742,16 @@
 			}
 		},
 		"node_modules/@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1748,9 +1766,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1761,21 +1779,20 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1789,9 +1806,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-			"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+			"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 			"dev": true,
 			"dependencies": {
 				"balanced-match": "^1.0.0"
@@ -1813,15 +1830,15 @@
 			}
 		},
 		"node_modules/@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1836,12 +1853,12 @@
 			}
 		},
 		"node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"engines": {
@@ -1868,7 +1885,8 @@
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
 			"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/@vitest/pretty-format": {
 			"version": "2.1.9",
@@ -3205,9 +3223,9 @@
 			}
 		},
 		"node_modules/acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true,
 			"bin": {
 				"acorn": "bin/acorn"
@@ -3525,6 +3543,12 @@
 				"@mdn/browser-compat-data": "^5.6.19"
 			}
 		},
+		"node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": {
+			"version": "5.7.6",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"dev": true
+		},
 		"node_modules/ast-types": {
 			"version": "0.13.4",
 			"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
@@ -3699,9 +3723,9 @@
 			}
 		},
 		"node_modules/basic-ftp": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
-			"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+			"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
 			"dev": true,
 			"engines": {
 				"node": ">=10.0.0"
@@ -4147,9 +4171,9 @@
 			}
 		},
 		"node_modules/comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true,
 			"engines": {
 				"node": ">= 12.0.0"
@@ -4804,7 +4828,8 @@
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
 			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/deepmerge-ts": {
 			"version": "7.1.5",
@@ -4886,6 +4911,7 @@
 			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
 			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"esutils": "^2.0.2"
 			},
@@ -5198,13 +5224,13 @@
 			}
 		},
 		"node_modules/enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"dependencies": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			},
 			"engines": {
 				"node": ">=10.13.0"
@@ -5335,6 +5361,7 @@
 			"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
 			"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.2.0",
 				"@eslint-community/regexpp": "^4.6.1",
@@ -5401,46 +5428,47 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"dependencies": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			},
 			"engines": {
 				"node": ">=20 <25"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"dependencies": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -5450,7 +5478,7 @@
 				"node": ">=18.x"
 			},
 			"peerDependencies": {
-				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/globals": {
@@ -5516,31 +5544,31 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"dependencies": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"peerDependencies": {
-				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
@@ -5556,29 +5584,29 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": {
-			"version": "4.2.1",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-			"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+			"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 			"dev": true,
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/espree": {
-			"version": "10.4.0",
-			"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-			"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+			"version": "11.2.0",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+			"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 			"dev": true,
 			"dependencies": {
-				"acorn": "^8.15.0",
+				"acorn": "^8.16.0",
 				"acorn-jsx": "^5.3.2",
-				"eslint-visitor-keys": "^4.2.1"
+				"eslint-visitor-keys": "^5.0.1"
 			},
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
@@ -5608,9 +5636,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"dependencies": {
 				"upath": "^2.0.1"
@@ -5637,9 +5665,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -5711,31 +5739,34 @@
 			}
 		},
 		"node_modules/eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"peerDependencies": {
-				"eslint": ">=8.0.0"
+				"eslint": ">=8.0.0 <9.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"dependencies": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			},
 			"engines": {
 				"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
+			},
+			"peerDependencies": {
+				"eslint": ">=8.38.0"
 			}
 		},
 		"node_modules/eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"dependencies": {
 				"safe-regex": "^2.1.1"
@@ -5815,9 +5846,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.20.0"
@@ -5918,6 +5949,7 @@
 			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 			"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"ansi-styles": "^4.1.0",
 				"supports-color": "^7.1.0"
@@ -5934,6 +5966,7 @@
 			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
 			"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=10"
 			},
@@ -5946,6 +5979,7 @@
 			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"is-glob": "^4.0.3"
 			},
@@ -5984,9 +6018,9 @@
 			}
 		},
 		"node_modules/esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"dependencies": {
 				"estraverse": "^5.1.0"
@@ -6270,7 +6304,8 @@
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/fast-uri": {
 			"version": "3.0.5",
@@ -6406,6 +6441,7 @@
 			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
 			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"flat-cache": "^3.0.4"
 			},
@@ -6485,6 +6521,7 @@
 			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
 			"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"flatted": "^3.2.9",
 				"keyv": "^4.5.3",
@@ -6714,6 +6751,7 @@
 			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
@@ -6830,7 +6868,8 @@
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
 			"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/grunt-banana-checker": {
 			"version": "0.13.0",
@@ -7186,24 +7225,14 @@
 			}
 		},
 		"node_modules/ip-address": {
-			"version": "9.0.5",
-			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
-			"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+			"version": "10.2.0",
+			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+			"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
 			"dev": true,
-			"dependencies": {
-				"jsbn": "1.1.0",
-				"sprintf-js": "^1.1.3"
-			},
 			"engines": {
 				"node": ">= 12"
 			}
 		},
-		"node_modules/ip-address/node_modules/jsbn": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
-			"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
-			"dev": true
-		},
 		"node_modules/is-arrayish": {
 			"version": "0.2.1",
 			"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -7296,6 +7325,7 @@
 			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
 			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -7633,9 +7663,9 @@
 			"dev": true
 		},
 		"node_modules/jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true,
 			"engines": {
 				"node": ">=20.0.0"
@@ -7718,7 +7748,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
 			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/json-stringify-safe": {
 			"version": "5.0.1",
@@ -7865,6 +7896,7 @@
 			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
 			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"prelude-ls": "^1.2.1",
 				"type-check": "~0.4.0"
@@ -7973,7 +8005,8 @@
 			"version": "4.6.2",
 			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
 			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"node_modules/lodash.pickby": {
 			"version": "4.6.0",
@@ -8614,6 +8647,7 @@
 			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
 			"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"@aashutoshrathi/word-wrap": "^1.2.3",
 				"deep-is": "^0.1.3",
@@ -8844,6 +8878,7 @@
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -9046,6 +9081,7 @@
 			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
 			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
 			"dev": true,
+			"peer": true,
 			"engines": {
 				"node": ">= 0.8.0"
 			}
@@ -9615,6 +9651,7 @@
 			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
 			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"glob": "^7.1.3"
 			},
@@ -9904,12 +9941,12 @@
 			}
 		},
 		"node_modules/socks": {
-			"version": "2.8.5",
-			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
-			"integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
+			"version": "2.8.8",
+			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz",
+			"integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==",
 			"dev": true,
 			"dependencies": {
-				"ip-address": "^9.0.5",
+				"ip-address": "^10.1.1",
 				"smart-buffer": "^4.2.0"
 			},
 			"engines": {
@@ -10006,12 +10043,6 @@
 				"node": ">= 10.x"
 			}
 		},
-		"node_modules/sprintf-js": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
-			"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
-			"dev": true
-		},
 		"node_modules/sshpk": {
 			"version": "1.18.0",
 			"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -10560,9 +10591,9 @@
 			"dev": true
 		},
 		"node_modules/tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true,
 			"engines": {
 				"node": ">=6"
@@ -10610,7 +10641,53 @@
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
-			"dev": true
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/tinyglobby": {
+			"version": "0.2.16",
+			"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+			"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+			"dev": true,
+			"dependencies": {
+				"fdir": "^6.5.0",
+				"picomatch": "^4.0.4"
+			},
+			"engines": {
+				"node": ">=12.0.0"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/SuperchupuDev"
+			}
+		},
+		"node_modules/tinyglobby/node_modules/fdir": {
+			"version": "6.5.0",
+			"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+			"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+			"dev": true,
+			"engines": {
+				"node": ">=12.0.0"
+			},
+			"peerDependencies": {
+				"picomatch": "^3 || ^4"
+			},
+			"peerDependenciesMeta": {
+				"picomatch": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/tinyglobby/node_modules/picomatch": {
+			"version": "4.0.4",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+			"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+			"dev": true,
+			"engines": {
+				"node": ">=12"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/jonschlinkert"
+			}
 		},
 		"node_modules/tinyrainbow": {
 			"version": "1.2.0",
@@ -10663,9 +10740,9 @@
 			}
 		},
 		"node_modules/ts-api-utils": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
-			"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+			"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.12"
@@ -10756,6 +10833,7 @@
 			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
 			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
 			"dev": true,
+			"peer": true,
 			"dependencies": {
 				"prelude-ls": "^1.2.1"
 			},
@@ -11620,7 +11698,8 @@
 			"version": "1.2.6",
 			"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
 			"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@babel/code-frame": {
 			"version": "7.27.1",
@@ -11672,16 +11751,24 @@
 			"dev": true
 		},
 		"@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"requires": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
+			},
+			"dependencies": {
+				"@typescript-eslint/types": {
+					"version": "8.59.2",
+					"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+					"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
+					"dev": true
+				}
 			}
 		},
 		"@es-joy/resolve.exports": {
@@ -11866,18 +11953,18 @@
 			"optional": true
 		},
 		"@eslint-community/eslint-utils": {
-			"version": "4.7.0",
-			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
-			"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+			"version": "4.9.1",
+			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+			"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
 			"dev": true,
 			"requires": {
 				"eslint-visitor-keys": "^3.4.3"
 			}
 		},
 		"@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true
 		},
 		"@eslint/eslintrc": {
@@ -11885,6 +11972,7 @@
 			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
 			"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
@@ -11901,13 +11989,15 @@
 			"version": "8.57.1",
 			"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
 			"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@humanwhocodes/config-array": {
 			"version": "0.13.0",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
 			"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@humanwhocodes/object-schema": "^2.0.3",
 				"debug": "^4.3.1",
@@ -11918,13 +12008,15 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
 			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@humanwhocodes/object-schema": {
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
 			"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@inquirer/checkbox": {
 			"version": "4.2.0",
@@ -12256,9 +12348,9 @@
 			}
 		},
 		"@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"@nodable/entities": {
@@ -12452,9 +12544,9 @@
 			"dev": true
 		},
 		"@types/estree": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-			"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+			"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
 			"dev": true
 		},
 		"@types/istanbul-lib-coverage": {
@@ -12583,20 +12675,19 @@
 			}
 		},
 		"@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"requires": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"dependencies": {
 				"ignore": {
@@ -12608,87 +12699,86 @@
 			}
 		},
 		"@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			}
 		},
 		"@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			}
 		},
 		"@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			}
 		},
 		"@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
 			"requires": {}
 		},
 		"@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			}
 		},
 		"@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true
 		},
 		"@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
 			},
 			"dependencies": {
 				"brace-expansion": {
-					"version": "2.0.3",
-					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-					"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+					"version": "2.1.0",
+					"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+					"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 					"dev": true,
 					"requires": {
 						"balanced-match": "^1.0.0"
@@ -12706,24 +12796,24 @@
 			}
 		},
 		"@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"requires": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			}
 		},
 		"@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"dependencies": {
@@ -12739,7 +12829,8 @@
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
 			"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"@vitest/pretty-format": {
 			"version": "2.1.9",
@@ -13701,9 +13792,9 @@
 			}
 		},
 		"acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true
 		},
 		"acorn-jsx": {
@@ -13935,6 +14026,14 @@
 			"dev": true,
 			"requires": {
 				"@mdn/browser-compat-data": "^5.6.19"
+			},
+			"dependencies": {
+				"@mdn/browser-compat-data": {
+					"version": "5.7.6",
+					"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+					"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+					"dev": true
+				}
 			}
 		},
 		"ast-types": {
@@ -14053,9 +14152,9 @@
 			"dev": true
 		},
 		"basic-ftp": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
-			"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+			"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
 			"dev": true
 		},
 		"bcrypt-pbkdf": {
@@ -14353,9 +14452,9 @@
 			"dev": true
 		},
 		"comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true
 		},
 		"compress-commons": {
@@ -14827,7 +14926,8 @@
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
 			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"deepmerge-ts": {
 			"version": "7.1.5",
@@ -14888,6 +14988,7 @@
 			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
 			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"esutils": "^2.0.2"
 			}
@@ -15125,13 +15226,13 @@
 			}
 		},
 		"enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"requires": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			}
 		},
 		"entities": {
@@ -15226,6 +15327,7 @@
 			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
 			"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@eslint-community/eslint-utils": "^4.2.0",
 				"@eslint-community/regexpp": "^4.6.1",
@@ -15272,6 +15374,7 @@
 					"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 					"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 					"dev": true,
+					"peer": true,
 					"requires": {
 						"ansi-styles": "^4.1.0",
 						"supports-color": "^7.1.0"
@@ -15281,13 +15384,15 @@
 					"version": "4.0.0",
 					"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
 					"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-					"dev": true
+					"dev": true,
+					"peer": true
 				},
 				"glob-parent": {
 					"version": "6.0.2",
 					"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 					"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
 					"dev": true,
+					"peer": true,
 					"requires": {
 						"is-glob": "^4.0.3"
 					}
@@ -15304,43 +15409,41 @@
 			}
 		},
 		"eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"requires": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			}
 		},
 		"eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"requires": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -15376,23 +15479,23 @@
 			}
 		},
 		"eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"requires": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
@@ -15404,20 +15507,20 @@
 					"dev": true
 				},
 				"eslint-visitor-keys": {
-					"version": "4.2.1",
-					"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-					"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+					"version": "5.0.1",
+					"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+					"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 					"dev": true
 				},
 				"espree": {
-					"version": "10.4.0",
-					"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-					"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+					"version": "11.2.0",
+					"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+					"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 					"dev": true,
 					"requires": {
-						"acorn": "^8.15.0",
+						"acorn": "^8.16.0",
 						"acorn-jsx": "^5.3.2",
-						"eslint-visitor-keys": "^4.2.1"
+						"eslint-visitor-keys": "^5.0.1"
 					}
 				},
 				"spdx-expression-parse": {
@@ -15443,9 +15546,9 @@
 			}
 		},
 		"eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"requires": {
 				"upath": "^2.0.1"
@@ -15463,9 +15566,9 @@
 			}
 		},
 		"eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"requires": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -15508,26 +15611,26 @@
 			}
 		},
 		"eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"requires": {}
 		},
 		"eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"requires": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			}
 		},
 		"eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"requires": {
 				"safe-regex": "^2.1.1"
@@ -15582,9 +15685,9 @@
 			}
 		},
 		"eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true
 		},
 		"eslint-plugin-yml": {
@@ -15660,9 +15763,9 @@
 			"dev": true
 		},
 		"esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"requires": {
 				"estraverse": "^5.1.0"
@@ -15865,7 +15968,8 @@
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"fast-uri": {
 			"version": "3.0.5",
@@ -15950,6 +16054,7 @@
 			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
 			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"flat-cache": "^3.0.4"
 			}
@@ -16013,6 +16118,7 @@
 			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
 			"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"flatted": "^3.2.9",
 				"keyv": "^4.5.3",
@@ -16177,6 +16283,7 @@
 			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
 			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
@@ -16266,7 +16373,8 @@
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
 			"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"grunt-banana-checker": {
 			"version": "0.13.0",
@@ -16509,22 +16617,10 @@
 			}
 		},
 		"ip-address": {
-			"version": "9.0.5",
-			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
-			"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
-			"dev": true,
-			"requires": {
-				"jsbn": "1.1.0",
-				"sprintf-js": "^1.1.3"
-			},
-			"dependencies": {
-				"jsbn": {
-					"version": "1.1.0",
-					"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
-					"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
-					"dev": true
-				}
-			}
+			"version": "10.2.0",
+			"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+			"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+			"dev": true
 		},
 		"is-arrayish": {
 			"version": "0.2.1",
@@ -16590,7 +16686,8 @@
 			"version": "3.0.3",
 			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
 			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"is-plain-obj": {
 			"version": "2.1.0",
@@ -16855,9 +16952,9 @@
 			"dev": true
 		},
 		"jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true
 		},
 		"jsdoc-wmf-theme": {
@@ -16918,7 +17015,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
 			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"json-stringify-safe": {
 			"version": "5.0.1",
@@ -17057,6 +17155,7 @@
 			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
 			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"prelude-ls": "^1.2.1",
 				"type-check": "~0.4.0"
@@ -17142,7 +17241,8 @@
 			"version": "4.6.2",
 			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
 			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"lodash.pickby": {
 			"version": "4.6.0",
@@ -17606,6 +17706,7 @@
 			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
 			"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"@aashutoshrathi/word-wrap": "^1.2.3",
 				"deep-is": "^0.1.3",
@@ -17771,7 +17872,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"path-key": {
 			"version": "3.1.1",
@@ -17916,7 +18018,8 @@
 			"version": "1.2.1",
 			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
 			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-			"dev": true
+			"dev": true,
+			"peer": true
 		},
 		"pretty-format": {
 			"version": "30.2.0",
@@ -18352,6 +18455,7 @@
 			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
 			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"glob": "^7.1.3"
 			}
@@ -18551,12 +18655,12 @@
 			"dev": true
 		},
 		"socks": {
-			"version": "2.8.5",
-			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
-			"integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
+			"version": "2.8.8",
+			"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz",
+			"integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==",
 			"dev": true,
 			"requires": {
-				"ip-address": "^9.0.5",
+				"ip-address": "^10.1.1",
 				"smart-buffer": "^4.2.0"
 			}
 		},
@@ -18627,12 +18731,6 @@
 			"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
 			"dev": true
 		},
-		"sprintf-js": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
-			"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
-			"dev": true
-		},
 		"sshpk": {
 			"version": "1.18.0",
 			"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -18994,9 +19092,9 @@
 			}
 		},
 		"tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true
 		},
 		"tar-fs": {
@@ -19035,7 +19133,33 @@
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
-			"dev": true
+			"dev": true,
+			"peer": true
+		},
+		"tinyglobby": {
+			"version": "0.2.16",
+			"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+			"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+			"dev": true,
+			"requires": {
+				"fdir": "^6.5.0",
+				"picomatch": "^4.0.4"
+			},
+			"dependencies": {
+				"fdir": {
+					"version": "6.5.0",
+					"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+					"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+					"dev": true,
+					"requires": {}
+				},
+				"picomatch": {
+					"version": "4.0.4",
+					"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+					"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+					"dev": true
+				}
+			}
 		},
 		"tinyrainbow": {
 			"version": "1.2.0",
@@ -19073,9 +19197,9 @@
 			}
 		},
 		"ts-api-utils": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
-			"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+			"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
 			"dev": true,
 			"requires": {}
 		},
@@ -19133,6 +19257,7 @@
 			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
 			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
 			"dev": true,
+			"peer": true,
 			"requires": {
 				"prelude-ls": "^1.2.1"
 			}
diff --git a/package.json b/package.json
index 12979eb..48b6472 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
 		"@wdio/local-runner": "9.23.0",
 		"@wdio/mocha-framework": "9.15.0",
 		"@wdio/spec-reporter": "9.20.0",
-		"eslint-config-wikimedia": "0.32.3",
+		"eslint-config-wikimedia": "0.32.4",
 		"grunt-banana-checker": "0.13.0",
 		"jsdoc": "4.0.5",
 		"jsdoc-wmf-theme": "1.2.0",
-- 
2.47.3


--- end ---
Source code is licensed under the AGPL.