This run took 78 seconds.
From db674fdf6aec619bea89d094811840959aa283dd Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Sat, 15 Nov 2025 15:47:12 +0000
Subject: [PATCH] build: Updating npm dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* eslint-config-wikimedia: 0.31.0 → 0.32.1
The following rules are failing and were disabled:
* modules:
* mediawiki/no-unlabeled-buttonwidget
* jsdoc: ^4.0.4 → 4.0.5
Change-Id: I468d68ffeae00d2b55276b3a794c66f6ecc30352
---
modules/.eslintrc.json | 3 +-
package-lock.json | 1003 ++++++++++++++++++----------------------
package.json | 4 +-
3 files changed, 465 insertions(+), 545 deletions(-)
diff --git a/modules/.eslintrc.json b/modules/.eslintrc.json
index 54d1204..c7539ee 100644
--- a/modules/.eslintrc.json
+++ b/modules/.eslintrc.json
@@ -10,6 +10,7 @@
},
"rules": {
"compat/compat": "warn",
- "no-jquery/no-done-fail": "warn"
+ "no-jquery/no-done-fail": "warn",
+ "mediawiki/no-unlabeled-buttonwidget": "warn"
}
}
diff --git a/package-lock.json b/package-lock.json
index d07cb9a..5306fd9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,12 +6,12 @@
"": {
"name": "wikispeech",
"devDependencies": {
- "eslint-config-wikimedia": "0.31.0",
+ "eslint-config-wikimedia": "0.32.1",
"grunt": "1.6.1",
"grunt-banana-checker": "0.13.0",
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
- "jsdoc": "^4.0.4",
+ "jsdoc": "4.0.5",
"jsdoc-wmf-theme": "^1.1.0",
"stylelint-config-wikimedia": "0.18.0"
}
@@ -245,33 +245,19 @@
}
},
"node_modules/@es-joy/jsdoccomment": {
- "version": "0.43.1",
- "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz",
- "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==",
+ "version": "0.75.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.75.0.tgz",
+ "integrity": "sha512-Bj+oF8reFb4b+6LUmG6ETpDsBU/28y/bAAzioyIR4VK/V6UodYBNGbtxRyGxk0aJJQqpZZ6jz82vVZWCX6Mwmg==",
"dev": true,
"dependencies": {
- "@types/eslint": "^8.56.5",
- "@types/estree": "^1.0.5",
- "@typescript-eslint/types": "^7.2.0",
+ "@types/estree": "^1.0.8",
+ "@typescript-eslint/types": "^8.46.0",
"comment-parser": "1.4.1",
- "esquery": "^1.5.0",
- "jsdoc-type-pratt-parser": "~4.0.0"
+ "esquery": "^1.6.0",
+ "jsdoc-type-pratt-parser": "~6.9.1"
},
"engines": {
- "node": ">=16"
- }
- },
- "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
- "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">=20.11.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
@@ -293,9 +279,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
- "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
+ "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"
@@ -331,9 +317,9 @@
"dev": true
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -399,9 +385,9 @@
}
},
"node_modules/@mdn/browser-compat-data": {
- "version": "5.5.9",
- "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.9.tgz",
- "integrity": "sha512-36jBin7kGrMn+RC/8k9IKeKvZyMweA0sDNIthUbzSGTQasfMIp2naJ1e+ISUtzu/7RrpDjRh4BkVTSO6f0XArA==",
+ "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/@nodelib/fs.scandir": {
@@ -458,150 +444,6 @@
"eslint": ">=8.40.0"
}
},
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/project-service": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz",
- "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.38.0",
- "@typescript-eslint/types": "^8.38.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz",
- "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/visitor-keys": "8.38.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz",
- "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/types": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz",
- "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz",
- "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/project-service": "8.38.0",
- "@typescript-eslint/tsconfig-utils": "8.38.0",
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/visitor-keys": "8.38.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"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/utils": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz",
- "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.38.0",
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/typescript-estree": "8.38.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz",
- "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "8.38.0",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
"node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
@@ -631,21 +473,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@stylistic/eslint-plugin/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
@@ -704,26 +531,10 @@
"node": ">=0.10.0"
}
},
- "node_modules/@types/eslint": {
- "version": "8.56.12",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz",
- "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==",
- "dev": true,
- "dependencies": {
- "@types/estree": "*",
- "@types/json-schema": "*"
- }
- },
"node_modules/@types/estree": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true
},
"node_modules/@types/linkify-it": {
@@ -761,16 +572,16 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.1.tgz",
- "integrity": "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
+ "integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/type-utils": "8.35.1",
- "@typescript-eslint/utils": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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",
"natural-compare": "^1.4.0",
@@ -784,9 +595,9 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.35.1",
+ "@typescript-eslint/parser": "^8.46.0",
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
@@ -799,15 +610,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.1.tgz",
- "integrity": "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
+ "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/typescript-estree": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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"
},
"engines": {
@@ -819,17 +630,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.1.tgz",
- "integrity": "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.35.1",
- "@typescript-eslint/types": "^8.35.1",
+ "@typescript-eslint/tsconfig-utils": "^8.46.0",
+ "@typescript-eslint/types": "^8.46.0",
"debug": "^4.3.4"
},
"engines": {
@@ -840,17 +651,17 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.1.tgz",
- "integrity": "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
+ "integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1"
+ "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/visitor-keys": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -861,9 +672,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.1.tgz",
- "integrity": "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==",
+ "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==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -873,17 +684,18 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.1.tgz",
- "integrity": "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.35.1",
- "@typescript-eslint/utils": "8.35.1",
+ "@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"
},
@@ -896,13 +708,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.1.tgz",
- "integrity": "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==",
+ "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==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -913,15 +725,15 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.1.tgz",
- "integrity": "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/project-service": "8.35.1",
- "@typescript-eslint/tsconfig-utils": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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",
@@ -937,7 +749,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
@@ -965,15 +777,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.1.tgz",
- "integrity": "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
+ "integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/typescript-estree": "8.35.1"
+ "@typescript-eslint/scope-manager": "8.46.0",
+ "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/typescript-estree": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -984,16 +796,16 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.1.tgz",
- "integrity": "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "8.35.1",
+ "@typescript-eslint/types": "8.46.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -1163,12 +975,12 @@
}
},
"node_modules/ast-metadata-inferer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz",
- "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.1.tgz",
+ "integrity": "sha512-ht3Dm6Zr7SXv6t1Ra6gFo0+kLDglHGrEbYihTkcycrbHw7WCcuhBzPlJYHEsIpycaUwzsJHje+vUcxXUX4ztTA==",
"dev": true,
"dependencies": {
- "@mdn/browser-compat-data": "^5.2.34"
+ "@mdn/browser-compat-data": "^5.6.19"
}
},
"node_modules/astral-regex": {
@@ -1192,6 +1004,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.28",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz",
+ "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==",
+ "dev": true,
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -1227,9 +1048,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
- "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
+ "version": "4.28.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
+ "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
"dev": true,
"funding": [
{
@@ -1246,10 +1067,11 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001663",
- "electron-to-chromium": "^1.5.28",
- "node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "baseline-browser-mapping": "^2.8.25",
+ "caniuse-lite": "^1.0.30001754",
+ "electron-to-chromium": "^1.5.249",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.1.4"
},
"bin": {
"browserslist": "cli.js"
@@ -1286,9 +1108,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001692",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz",
- "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==",
+ "version": "1.0.30001754",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz",
+ "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==",
"dev": true,
"funding": [
{
@@ -1334,9 +1156,9 @@
}
},
"node_modules/ci-info": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz",
- "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz",
+ "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==",
"dev": true,
"funding": [
{
@@ -1432,12 +1254,12 @@
"dev": true
},
"node_modules/core-js-compat": {
- "version": "3.38.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
- "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
+ "version": "3.46.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz",
+ "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==",
"dev": true,
"dependencies": {
- "browserslist": "^4.23.3"
+ "browserslist": "^4.26.3"
},
"funding": {
"type": "opencollective",
@@ -1483,9 +1305,9 @@
"dev": true
},
"node_modules/cosmiconfig/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -1562,9 +1384,9 @@
}
},
"node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"dependencies": {
"ms": "^2.1.3"
@@ -1593,6 +1415,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/diff-sequences": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
+ "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
+ "dev": true,
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -1736,9 +1567,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.29",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
- "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==",
+ "version": "1.5.253",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.253.tgz",
+ "integrity": "sha512-O0tpQ/35rrgdiGQ0/OFWhy1itmd9A6TY9uQzlqj3hKSu/aYpe7UIn5d7CU2N9myH6biZiWF3VMZVuup8pw5U9w==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -1757,9 +1588,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.17.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
- "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "version": "5.18.3",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
+ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -1876,9 +1707,9 @@
}
},
"node_modules/eslint-compat-utils": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
- "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz",
+ "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==",
"dev": true,
"dependencies": {
"semver": "^7.5.4"
@@ -1891,61 +1722,74 @@
}
},
"node_modules/eslint-config-wikimedia": {
- "version": "0.31.0",
- "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.31.0.tgz",
- "integrity": "sha512-Z/t/zGPdxs/ehxb0EM6THNWAzueT7GtuqzjUvmBpkxcTKzZPJEXWnnpswdj/hgv8Ce8PIeDp0zwQxR4e3c9CIw==",
+ "version": "0.32.1",
+ "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.1.tgz",
+ "integrity": "sha512-gPvhyVFNlpKFOcJfoVTNlzg3A0b6qjhAbjjBIJ9xp5m+om0oqix5gkqIIEav5BaGxdDxYNmrY4ge3DAPP3u/lg==",
"dev": true,
"dependencies": {
"@stylistic/eslint-plugin": "^3.1.0",
- "@typescript-eslint/eslint-plugin": "8.35.1",
- "@typescript-eslint/parser": "8.35.1",
+ "@typescript-eslint/eslint-plugin": "8.46.0",
+ "@typescript-eslint/parser": "8.46.0",
"browserslist-config-wikimedia": "^0.7.0",
"eslint": "^8.57.0",
- "eslint-plugin-compat": "^4.2.0",
- "eslint-plugin-es-x": "^7.6.0",
- "eslint-plugin-jest": "^28.5.0",
- "eslint-plugin-jsdoc": "48.2.5",
+ "eslint-plugin-compat": "^6.0.2",
+ "eslint-plugin-es-x": "^8.7.0",
+ "eslint-plugin-jest": "^29.0.1",
+ "eslint-plugin-jsdoc": "61.0.0",
"eslint-plugin-json-es": "^1.6.0",
- "eslint-plugin-mediawiki": "^0.7.0",
- "eslint-plugin-mocha": "^10.4.3",
- "eslint-plugin-n": "^17.7.0",
+ "eslint-plugin-mediawiki": "^0.8.1",
+ "eslint-plugin-mocha": "^10.5.0",
+ "eslint-plugin-n": "^17.23.1",
"eslint-plugin-no-jquery": "^3.1.1",
- "eslint-plugin-qunit": "^8.1.1",
- "eslint-plugin-security": "^1.7.1",
- "eslint-plugin-unicorn": "^53.0.0",
- "eslint-plugin-vue": "^9.26.0",
- "eslint-plugin-wdio": "^8.24.12",
- "eslint-plugin-yml": "^1.14.0"
+ "eslint-plugin-qunit": "^8.2.5",
+ "eslint-plugin-security": "^3.0.1",
+ "eslint-plugin-unicorn": "^56.0.1",
+ "eslint-plugin-vue": "^9.33.0",
+ "eslint-plugin-wdio": "^9.16.2",
+ "eslint-plugin-yml": "^1.19.0"
},
"engines": {
- "node": ">=18 <25"
+ "node": ">=20 <25"
}
},
"node_modules/eslint-plugin-compat": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz",
- "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==",
+ "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==",
"dev": true,
"dependencies": {
- "@mdn/browser-compat-data": "^5.3.13",
- "ast-metadata-inferer": "^0.8.0",
- "browserslist": "^4.21.10",
- "caniuse-lite": "^1.0.30001524",
+ "@mdn/browser-compat-data": "^5.5.35",
+ "ast-metadata-inferer": "^0.8.1",
+ "browserslist": "^4.24.2",
+ "caniuse-lite": "^1.0.30001687",
"find-up": "^5.0.0",
+ "globals": "^15.7.0",
"lodash.memoize": "^4.1.2",
- "semver": "^7.5.4"
+ "semver": "^7.6.2"
},
"engines": {
- "node": ">=14.x"
+ "node": ">=18.x"
},
"peerDependencies": {
- "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-compat/node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-es-x": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz",
- "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==",
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-8.7.0.tgz",
+ "integrity": "sha512-Du5Sb067sjqzmglaPhsfcEQgE1EYfL8sko+4jOMcAB/XKGoCxntSrOmTYuVzswA1rzM9+MZwH6+GOp0G3/wVCg==",
"dev": true,
"funding": [
"https://github.com/sponsors/ota-meshi",
@@ -1953,8 +1797,8 @@
],
"dependencies": {
"@eslint-community/eslint-utils": "^4.1.2",
- "@eslint-community/regexpp": "^4.11.0",
- "eslint-compat-utils": "^0.5.1"
+ "@eslint-community/regexpp": "^4.12.1",
+ "eslint-compat-utils": "^0.6.3"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
@@ -1964,19 +1808,19 @@
}
},
"node_modules/eslint-plugin-jest": {
- "version": "28.8.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz",
- "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==",
+ "version": "29.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz",
+ "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "@typescript-eslint/utils": "^8.0.0"
},
"engines": {
- "node": "^16.10.0 || ^18.12.0 || >=20.0.0"
+ "node": "^20.12.0 || ^22.0.0 || >=24.0.0"
},
"peerDependencies": {
- "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0",
- "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0",
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
+ "eslint": "^8.57.0 || ^9.0.0",
"jest": "*"
},
"peerDependenciesMeta": {
@@ -1989,28 +1833,60 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
- "version": "48.2.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.5.tgz",
- "integrity": "sha512-ZeTfKV474W1N9niWfawpwsXGu+ZoMXu4417eBROX31d7ZuOk8zyG66SO77DpJ2+A9Wa2scw/jRqBPnnQo7VbcQ==",
+ "version": "61.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.0.0.tgz",
+ "integrity": "sha512-YxvOY3A9H8usnOfOEH82y71yHR7zVNWZJpQbjkC+rWqrADQtM+Gza3+db/j9euNNWCNKnN+/gBrowg16n9lwgg==",
"dev": true,
"dependencies": {
- "@es-joy/jsdoccomment": "~0.43.0",
+ "@es-joy/jsdoccomment": "~0.75.0",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.1",
- "debug": "^4.3.4",
+ "debug": "^4.4.3",
"escape-string-regexp": "^4.0.0",
- "esquery": "^1.5.0",
- "is-builtin-module": "^3.2.1",
- "semver": "^7.6.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.6.0",
+ "html-entities": "^2.6.0",
+ "object-deep-merge": "^1.0.5",
+ "parse-imports-exports": "^0.2.4",
+ "semver": "^7.7.3",
"spdx-expression-parse": "^4.0.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20.11.0"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/eslint-plugin-json-es": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-json-es/-/eslint-plugin-json-es-1.6.0.tgz",
@@ -2025,12 +1901,11 @@
}
},
"node_modules/eslint-plugin-mediawiki": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.7.0.tgz",
- "integrity": "sha512-1Y2nsFDPp96xOZCB5ivZAgqYe9i6w2u64VoCIaAzPyZnd/2h8VQR3CtD+u4Yk/KrpbKq9AAJjrs5LS8VAz6KOA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.1.tgz",
+ "integrity": "sha512-zjTg3hh375lkztKhOYEmPeYiIhKooAu92BkZf2F/fr+5Htvb2i8MNB3gImhM98aTBbkyHTjXoyTHNUrjSjPhmw==",
"dev": true,
"dependencies": {
- "eslint-plugin-vue": "^9.23.0",
"upath": "^2.0.1"
},
"peerDependencies": {
@@ -2055,19 +1930,20 @@
}
},
"node_modules/eslint-plugin-n": {
- "version": "17.10.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.3.tgz",
- "integrity": "sha512-ySZBfKe49nQZWR1yFaA0v/GsH6Fgp8ah6XV0WDz6CN8WO0ek4McMzb7A2xnf4DCYV43frjCygvb9f/wx7UUxRw==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "enhanced-resolve": "^5.17.0",
- "eslint-plugin-es-x": "^7.5.0",
- "get-tsconfig": "^4.7.0",
- "globals": "^15.8.0",
- "ignore": "^5.2.4",
- "minimatch": "^9.0.5",
- "semver": "^7.5.3"
+ "version": "17.23.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
+ "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.5.0",
+ "enhanced-resolve": "^5.17.1",
+ "eslint-plugin-es-x": "^7.8.0",
+ "get-tsconfig": "^4.8.1",
+ "globals": "^15.11.0",
+ "globrex": "^0.1.2",
+ "ignore": "^5.3.2",
+ "semver": "^7.6.3",
+ "ts-declaration-location": "^1.0.6"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2079,40 +1955,52 @@
"eslint": ">=8.23.0"
}
},
- "node_modules/eslint-plugin-n/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "node_modules/eslint-plugin-n/node_modules/eslint-compat-utils": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
+ "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
"dev": true,
"dependencies": {
- "balanced-match": "^1.0.0"
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
}
},
- "node_modules/eslint-plugin-n/node_modules/globals": {
- "version": "15.9.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz",
- "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==",
+ "node_modules/eslint-plugin-n/node_modules/eslint-plugin-es-x": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz",
+ "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==",
"dev": true,
+ "funding": [
+ "https://github.com/sponsors/ota-meshi",
+ "https://opencollective.com/eslint"
+ ],
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.1.2",
+ "@eslint-community/regexpp": "^4.11.0",
+ "eslint-compat-utils": "^0.5.1"
+ },
"engines": {
- "node": ">=18"
+ "node": "^14.18.0 || >=16.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "eslint": ">=8"
}
},
- "node_modules/eslint-plugin-n/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/eslint-plugin-n/node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=18"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-no-jquery": {
@@ -2125,9 +2013,9 @@
}
},
"node_modules/eslint-plugin-qunit": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.1.2.tgz",
- "integrity": "sha512-2gDQdHlQW8GVXD7YYkO8vbm9Ldc60JeGMuQN5QlD48OeZ8znBvvoHWZZMeXjvoDPReGaLEvyuWrDtrI8bDbcqw==",
+ "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==",
"dev": true,
"dependencies": {
"eslint-utils": "^3.0.0",
@@ -2138,27 +2026,33 @@
}
},
"node_modules/eslint-plugin-security": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz",
- "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
+ "integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
"dev": true,
"dependencies": {
"safe-regex": "^2.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-plugin-unicorn": {
- "version": "53.0.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz",
- "integrity": "sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==",
+ "version": "56.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz",
+ "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.5",
+ "@babel/helper-validator-identifier": "^7.24.7",
"@eslint-community/eslint-utils": "^4.4.0",
- "@eslint/eslintrc": "^3.0.2",
"ci-info": "^4.0.0",
"clean-regexp": "^1.0.0",
- "core-js-compat": "^3.37.0",
- "esquery": "^1.5.0",
+ "core-js-compat": "^3.38.1",
+ "esquery": "^1.6.0",
+ "globals": "^15.9.0",
"indent-string": "^4.0.0",
"is-builtin-module": "^3.2.1",
"jsesc": "^3.0.2",
@@ -2166,7 +2060,7 @@
"read-pkg-up": "^7.0.1",
"regexp-tree": "^0.1.27",
"regjsparser": "^0.10.0",
- "semver": "^7.6.1",
+ "semver": "^7.6.3",
"strip-indent": "^3.0.0"
},
"engines": {
@@ -2179,68 +2073,10 @@
"eslint": ">=8.56.0"
}
},
- "node_modules/eslint-plugin-unicorn/node_modules/@eslint/eslintrc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
- "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^10.0.1",
- "globals": "^14.0.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-unicorn/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
- "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-unicorn/node_modules/espree": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
- "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.12.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.0.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
"node_modules/eslint-plugin-unicorn/node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
"engines": {
"node": ">=18"
@@ -2249,22 +2085,10 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint-plugin-unicorn/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
"node_modules/eslint-plugin-vue": {
- "version": "9.28.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.28.0.tgz",
- "integrity": "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g==",
+ "version": "9.33.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz",
+ "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
@@ -2284,23 +2108,24 @@
}
},
"node_modules/eslint-plugin-wdio": {
- "version": "8.37.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-8.37.0.tgz",
- "integrity": "sha512-X217zXxSqj1IPWu3bxN7D/xEUmNk7Jg5lBf2JwYH3mCogaqL2tnHZnwt0EQ5D9oEejfEl2+4zqHSzhXq1X7F2A==",
+ "version": "9.16.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
+ "integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
"dev": true,
"engines": {
- "node": "^16.13 || >=18"
+ "node": ">=18.20.0"
}
},
"node_modules/eslint-plugin-yml": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.14.0.tgz",
- "integrity": "sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.19.0.tgz",
+ "integrity": "sha512-S+4GbcCWksFKAvFJtf0vpdiCkZZvDJCV4Zsi9ahmYkYOYcf+LRqqzvzkb/ST7vTYV6sFwXOvawzYyL/jFT2nQA==",
"dev": true,
"dependencies": {
"debug": "^4.3.2",
- "eslint-compat-utils": "^0.5.0",
- "lodash": "^4.17.21",
+ "diff-sequences": "^27.5.1",
+ "escape-string-regexp": "4.0.0",
+ "eslint-compat-utils": "^0.6.0",
"natural-compare": "^1.4.0",
"yaml-eslint-parser": "^1.2.1"
},
@@ -2388,9 +2213,9 @@
}
},
"node_modules/eslint/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -2430,9 +2255,9 @@
}
},
"node_modules/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
"dependencies": {
"estraverse": "^5.1.0"
@@ -2718,9 +2543,9 @@
}
},
"node_modules/get-tsconfig": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
- "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
+ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
"dev": true,
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
@@ -2849,6 +2674,12 @@
"integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
"dev": true
},
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -3084,6 +2915,22 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
+ "node_modules/html-entities": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
+ "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ]
+ },
"node_modules/html-tags": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
@@ -3365,9 +3212,9 @@
"dev": true
},
"node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"dependencies": {
"argparse": "^1.0.7",
@@ -3387,11 +3234,10 @@
}
},
"node_modules/jsdoc": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
- "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.5.tgz",
+ "integrity": "sha512-P4C6MWP9yIlMiK8nwoZvxN84vb6MsnXcHuy7XzVOvQoCizWX5JFCBsWIIWKXBltpoRZXddUOVQmCTOZt9yDj9g==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@babel/parser": "^7.20.15",
"@jsdoc/salty": "^0.2.1",
@@ -3423,12 +3269,12 @@
"dev": true
},
"node_modules/jsdoc-type-pratt-parser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
- "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
+ "version": "6.9.1",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.9.1.tgz",
+ "integrity": "sha512-HbYNAorY51GnpKvgDf4YINSY+V1segv0qEeijvTSI6OWMCmqah0W6mVwBFeWskJ81uTJJVnDQlwhpJMREvGsXg==",
"dev": true,
"engines": {
- "node": ">=12.0.0"
+ "node": ">=20.0.0"
}
},
"node_modules/jsdoc-wmf-theme": {
@@ -3469,9 +3315,9 @@
}
},
"node_modules/jsesc": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
- "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"bin": {
"jsesc": "bin/jsesc"
@@ -3849,9 +3695,9 @@
"dev": true
},
"node_modules/node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
"dev": true
},
"node_modules/nopt": {
@@ -3914,6 +3760,27 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/object-deep-merge": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz",
+ "integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "4.2.0"
+ }
+ },
+ "node_modules/object-deep-merge/node_modules/type-fest": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz",
+ "integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/object.defaults": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
@@ -4073,6 +3940,15 @@
"node": ">=0.8"
}
},
+ "node_modules/parse-imports-exports": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz",
+ "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==",
+ "dev": true,
+ "dependencies": {
+ "parse-statements": "1.0.11"
+ }
+ },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -4100,6 +3976,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/parse-statements": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz",
+ "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==",
+ "dev": true
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -4699,9 +4581,9 @@
"dev": true
},
"node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -4824,9 +4706,9 @@
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.20",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
- "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
+ "version": "3.0.22",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz",
+ "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==",
"dev": true
},
"node_modules/sprintf-js": {
@@ -5261,12 +5143,16 @@
"dev": true
},
"node_modules/tapable": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
- "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
"dev": true,
"engines": {
"node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/text-table": {
@@ -5299,6 +5185,40 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-declaration-location": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz",
+ "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "ko-fi",
+ "url": "https://ko-fi.com/rebeccastevens"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/ts-declaration-location"
+ }
+ ],
+ "dependencies": {
+ "picomatch": "^4.0.2"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.0.0"
+ }
+ },
+ "node_modules/ts-declaration-location/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -5388,9 +5308,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
"dev": true,
"funding": [
{
@@ -5407,8 +5327,8 @@
}
],
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@@ -5564,25 +5484,24 @@
}
},
"node_modules/yaml": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
- "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"dev": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 14.6"
}
},
"node_modules/yaml-eslint-parser": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz",
- "integrity": "sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz",
+ "integrity": "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==",
"dev": true,
"dependencies": {
"eslint-visitor-keys": "^3.0.0",
- "lodash": "^4.17.21",
"yaml": "^2.0.0"
},
"engines": {
diff --git a/package.json b/package.json
index df7205f..1d32837 100644
--- a/package.json
+++ b/package.json
@@ -7,12 +7,12 @@
"doc": "jsdoc -c jsdoc.json"
},
"devDependencies": {
- "eslint-config-wikimedia": "0.31.0",
+ "eslint-config-wikimedia": "0.32.1",
"grunt": "1.6.1",
"grunt-banana-checker": "0.13.0",
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
- "jsdoc": "^4.0.4",
+ "jsdoc": "4.0.5",
"jsdoc-wmf-theme": "^1.1.0",
"stylelint-config-wikimedia": "0.18.0"
}
--
2.47.3
$ date
--- stdout ---
Sat Nov 15 15:46:08 UTC 2025
--- end ---
$ git clone file:///srv/git/mediawiki-extensions-Wikispeech.git repo --depth=1 -b master
--- stderr ---
Cloning into '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 ---
467b846936acb26635cfe1b07f7594ee461fa67a refs/heads/master
--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
"auditReportVersion": 2,
"vulnerabilities": {
"grunt": {
"name": "grunt",
"severity": "moderate",
"isDirect": true,
"via": [
"js-yaml"
],
"effects": [
"grunt-eslint"
],
"range": ">=0.4.0-a",
"nodes": [
"node_modules/grunt"
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
},
"grunt-eslint": {
"name": "grunt-eslint",
"severity": "moderate",
"isDirect": true,
"via": [
"grunt"
],
"effects": [],
"range": "<=1.0.0 || >=18.1.0",
"nodes": [
"node_modules/grunt-eslint"
],
"fixAvailable": {
"name": "grunt-eslint",
"version": "18.0.0",
"isSemVerMajor": true
}
},
"js-yaml": {
"name": "js-yaml",
"severity": "moderate",
"isDirect": false,
"via": [
{
"source": 1109754,
"name": "js-yaml",
"dependency": "js-yaml",
"title": "js-yaml has prototype pollution in merge (<<)",
"url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m",
"severity": "moderate",
"cwe": [
"CWE-1321"
],
"cvss": {
"score": 5.3,
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
},
"range": "<4.1.1"
}
],
"effects": [
"grunt"
],
"range": "<4.1.1",
"nodes": [
"node_modules/@eslint/eslintrc/node_modules/js-yaml",
"node_modules/cosmiconfig/node_modules/js-yaml",
"node_modules/eslint-plugin-unicorn/node_modules/js-yaml",
"node_modules/eslint/node_modules/js-yaml",
"node_modules/js-yaml"
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
}
},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 3,
"high": 0,
"critical": 0,
"total": 3
},
"dependencies": {
"prod": 1,
"dev": 462,
"optional": 0,
"peer": 1,
"peerOptional": 0,
"total": 462
}
}
}
--- 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: 38 installs, 0 updates, 0 removals
- Locking composer/pcre (3.3.2)
- Locking composer/semver (3.4.4)
- Locking composer/spdx-licenses (1.5.9)
- Locking composer/xdebug-handler (3.0.5)
- Locking dealerdirect/phpcodesniffer-composer-installer (v1.2.0)
- Locking doctrine/deprecations (1.1.5)
- Locking felixfbecker/advanced-json-rpc (v3.2.1)
- Locking mediawiki/mediawiki-codesniffer (v48.0.0)
- Locking mediawiki/mediawiki-phan-config (0.17.0)
- Locking mediawiki/minus-x (1.1.3)
- Locking mediawiki/phan-taint-check-plugin (7.0.0)
- Locking microsoft/tolerant-php-parser (v0.1.2)
- Locking netresearch/jsonmapper (v4.5.0)
- Locking phan/phan (5.5.1)
- 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.1.1)
- Locking phpdocumentor/reflection-common (2.2.0)
- Locking phpdocumentor/reflection-docblock (5.6.3)
- Locking phpdocumentor/type-resolver (1.10.0)
- Locking phpstan/phpdoc-parser (2.3.0)
- Locking psr/container (2.0.2)
- Locking psr/log (3.0.2)
- Locking sabre/event (5.1.7)
- Locking squizlabs/php_codesniffer (3.13.2)
- Locking symfony/console (v7.3.6)
- Locking symfony/deprecation-contracts (v3.6.0)
- Locking symfony/polyfill-ctype (v1.33.0)
- Locking symfony/polyfill-intl-grapheme (v1.33.0)
- Locking symfony/polyfill-intl-normalizer (v1.33.0)
- Locking symfony/polyfill-mbstring (v1.33.0)
- Locking symfony/polyfill-php80 (v1.33.0)
- Locking symfony/service-contracts (v3.6.1)
- Locking symfony/string (v7.3.4)
- Locking tysonandre/var_representation_polyfill (0.1.3)
- Locking webmozart/assert (1.12.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 38 installs, 0 updates, 0 removals
0 [>---------------------------] 0 [->--------------------------]
- Installing squizlabs/php_codesniffer (3.13.2): Extracting archive
- Installing dealerdirect/phpcodesniffer-composer-installer (v1.2.0): Extracting archive
- Installing composer/pcre (3.3.2): Extracting archive
- Installing phpcsstandards/phpcsutils (1.1.1): Extracting archive
- Installing phpcsstandards/phpcsextra (1.4.0): Extracting archive
- Installing symfony/polyfill-mbstring (v1.33.0): Extracting archive
- Installing composer/spdx-licenses (1.5.9): Extracting archive
- Installing composer/semver (3.4.4): Extracting archive
- Installing mediawiki/mediawiki-codesniffer (v48.0.0): Extracting archive
- Installing tysonandre/var_representation_polyfill (0.1.3): Extracting archive
- Installing symfony/polyfill-php80 (v1.33.0): Extracting archive
- Installing symfony/polyfill-intl-normalizer (v1.33.0): Extracting archive
- Installing symfony/polyfill-intl-grapheme (v1.33.0): Extracting archive
- Installing symfony/polyfill-ctype (v1.33.0): Extracting archive
- Installing symfony/string (v7.3.4): Extracting archive
- Installing symfony/deprecation-contracts (v3.6.0): Extracting archive
- Installing psr/container (2.0.2): Extracting archive
- Installing symfony/service-contracts (v3.6.1): Extracting archive
- Installing symfony/console (v7.3.6): Extracting archive
- Installing sabre/event (5.1.7): Extracting archive
- Installing netresearch/jsonmapper (v4.5.0): Extracting archive
- Installing microsoft/tolerant-php-parser (v0.1.2): Extracting archive
- Installing webmozart/assert (1.12.1): Extracting archive
- Installing phpstan/phpdoc-parser (2.3.0): Extracting archive
- Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
- Installing doctrine/deprecations (1.1.5): Extracting archive
- Installing phpdocumentor/type-resolver (1.10.0): Extracting archive
- Installing phpdocumentor/reflection-docblock (5.6.3): Extracting archive
- Installing felixfbecker/advanced-json-rpc (v3.2.1): Extracting archive
- Installing psr/log (3.0.2): Extracting archive
- Installing composer/xdebug-handler (3.0.5): Extracting archive
- Installing phan/phan (5.5.1): Extracting archive
- Installing mediawiki/phan-taint-check-plugin (7.0.0): Extracting archive
- Installing mediawiki/mediawiki-phan-config (0.17.0): Extracting archive
- Installing mediawiki/minus-x (1.1.3): 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/36 [>---------------------------] 0%
28/36 [=====================>------] 77%
36/36 [============================] 100%
1 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
17 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.31.0 -> 0.32.1
Upgrading n:jsdoc from ^4.0.4 -> 4.0.5
$ /usr/bin/npm install
--- stderr ---
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
--- stdout ---
added 458 packages, and audited 459 packages in 7s
102 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
--- end ---
$ package-lock-lint package-lock.json
--- stdout ---
Checking package-lock.json
--- end ---
$ /usr/bin/npm install grunt-eslint@24.3.0 --save-exact
--- stdout ---
up to date, audited 459 packages in 1s
102 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
--- end ---
$ package-lock-lint package-lock.json
--- stdout ---
Checking package-lock.json
--- end ---
$ ./node_modules/.bin/eslint . --fix
--- stdout ---
/src/repo/dev/speechoid-docker-compose/docker-compose.yml
19:1 warning This line has a length of 118. Maximum allowed is 100 max-len
24:1 warning This line has a length of 117. Maximum allowed is 100 max-len
30:1 warning This line has a length of 118. Maximum allowed is 100 max-len
49:1 warning This line has a length of 119. Maximum allowed is 100 max-len
56:1 warning This line has a length of 117. Maximum allowed is 100 max-len
70:1 warning This line has a length of 107. Maximum allowed is 100 max-len
79:1 warning This line has a length of 127. Maximum allowed is 100 max-len
/src/repo/modules/ext.wikispeech.gadget.js
29:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
39:3 warning Prefer .then to .done no-jquery/no-done-fail
39:3 warning Prefer .then to .fail no-jquery/no-done-fail
77:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
83:2 warning Prefer .then to .done no-jquery/no-done-fail
107:1 warning The type 'ext.wikispeech.UserOptionsDialog' is undefined jsdoc/no-undefined-types
115:2 warning Prefer .then to .done no-jquery/no-done-fail
115:2 warning Prefer .then to .fail no-jquery/no-done-fail
159:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.loader.js
10:2 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.main.js
109:1 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.player.js
111:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .fail no-jquery/no-done-fail
169:5 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.selectionPlayer.js
148:3 warning Prefer .then to .done no-jquery/no-done-fail
184:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.storage.js
47:3 warning Prefer .then to .done no-jquery/no-done-fail
94:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
150:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
159:10 warning Prefer .then to .done no-jquery/no-done-fail
183:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
203:19 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.transcriptionPreviewer.js
32:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
37:1 warning This line has a length of 103. Maximum allowed is 100 max-len
57:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
66:19 warning Prefer .then to .done no-jquery/no-done-fail
66:19 warning Prefer .then to .fail no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.ui.js
126:3 warning Prefer .then to .done no-jquery/no-done-fail
240:1 warning This line has a length of 119. Maximum allowed is 100 max-len
356:27 error OO.ui.ButtonWidget has no label. Even icon-only buttons should set a label with invisibleLabel set to true mediawiki/no-unlabeled-buttonwidget
591:21 warning Found non-literal argument in require security/detect-non-literal-require
605:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
630:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
/src/repo/modules/ext.wikispeech.userOptionsDialog.js
84:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/tests/qunit/ext.wikispeech.ui.test.js
339:1 warning The type 'QUnit.assert' is undefined jsdoc/no-undefined-types
✖ 43 problems (1 error, 42 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/Gruntfile.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/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/dev/speechoid-docker-compose/docker-compose.yml","messages":[{"ruleId":"max-len","severity":1,"message":"This line has a length of 118. Maximum allowed is 100.","line":19,"column":1,"nodeType":"Program","messageId":"max","endLine":19,"endColumn":119},{"ruleId":"max-len","severity":1,"message":"This line has a length of 117. Maximum allowed is 100.","line":24,"column":1,"nodeType":"Program","messageId":"max","endLine":24,"endColumn":118},{"ruleId":"max-len","severity":1,"message":"This line has a length of 118. Maximum allowed is 100.","line":30,"column":1,"nodeType":"Program","messageId":"max","endLine":30,"endColumn":119},{"ruleId":"max-len","severity":1,"message":"This line has a length of 119. Maximum allowed is 100.","line":49,"column":1,"nodeType":"Program","messageId":"max","endLine":49,"endColumn":120},{"ruleId":"max-len","severity":1,"message":"This line has a length of 117. Maximum allowed is 100.","line":56,"column":1,"nodeType":"Program","messageId":"max","endLine":56,"endColumn":118},{"ruleId":"max-len","severity":1,"message":"This line has a length of 107. Maximum allowed is 100.","line":70,"column":1,"nodeType":"Program","messageId":"max","endLine":70,"endColumn":108},{"ruleId":"max-len","severity":1,"message":"This line has a length of 127. Maximum allowed is 100.","line":79,"column":1,"nodeType":"Program","messageId":"max","endLine":79,"endColumn":128}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":7,"fixableErrorCount":0,"fixableWarningCount":0,"source":"# If you want to use non-default values in your config it's best to use an\n# override file rather than to edit this one. See\n# https://docs.docker.com/compose/multiple-compose-files/merge/ for details.\n\nversion: \"3.8\"\nname: speechoid\nservices:\n mariadb:\n image: mariadb:10.5.3\n restart: always\n environment:\n - MYSQL_ROOT_PASSWORD=root\n - MYSQL_DATABASE=pronlex\n - MYSQL_USER=pronlex\n - MYSQL_PASSWORD=pronlex\n\n # Disabled for now, see https://phabricator.wikimedia.org/T384313.\n # ahotts:\n # image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-ahotts:2021-07-07-080449-production\n # expose:\n # - \"1200\"\n\n mishkal:\n image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-mishkal:2025-01-21-125334-production\n expose:\n - \"8080\"\n entrypoint: ./interfaces/web/mishkal-webserver.py\n\n mary-tts:\n image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-mary-tts:2024-02-28-153902-production\n environment:\n - MARY_TTS_MISHKAL_URL=http://mishkal:8080/\n - HAPROXY_MARY_TTS_BACKEND_MAXIMUM_CONCURRENT_CONNECTIONS=4\n # - HAPROXY_QUEUE_SIZE=100\n # - HAPROXY_TIMEOUT_CONNECT=60s\n # - HAPROXY_TIMEOUT_CLIENT=60s\n # - HAPROXY_TIMEOUT_SERVER=60s\n # - HAPROXY_MARY_TTS_FRONTEND_PORT=8080\n # - HAPROXY_MARY_TTS_BACKEND_PORT=59125\n # - HAPROXY_STATS_FRONTEND_REFRESH_RATE=4s\n expose:\n - \"8080\"\n volumes:\n - ./compose-files/wait-for-it.sh:/srv/compose/wait-for-it.sh\n - ./compose-files/mary-entrypoint.sh:/srv/compose/entrypoint.sh\n entrypoint: /srv/compose/entrypoint.sh\n\n symbolset:\n image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-symbolset:2024-02-28-153900-production\n expose:\n - \"8771\"\n ports:\n - 8771:8771\n\n pronlex:\n image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-pronlex:2024-02-28-153924-production\n expose:\n - \"8787\"\n # environment:\n # If this is set, Pronlex will connect to this MariaDB database.\n # If this NOT is set, Pronlex will use built in SQLite database.\n # - PRONLEX_MARIADB_URI=speechoid:password@tcp(wikispeech-tts-pronlex:3306)\n volumes:\n - ./compose-files/wait-for-it.sh:/srv/compose/wait-for-it.sh\n - ./compose-files/pronlex-entrypoint.sh:/srv/compose/entrypoint.sh\n entrypoint: /srv/compose/entrypoint.sh\n\n # This is a temporary workaround to handle low volume samples from MaryTTS.\n sox-proxy:\n image: docker-registry.wikimedia.org/repos/mediawiki/services/speechoid/sox-proxy:2024-03-18-production\n expose:\n - \"5000\"\n ports:\n - 5000:5000\n environment:\n - SPEECHOID_URL=http://wikispeech-server:10001/\n\n wikispeech-server:\n image: docker-registry.wikimedia.org/wikimedia/mediawiki-services-wikispeech-wikispeech-server:2024-02-28-153857-production\n expose:\n - \"10001\"\n ports:\n - 10000:10000\n - 10001:10001\n - 10002:10002\n volumes:\n - ./compose-files/wikispeech-server-entrypoint.sh:/srv/compose/entrypoint.sh\n - ./compose-files/wikispeech-server.conf:/srv/wikispeech-server/wikispeech_server/default.conf\n - ./compose-files/wait-for-it.sh:/srv/compose/wait-for-it.sh\n entrypoint: /srv/compose/entrypoint.sh\n environment:\n - HAPROXY_QUEUE_SIZE=100\n - HAPROXY_WIKISPEECH_SERVER_BACKEND_MAXIMUM_CONCURRENT_CONNECTIONS=1\n - HAPROXY_TIMEOUT_CONNECT=60s\n - HAPROXY_TIMEOUT_CLIENT=60s\n - HAPROXY_TIMEOUT_SERVER=60s\n - HAPROXY_WIKISPEECH_SERVER_BACKEND_PORT=10000\n - HAPROXY_WIKISPEECH_SERVER_FRONTEND_PORT=10001\n - HAPROXY_STATS_FRONTEND_PORT=10002\n - HAPROXY_STATS_FRONTEND_REFRESH_RATE=4s\n","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":"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/api/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/api/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/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":"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/audio/error.en.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/audio/error.sv.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.gadget.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Deferred' is undefined.","line":29,"column":1,"nodeType":"Block","endLine":29,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":39,"column":3,"nodeType":"CallExpression","endLine":58,"endColumn":7},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .fail","line":39,"column":3,"nodeType":"CallExpression","endLine":65,"endColumn":7},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Deferred' is undefined.","line":77,"column":1,"nodeType":"Block","endLine":77,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":83,"column":2,"nodeType":"CallExpression","endLine":97,"endColumn":5},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'ext.wikispeech.UserOptionsDialog' is undefined.","line":107,"column":1,"nodeType":"Block","endLine":107,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":115,"column":2,"nodeType":"CallExpression","endLine":123,"endColumn":6},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .fail","line":115,"column":2,"nodeType":"CallExpression","endLine":129,"endColumn":6},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":159,"column":3,"nodeType":"CallExpression","endLine":170,"endColumn":7}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":9,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Loads wikispeech modules from producer\n *\n * @module ext.wikispeech.gadget\n */\n\nlet moduleUrl, api, optionsPage, main;\n\n/**\n * Add config variables from the producer's config.\n *\n * The config values are specified in extension.json under\n * ResourceModules -> ext.wikispeech.gadget.\n */\nfunction addConfig() {\n\tconst config = require( './config.json' );\n\tObject.keys( config ).forEach( ( key ) => {\n\t\tconst value = config[ key ];\n\t\tmw.config.set( 'wg' + key, value );\n\t} );\n}\n\n/**\n * Read user options from the consumer wiki.\n *\n * User options are stored in a subpage to the user page called\n * \"Wikispeech_preferences\".\n *\n * @return {jQuery.Deferred} Resolves with an object containing the\n * user options. Resolves with the empty object if the options\n * could not be read.\n */\nfunction getUserOptionsOnConsumer() {\n\tconst done = $.Deferred();\n\tif ( mw.user.isAnon() ) {\n\t\t// No user options set if not logged in.\n\t\tdone.resolve( {} );\n\t} else {\n\t\tapi.get( {\n\t\t\taction: 'parse',\n\t\t\tpage: optionsPage,\n\t\t\tprop: 'wikitext',\n\t\t\tformatversion: 2\n\t\t} )\n\t\t\t.done( ( response ) => {\n\t\t\t\tconst content = response.parse.wikitext;\n\t\t\t\tlet options;\n\t\t\t\ttry {\n\t\t\t\t\toptions = JSON.parse( content );\n\t\t\t\t} catch ( error ) {\n\t\t\t\t\tmw.log.warn(\n\t\t\t\t\t\t'[Wikispeech] Failed to parse user preferences, ' +\n\t\t\t\t\t\t\t'using defaults: ' + error\n\t\t\t\t\t);\n\t\t\t\t\toptions = {};\n\t\t\t\t}\n\t\t\t\tdone.resolve( options );\n\t\t\t} )\n\t\t\t.fail( ( error ) => {\n\t\t\t\tmw.log.warn(\n\t\t\t\t\t'[Wikispeech] Failed to load user preferences page, ' +\n\t\t\t\t\t\t'using defaults: ' + error\n\t\t\t\t);\n\t\t\t\tdone.resolve( {} );\n\t\t\t} );\n\t}\n\treturn done;\n}\n\n/**\n * Add user options for Wikispeech.\n *\n * Reads user options from the consumer wiki and add those. Any\n * option that is not present on the consumer wiki will be set to the\n * default from the producer wiki.\n *\n * @return {jQuery.Deferred} Resolves when user options have been\n * read.\n */\nfunction addUserOptions() {\n\tconst done = $.Deferred();\n\tconst defaultOptions = require( './default-user-options.json' );\n\tgetUserOptionsOnConsumer().done( ( options ) => {\n\t\tObject.keys( defaultOptions ).forEach( ( key ) => {\n\t\t\tlet value;\n\n\t\t\t// Take the option value from user page if it is set,\n\t\t\t// otherwise use default.\n\t\t\tif ( Object.keys( options ).includes( key ) ) {\n\t\t\t\tvalue = options[ key ];\n\t\t\t} else {\n\t\t\t\tvalue = defaultOptions[ key ];\n\t\t\t}\n\t\t\tmw.user.options.set( key, value );\n\t\t\tdone.resolve();\n\t\t} );\n\t} );\n\treturn done;\n}\n\n/**\n * Write user options to a subpage to the user page.\n *\n * User options are read from the preferences popup dialog and\n * stored as JSON.\n *\n * @param {ext.wikispeech.UserOptionsDialog} dialog\n */\nfunction writeUserOptionsToWikiPage( dialog ) {\n\tconst options = require( './default-user-options.json' );\n\tconst voice = dialog.getVoice();\n\toptions[ voice.variable ] = voice.voice;\n\toptions.wikispeechSpeechRate = dialog.getSpeechRate();\n\tconst optionsJson = JSON.stringify( options, null, 4 );\n\tapi.postWithEditToken( {\n\t\taction: 'edit',\n\t\ttitle: optionsPage,\n\t\ttext: optionsJson,\n\t\tformatversion: 2\n\t} )\n\t\t.done( () => {\n\t\t\tmw.log( '[Wikispeech] Wrote user preferences to \"' + optionsPage + '\".' );\n\t\t} )\n\t\t.fail( ( error ) => {\n\t\t\tmw.log.warn(\n\t\t\t\t'[Wikispeech] Failed to write user preferences to \"' +\n\t\t\t\t\toptionsPage + '\": ' + error\n\t\t\t);\n\t\t} );\n}\n\n/**\n * Add consumer specific elements to the UI.\n *\n * Adds a popup dialog for changing user options and a button on\n * the player toolbar to open it.\n */\nfunction extendUi() {\n\tconst UserOptionsDialog = require( './ext.wikispeech.userOptionsDialog.js' );\n\tconst dialog = new UserOptionsDialog();\n\tmain.ui.addWindow( dialog );\n\tconst gadgetGroup = main.ui.addToolbarGroup();\n\tmain.ui.addButton(\n\t\tgadgetGroup,\n\t\tasync () => {\n\t\t\tconst data = await main.ui.openWindow( dialog );\n\t\t\tif ( data && data.action === 'save' ) {\n\t\t\t\twriteUserOptionsToWikiPage( dialog );\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttitle: mw.msg( 'wikispeech-settings' ),\n\t\t\ticon: 'settings'\n\t\t}\n\t);\n\tif ( mw.config.get( 'wgWikispeechAllowConsumerEdits' ) ) {\n\t\tconst producerUrl = mw.config.get( 'wgWikispeechProducerUrl' );\n\t\tconst producerApi = new mw.ForeignApi( `${ producerUrl }/api.php` );\n\t\tproducerApi.get( {\n\t\t\taction: 'query',\n\t\t\tformat: 'json',\n\t\t\tmeta: 'siteinfo',\n\t\t\tsiprop: 'general'\n\t\t} )\n\t\t\t.done( ( response ) => {\n\t\t\t\tconst producerInfo = response.query.general,\n\t\t\t\t\tscriptPath = producerInfo.server + producerInfo.script;\n\t\t\t\tconst consumerUrl = window.location.origin + mw.config.get( 'wgScriptPath' );\n\t\t\t\tmain.ui.addEditButton( scriptPath, consumerUrl );\n\t\t\t} );\n\t}\n}\n\nmw.loader.using( [\n\t'mediawiki.api',\n\t'mediawiki.user',\n\t'mediawiki.ForeignApi',\n\t'oojs-ui',\n\t'oojs-ui-core',\n\t'oojs-ui-toolbars',\n\t'oojs-ui-windows',\n\t'oojs-ui.styles.icons-media',\n\t'oojs-ui.styles.icons-movement',\n\t'oojs-ui.styles.icons-interactions',\n\t'oojs-ui.styles.icons-editing-core'\n] ).then( async () => {\n\tconst producerUrl = mw.config.get( 'wgWikispeechProducerUrl' );\n\tif ( !producerUrl ) {\n\t\tmw.log.error( '[Wikispeech] No producer URL given. Set it with the config variable \"wgWikispeechProducerUrl\".' );\n\t\treturn;\n\t}\n\n\taddConfig();\n\tconst namespace = mw.config.get( 'wgNamespaceIds' ).user;\n\tconst userPage = mw.Title.makeTitle( namespace, mw.user.getName() )\n\t\t.getPrefixedText();\n\toptionsPage = userPage + '/Wikispeech_preferences';\n\tapi = new mw.Api();\n\tawait addUserOptions();\n\tconst parametersString = $.param( {\n\t\tlang: mw.config.get( 'wgUserLanguage' ),\n\t\tskin: mw.config.get( 'skin' ),\n\t\traw: 1,\n\t\tsafemode: 1,\n\t\tmodules: 'ext.wikispeech'\n\t} );\n\tmoduleUrl = `${ producerUrl }/load.php?${ parametersString }`;\n\tmw.log( `[Wikispeech] Loading wikispeech module from ${ moduleUrl }` );\n\ttry {\n\t\tawait mw.loader.getScript( moduleUrl );\n\t\tawait mw.loader.using( 'ext.wikispeech' );\n\t\tmain = require( 'ext.wikispeech' );\n\t\tawait main.ui.ready;\n\t\textendUi( main );\n\t} catch ( error ) {\n\t\tmw.log.error( '[Wikispeech] Failed to load Wikispeech module: ', error );\n\t}\n} );\n","usedDeprecatedRules":[{"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/ext.wikispeech.highlighter.js","messages":[],"suppressedMessages":[{"ruleId":"mediawiki/class-doc","severity":2,"message":"All possible CSS classes should be documented. See https://w.wiki/PS2 for details.","line":38,"column":16,"nodeType":"CallExpression","endLine":39,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.loader.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":10,"column":2,"nodeType":"CallExpression","endLine":12,"endColumn":5}],"suppressedMessages":[{"ruleId":"no-jquery/no-global-selector","severity":2,"message":"Avoid queries which search the entire DOM. Keep DOM nodes in memory where possible.","line":8,"column":1,"nodeType":"CallExpression","endLine":8,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * A small helper script to trigger the loading of the Wikispeech modules.\n *\n * @class ext.wikispeech.loader\n */\n\n// eslint-disable-next-line no-jquery/no-global-selector\n$( '.ext-wikispeech-listen a' ).one( 'click', () => {\n\tmw.log( '[Wikispeech] Loading Wikispeech...' );\n\tmw.loader.using( 'ext.wikispeech' ).done( () => {\n\t\tmw.log( '[Wikispeech] Loaded Wikispeech.' );\n\t} );\n} );\n","usedDeprecatedRules":[{"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/ext.wikispeech.main.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":109,"column":1,"nodeType":"CallExpression","endLine":115,"endColumn":2}],"suppressedMessages":[{"ruleId":"no-jquery/no-global-selector","severity":2,"message":"Avoid queries which search the entire DOM. Keep DOM nodes in memory where possible.","line":59,"column":29,"nodeType":"CallExpression","endLine":59,"endColumn":60,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Main class for the Wikispeech extension.\n *\n * Handles setup of various components and initialization.\n *\n * @class ext.wikispeech.Main\n * @constructor\n */\nconst Ui = require( './ext.wikispeech.ui.js' );\nconst Storage = require( './ext.wikispeech.storage.js' );\nconst Player = require( './ext.wikispeech.player.js' );\nconst SelectionPlayer = require( './ext.wikispeech.selectionPlayer.js' );\nconst Highlighter = require( './ext.wikispeech.highlighter.js' );\n\nclass Main {\n\tconstructor() {\n\t\tthis.storage = new Storage();\n\t\tthis.selectionPlayer = new SelectionPlayer();\n\t\tthis.ui = new Ui();\n\t\tthis.player = new Player();\n\t\tthis.highlighter = new Highlighter();\n\n\t\tthis.highlighter.storage = this.storage;\n\t\tthis.storage.player = this.player;\n\t\tthis.storage.highlighter = this.highlighter;\n\t\tthis.player.ui = this.ui;\n\t\tthis.player.storage = this.storage;\n\t\tthis.player.highlighter = this.highlighter;\n\t\tthis.player.selectionPlayer = this.selectionPlayer;\n\t\tthis.selectionPlayer.storage = this.storage;\n\t\tthis.selectionPlayer.player = this.player;\n\t\tthis.selectionPlayer.ui = this.ui;\n\t\tthis.ui.player = this.player;\n\t\tthis.ui.storage = this.storage;\n\t\tthis.ui.selectionPlayer = this.selectionPlayer;\n\t}\n\n\tinit() {\n\t\tif ( !this.enabledForNamespace() ) {\n\t\t\t// TODO: This is only required for tests to run\n\t\t\t// properly since namespace is checked at an earlier\n\t\t\t// stage for production code. See T267529.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( mw.config.get( 'wgMFMode' ) ) {\n\t\t\t// Do not load Wikispeech if MobileFrontend is\n\t\t\t// enabled since it does not support its mobile\n\t\t\t// view. See T169059.\n\t\t\treturn;\n\t\t}\n\n\t\tthis.storage.loadUtterances( window );\n\t\t// Prepare the first utterance for playback.\n\n\t\tthis.ui.init();\n\t\t// Prepare action link.\n\t\t// eslint-disable-next-line no-jquery/no-global-selector\n\t\tconst $toggleVisibility = $( '.ext-wikispeech-listen a' );\n\t\t// Set label to hide message since the player is\n\t\t// visible when loaded.\n\t\t$toggleVisibility.text(\n\t\t\tmw.msg( 'wikispeech-dont-listen' )\n\t\t);\n\t\t$toggleVisibility.on( 'click', this.toggleVisibility );\n\t}\n\n\t/**\n\t * Toggle the visibility of the control panel.\n\t *\n\t * @method\n\t * @memberof ext.wikispeech.Main\n\t * @param {Event} event\n\t */\n\n\ttoggleVisibility( event ) {\n\t\tthis.ui.toggleVisibility();\n\n\t\tlet toggleVisibilityMessage;\n\t\tif ( this.ui.isShown() ) {\n\t\t\ttoggleVisibilityMessage = 'wikispeech-dont-listen';\n\t\t} else {\n\t\t\ttoggleVisibilityMessage = 'wikispeech-listen';\n\t\t}\n\t\tconst $toggleVisibility = event.data;\n\t\t// Messages that can be used here:\n\t\t// * wikispeech-listen\n\t\t// * wikispeech-dont-listen\n\t\t$toggleVisibility.text( mw.msg( toggleVisibilityMessage ) );\n\t}\n\n\t/**\n\t * Check if Wikispeech is enabled for the current namespace.\n\t *\n\t * @method\n\t * @memberof ext.wikispeech.Main\n\t * @return {boolean} true is the namespace of current page\n\t * should activate Wikispeech, else false.\n\t */\n\n\tenabledForNamespace() {\n\t\tconst validNamespaces = mw.config.get( 'wgWikispeechNamespaces' );\n\t\tconst namespace = mw.config.get( 'wgNamespaceNumber' );\n\t\treturn validNamespaces.includes( namespace );\n\t}\n\n}\n\nmw.loader.using( [ 'mediawiki.api', 'ext.wikispeech' ] ).done(\n\t() => {\n\t\tconst main = new Main();\n\t\tmain.init();\n\t\tmodule.exports = main;\n\t}\n);\n","usedDeprecatedRules":[{"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/ext.wikispeech.player.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":111,"column":3,"nodeType":"CallExpression","endLine":116,"endColumn":6},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":156,"column":3,"nodeType":"CallExpression","endLine":161,"endColumn":7},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .fail","line":156,"column":3,"nodeType":"CallExpression","endLine":179,"endColumn":7},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":169,"column":5,"nodeType":"CallExpression","endLine":178,"endColumn":9}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Play, pause stop and navigate in the recitation.\n *\n * @class ext.wikispeech.Player\n * @constructor\n */\n\nconst util = require( './ext.wikispeech.util.js' );\n\nclass Player {\n\tconstructor() {\n\t\tthis.currentUtterance = null;\n\t\tthis.paused = false;\n\t\tthis.playingSelection = false;\n\n\t\tthis.ui = null;\n\t\tthis.storage = null;\n\t\tthis.highlighter = null;\n\t\tthis.selectionPlayer = null;\n\t}\n\n\t/**\n\t * Play or pause, depending on whether an utterance is playing.\n\t */\n\n\tplayOrPause() {\n\t\tif ( this.isPlaying() && !this.paused ) {\n\t\t\tthis.pause();\n\t\t} else {\n\t\t\tthis.play();\n\t\t}\n\t}\n\n\t/**\n\t * Play or stop, depending on whether an utterance is playing.\n\t */\n\n\tplayOrStop() {\n\t\tif ( this.isPlaying() ) {\n\t\t\tthis.stop();\n\t\t} else {\n\t\t\tthis.play();\n\t\t}\n\t}\n\n\t/**\n\t * Test if there currently is an utterance playing\n\t *\n\t * @return {boolean} true if there is an utterance playing,\n\t * else false.\n\t */\n\n\tisPlaying() {\n\t\treturn this.currentUtterance !== null;\n\t}\n\n\t/**\n\t * Stop playing the utterance currently playing.\n\t */\n\n\tstop() {\n\n\t\tthis.ui.setAllPlayerIconsToPlay();\n\n\t\tthis.paused = false;\n\n\t\tif ( this.isPlaying() ) {\n\t\t\tthis.stopUtterance( this.currentUtterance );\n\t\t\tthis.currentUtterance = null;\n\t\t}\n\n\t\tthis.ui.hideBufferingIcon();\n\n\t\tthis.playingSelection = false;\n\t}\n\n\t/**\n\t * Pause playing the utterance currently playing, and resume from paused utterance.\n\t */\n\tpause() {\n\t\tif ( this.isPlaying() && !this.paused ) {\n\t\t\tthis.paused = true;\n\t\t\tthis.pauseUtterance( this.currentUtterance );\n\t\t}\n\t\tif ( this.playingSelection ) {\n\t\t\tthis.stop();\n\t\t}\n\t\tthis.ui.setAllPlayerIconsToPlay();\n\t\tthis.ui.hideBufferingIcon();\n\t}\n\n\t/**\n\t * Start playing the first utterance or selected text, if any.\n\t */\n\tplay() {\n\t\tif ( this.playingSelection ) {\n\t\t\tthis.stop();\n\t\t} else {\n\t\t\tthis.ui.setPlayPauseIconToPause();\n\t\t}\n\t\tif ( this.paused ) {\n\t\t\tthis.currentUtterance.audio.play();\n\t\t\tthis.paused = false;\n\n\t\t\tconst currentToken = this.getCurrentToken();\n\t\t\tif ( currentToken ) {\n\t\t\t\tthis.highlighter.startTokenHighlighting( currentToken );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tthis.storage.utterancesLoaded.done( () => {\n\t\t\tif ( !this.selectionPlayer.playSelectionIfValid() ) {\n\t\t\t\tthis.playUtterance( this.storage.utterances[ 0 ] );\n\t\t\t}\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Play the audio for an utterance.\n\t *\n\t * This also stops any currently playing utterance.\n\t *\n\t * @param {Object} utterance The utterance to play the audio\n\t * for.\n\t * @param {boolean} [fromStart=true] Whether the utterance\n\t * should play from start or not.\n\t */\n\tplayUtterance( utterance, fromStart ) {\n\t\tfromStart = fromStart === undefined ? true : fromStart;\n\t\tif ( fromStart && this.isPlaying() ) {\n\t\t\tthis.stopUtterance( this.currentUtterance );\n\t\t}\n\t\tthis.currentUtterance = utterance;\n\t\tif ( !this.playingSelection ) {\n\t\t\tthis.highlighter.highlightUtterance( utterance );\n\t\t}\n\t\tthis.ui.showBufferingIconIfAudioIsLoading(\n\t\t\tutterance.audio\n\t\t);\n\t\tthis.prepareAndPlayUtterance( utterance );\n\t}\n\n\t/**\n\t * Ensure an utterance is ready for playback and play it.\n\t *\n\t * Plays utterance when it is ready. If the utterance fail to\n\t * prepare and it is currently playing, a popup dialog will\n\t * appear, letting the user retry or stop playback.\n\t *\n\t * @param {Object} utterance\n\t */\n\n\tprepareAndPlayUtterance( utterance ) {\n\t\tthis.storage.prepareUtterance( utterance )\n\t\t\t.done( () => {\n\t\t\t\tif ( utterance === this.currentUtterance && !this.paused ) {\n\t\t\t\t\tutterance.audio.play();\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.fail( () => {\n\t\t\t\tif ( utterance !== this.currentUtterance ) {\n\t\t\t\t\t// Only show dialog if the current utterance\n\t\t\t\t\t// fails to load, to avoid multiple and less\n\t\t\t\t\t// relevant dialogs.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.ui.showLoadAudioError()\n\t\t\t\t\t.done( ( data ) => {\n\t\t\t\t\t\tif ( !data || data.action === 'stop' ) {\n\t\t\t\t\t\t\t// Stop both when \"Stop\" is clicked\n\t\t\t\t\t\t\t// and when escape is pressed.\n\t\t\t\t\t\t\tthis.stop();\n\t\t\t\t\t\t} else if ( data.action === 'retry' ) {\n\t\t\t\t\t\t\tthis.prepareAndPlayUtterance( utterance );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t} );\n\t}\n\n\t/**\n\t * Stop and rewind the audio for an utterance.\n\t *\n\t * @param {Object} utterance The utterance to stop the audio\n\t * for.\n\t */\n\n\tstopUtterance( utterance ) {\n\t\tutterance.audio.pause();\n\t\t// Rewind audio for next time it plays.\n\t\tutterance.audio.currentTime = 0;\n\t\tthis.ui.removeCanPlayListener( $( utterance.audio ) );\n\t\tthis.highlighter.clearHighlighting();\n\t}\n\n\t/**\n\t * Pause the audio for an utterance.\n\t *\n\t * @param {Object} utterance The utterance to pause the audio\n\t * for.\n\t */\n\n\tpauseUtterance( utterance ) {\n\t\tutterance.audio.pause();\n\t\tthis.highlighter.clearHighlightTokenTimer();\n\t}\n\n\t/**\n\t * Skip to the next utterance.\n\t *\n\t * Stop the current utterance and start playing the next one.\n\t */\n\n\tskipAheadUtterance() {\n\t\tconst nextUtterance =\n\t\t\tthis.storage.getNextUtterance( this.currentUtterance );\n\t\tif ( nextUtterance ) {\n\t\t\tthis.playUtterance( nextUtterance );\n\t\t} else {\n\t\t\tthis.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Skip to the previous utterance.\n\t *\n\t * Stop the current utterance and start playing the previous\n\t * one. If the first utterance is playing, restart it.\n\t */\n\n\tskipBackUtterance() {\n\t\tconst rewindThreshold = mw.config.get(\n\t\t\t'wgWikispeechSkipBackRewindsThreshold'\n\t\t);\n\t\tconst time = this.currentUtterance.audio.currentTime;\n\t\tif (\n\t\t\ttime > rewindThreshold ||\n\t\t\t\tthis.currentUtterance === this.storage.utterances[ 0 ]\n\t\t) {\n\t\t\t// Restart the current utterance if it's the first one\n\t\t\t// or if it has played for longer than the skip back\n\t\t\t// threshold. The threshold is based on position in\n\t\t\t// the audio, rather than time played. This means it\n\t\t\t// scales with speech rate.\n\t\t\tthis.currentUtterance.audio.currentTime = 0;\n\t\t} else {\n\t\t\tconst previousUtterance =\n\t\t\t\tthis.storage.getPreviousUtterance(\n\t\t\t\t\tthis.currentUtterance\n\t\t\t\t);\n\t\t\tthis.playUtterance( previousUtterance );\n\t\t}\n\t}\n\n\t/**\n\t * Get the token being played.\n\t *\n\t * @return {Object} The token being played. Can return null.\n\t */\n\n\tgetCurrentToken() {\n\t\tif ( !this.currentUtterance || !this.currentUtterance.tokens ) {\n\t\t\treturn null;\n\t\t}\n\t\tlet currentToken = null;\n\t\tconst tokens = this.currentUtterance.tokens;\n\t\tconst currentTime = this.currentUtterance.audio.currentTime * 1000;\n\t\tconst tokensWithDuration = tokens.filter( ( token ) => {\n\t\t\tconst duration = token.endTime - token.startTime;\n\t\t\treturn duration > 0;\n\t\t} );\n\t\tconst lastTokenWithDuration =\n\t\t\tutil.getLast( tokensWithDuration );\n\t\tif ( currentTime === lastTokenWithDuration.endTime ) {\n\t\t\t// If the current time is equal to the end time of the\n\t\t\t// last token, the last token is the current.\n\t\t\tcurrentToken = lastTokenWithDuration;\n\t\t} else {\n\t\t\tcurrentToken = tokensWithDuration.find( ( token ) => token.startTime <= currentTime &&\n\t\t\t\t\ttoken.endTime > currentTime );\n\t\t}\n\t\treturn currentToken;\n\t}\n\n\t/**\n\t * Skip to the next token.\n\t *\n\t * If there are no more tokens in the current utterance, skip\n\t * to the next utterance.\n\t */\n\n\tskipAheadToken() {\n\t\tif ( !this.isPlaying() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentToken = this.getCurrentToken();\n\t\tconst nextToken = this.storage.getNextToken( currentToken );\n\n\t\tif ( !nextToken ) {\n\t\t\tthis.skipAheadUtterance();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.currentUtterance.audio.currentTime = nextToken.startTime / 1000;\n\n\t\tthis.highlighter.clearHighlighting();\n\t\tthis.highlighter.highlightUtterance( this.currentUtterance );\n\n\t\tif ( this.paused ) {\n\t\t\tthis.highlighter.highlightToken( nextToken );\n\n\t\t} else {\n\t\t\tthis.highlighter.startTokenHighlighting( nextToken );\n\t\t}\n\t}\n\n\t/**\n\t * Skip to the previous token.\n\t *\n\t * If there are no preceding tokens, skip to the last token of\n\t * the previous utterance.\n\t */\n\n\tskipBackToken() {\n\t\tif ( this.isPlaying() ) {\n\t\t\tconst currentToken = this.getCurrentToken();\n\t\t\tlet previousToken = this.storage.getPreviousToken( currentToken );\n\n\t\t\tif ( !previousToken ) {\n\t\t\t\tthis.skipBackUtterance();\n\t\t\t\tpreviousToken = this.storage.getLastToken( this.currentUtterance );\n\t\t\t}\n\n\t\t\tif ( previousToken ) {\n\t\t\t\tthis.highlighter.clearHighlighting();\n\t\t\t\tthis.highlighter.highlightUtterance( this.currentUtterance );\n\t\t\t}\n\n\t\t\tif ( previousToken ) {\n\t\t\t\tthis.currentUtterance.audio.currentTime = previousToken.startTime / 1000;\n\n\t\t\t\tif ( this.paused ) {\n\t\t\t\t\tthis.highlighter.highlightToken( previousToken );\n\t\t\t\t} else {\n\t\t\t\t\tthis.highlighter.startTokenHighlighting( previousToken );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\nmodule.exports = Player;\n","usedDeprecatedRules":[{"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/ext.wikispeech.selectionPlayer.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":148,"column":3,"nodeType":"CallExpression","endLine":160,"endColumn":7},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":184,"column":3,"nodeType":"CallExpression","endLine":196,"endColumn":7}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * The player that appears when the user selects a bit of text.\n *\n * Includes logic for finding what to play, and starting and\n * stopping within an utterance.\n *\n * @class ext.wikispeech.SelectionPlayer\n * @constructor\n */\n\nclass SelectionPlayer {\n\tconstructor() {\n\n\t\tthis.previousEndUtterance = null;\n\t\tthis.ui = null;\n\t\tthis.storage = null;\n\n\t}\n\t/**\n\t * Play selected text if selection is valid.\n\t *\n\t * @return {boolean} true selection plays, else false.\n\t */\n\n\tplaySelectionIfValid() {\n\t\tif ( this.isSelectionValid() ) {\n\t\t\tthis.playSelection();\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Test if the selected text is valid for recitation.\n\t *\n\t * Valid here means that the start and end points of the\n\t * selection are in nodes which are part of utterances. Nodes\n\t * outside utterances may occur within the selection.\n\t *\n\t * @return {boolean} true if the selection is valid for\n\t * recitation, else false.\n\t */\n\n\tisSelectionValid() {\n\t\tif ( !this.isTextSelected() ) {\n\t\t\treturn false;\n\t\t}\n\t\tconst firstNode = this.getFirstNodeInSelection();\n\t\tconst firstTextNode =\n\t\t\tthis.storage.getFirstTextNode( firstNode, true );\n\t\tconst lastNode = this.getLastNodeInSelection();\n\t\tconst lastTextNode =\n\t\t\tthis.storage.getLastTextNode( lastNode, true );\n\t\tif (\n\t\t\tthis.storage.isNodeInUtterance( firstTextNode ) &&\n\t\t\t\tthis.storage.isNodeInUtterance( lastTextNode )\n\t\t) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Test if there is any selected text.\n\t *\n\t * @return {boolean} true if there is any text selected, else false.\n\t */\n\n\tisTextSelected() {\n\t\tconst selection = window.getSelection();\n\t\treturn !selection.isCollapsed;\n\t}\n\n\t/**\n\t * Get the first node in the selection.\n\t *\n\t * Corrects node and offset that is sometimes incorrect in Firefox.\n\t *\n\t * @return {Text} The first node in the selection.\n\t */\n\n\tgetFirstNodeInSelection() {\n\t\tconst selection = window.getSelection();\n\t\tconst startRange = selection.getRangeAt( 0 );\n\t\tconst startNode = startRange.startContainer;\n\t\tif (\n\t\t\tstartNode.nodeType === 3 &&\n\t\t\t\tstartRange.startOffset === startNode.textContent.length\n\t\t) {\n\t\t\t// Check if start offset is beyond the end of the text node.\n\t\t\t// This is needed because of a bug in Firefox that\n\t\t\t// causes incorrect selections, when double clicking\n\t\t\t// selects the start or end of a text node. See:\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1298845\n\t\t\tlet nodeBeforeActualNode = startNode;\n\t\t\twhile ( !nodeBeforeActualNode.nextSibling ) {\n\t\t\t\tnodeBeforeActualNode = nodeBeforeActualNode.parentNode;\n\t\t\t}\n\t\t\treturn nodeBeforeActualNode.nextSibling;\n\t\t} else {\n\t\t\treturn startNode;\n\t\t}\n\t}\n\n\t/**\n\t * Play selected text.\n\t *\n\t * Plays utterances containing the selected text. The first\n\t * utterance starts playing at the first token that is\n\t * selected and the last utterance stops playing after the\n\t * last.\n\t */\n\n\tplaySelection() {\n\t\tthis.player.playingSelection = true;\n\t\tconst selection = window.getSelection();\n\t\tconst startRange = selection.getRangeAt( 0 );\n\t\tconst firstSelectionNode = this.getFirstNodeInSelection();\n\t\tlet startOffset;\n\t\tif (\n\t\t\tfirstSelectionNode !== startRange.startContainer ||\n\t\t\t\tfirstSelectionNode.nodeType === 1\n\t\t) {\n\t\t\t// If the start node has been changed, this is because\n\t\t\t// it was corrected in getFirstNodeInSelection(). If\n\t\t\t// this is the case, the selection actually starts at\n\t\t\t// the beginning of the current node. If the start\n\t\t\t// node is an element, start offset is also zero,\n\t\t\t// because if should start in the first child text\n\t\t\t// nodes of that node.\n\t\t\tstartOffset = 0;\n\t\t} else {\n\t\t\tstartOffset = startRange.startOffset;\n\t\t}\n\t\tconst startNode =\n\t\t\tthis.storage.getFirstTextNode(\n\t\t\t\tfirstSelectionNode,\n\t\t\t\ttrue\n\t\t\t);\n\t\tconst startUtterance =\n\t\t\tthis.storage.getStartUtterance(\n\t\t\t\tstartNode,\n\t\t\t\tstartOffset\n\t\t\t);\n\t\tthis.player.currentUtterance = startUtterance;\n\t\tthis.storage.prepareUtterance(\n\t\t\tstartUtterance\n\t\t)\n\t\t\t.done( () => {\n\t\t\t\tconst startToken = this.storage.getStartToken(\n\t\t\t\t\tstartUtterance,\n\t\t\t\t\tstartNode,\n\t\t\t\t\tstartOffset\n\t\t\t\t);\n\t\t\t\tthis.setStartTime( startUtterance, startToken.startTime );\n\t\t\t\tthis.player.playUtterance( startUtterance, false );\n\t\t\t\tthis.ui.setSelectionPlayerIconToStop();\n\t\t\t} );\n\t\tthis.ui.showBufferingIconIfAudioIsLoading(\n\t\t\tstartUtterance.audio\n\t\t);\n\n\t\tconst endRange = selection.getRangeAt( selection.rangeCount - 1 );\n\t\tconst lastSelectionNode = this.getLastNodeInSelection();\n\t\tlet endOffset;\n\t\tif (\n\t\t\tlastSelectionNode !== endRange.endContainer ||\n\t\t\t\tlastSelectionNode.nodeType === 1\n\t\t) {\n\t\t\tendOffset = lastSelectionNode.textContent.length - 1;\n\t\t} else {\n\t\t\tendOffset = endRange.endOffset - 1;\n\t\t}\n\t\tconst endNode =\n\t\t\tthis.storage.getLastTextNode(\n\t\t\t\tlastSelectionNode,\n\t\t\t\ttrue\n\t\t\t);\n\t\tconst endUtterance =\n\t\t\tthis.storage.getEndUtterance( endNode, endOffset );\n\t\tthis.previousEndUtterance = endUtterance;\n\t\tthis.storage.prepareUtterance(\n\t\t\tendUtterance\n\t\t)\n\t\t\t.done( () => {\n\t\t\t\t// Prepare the end utterance, since token information\n\t\t\t\t// is needed to calculate the correct end token.\n\t\t\t\tconst endToken = this.storage.getEndToken(\n\t\t\t\t\tendUtterance,\n\t\t\t\t\tendNode,\n\t\t\t\t\tendOffset\n\t\t\t\t);\n\t\t\t\tthis.setEndTime( endUtterance, endToken.endTime );\n\t\t\t} );\n\t}\n\n\t/**\n\t * Set the time where an utterance will start playing.\n\t *\n\t * @param {Object} utterance The utterance to set start time\n\t * for.\n\t * @param {number} startTime The time in milliseconds\n\t * to start playing at.\n\t */\n\n\tsetStartTime( utterance, startTime ) {\n\t\tutterance.audio.currentTime = startTime / 1000;\n\t}\n\n\t/**\n\t * Get the last node in the selection.\n\t *\n\t * Corrects node and offset that is sometimes incorrect in\n\t * Firefox.\n\t *\n\t * @return {Text} The last node in the selection.\n\t */\n\n\tgetLastNodeInSelection() {\n\t\tconst selection = window.getSelection();\n\t\tconst endRange = selection.getRangeAt( selection.rangeCount - 1 );\n\t\tconst endNode = endRange.endContainer;\n\t\tif (\n\t\t\tendNode.nodeType === 3 &&\n\t\t\t\tendRange.endOffset === 0\n\t\t) {\n\t\t\t// Check if end offset is zero. This is needed\n\t\t\t// because of a bug in Firefox that causes incorrect\n\t\t\t// selections, when double clicking selects the start\n\t\t\t// or end of a text node. See:\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1298845\n\t\t\tlet nodeAfterActualNode = endNode;\n\t\t\twhile ( !nodeAfterActualNode.previousSibling ) {\n\t\t\t\tnodeAfterActualNode = nodeAfterActualNode.parentNode;\n\t\t\t}\n\t\t\treturn nodeAfterActualNode.previousSibling;\n\t\t} else {\n\t\t\treturn endNode;\n\t\t}\n\t}\n\n\t/**\n\t * Set the time where an utterance will stop playing.\n\t *\n\t * Create an event handler for when the utterance starts\n\t * playing. The handler creates a timeout that triggers when\n\t * the end time is reached, stopping playback.\n\t *\n\t * @param {Object} utterance The utterance to set end time for.\n\t * @param {number} endTime The time in milliseconds to stop\n\t * playing after.\n\t */\n\n\tsetEndTime( utterance, endTime ) {\n\t\t$( utterance.audio ).one( 'playing.end', () => {\n\t\t\tconst timeLeft = endTime - utterance.audio.currentTime * 1000;\n\t\t\tutterance.stopTimeout =\n\t\t\t\twindow.setTimeout(\n\t\t\t\t\t() => {\n\t\t\t\t\t\tthis.player.stop();\n\t\t\t\t\t\tthis.resetPreviousEndUtterance();\n\t\t\t\t\t},\n\t\t\t\t\ttimeLeft / mw.user.options.get( 'wikispeechSpeechRate' )\n\t\t\t\t);\n\t\t} );\n\t}\n\n\t/**\n\t * Remove timeout for stopping end utterance.\n\t */\n\n\tresetPreviousEndUtterance() {\n\t\tif ( this.previousEndUtterance ) {\n\t\t\t// Remove any trigger for setting end time for an\n\t\t\t// utterance. Otherwise, this will trigger the next\n\t\t\t// time the utterance is the end utterance, possibly\n\t\t\t// stopping playback too early.\n\t\t\t$( this.previousEndUtterance.audio ).off( 'playing.end' );\n\t\t\twindow.clearTimeout( this.previousEndUtterance.stopTimeout );\n\t\t\tthis.previousEndUtterance.stopTimeout = null;\n\t\t\tthis.previousEndUtterance = null;\n\t\t}\n\t}\n}\n\nmodule.exports = SelectionPlayer;\n","usedDeprecatedRules":[{"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/ext.wikispeech.specialEditLexicon.js","messages":[],"suppressedMessages":[{"ruleId":"no-jquery/no-global-selector","severity":2,"message":"Avoid queries which search the entire DOM. Keep DOM nodes in memory where possible.","line":5,"column":19,"nodeType":"CallExpression","endLine":5,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.storage.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":47,"column":3,"nodeType":"CallExpression","endLine":80,"endColumn":6},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":94,"column":1,"nodeType":"Block","endLine":94,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":150,"column":1,"nodeType":"Block","endLine":150,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":159,"column":10,"nodeType":"CallExpression","endLine":172,"endColumn":7},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":183,"column":1,"nodeType":"Block","endLine":183,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":203,"column":19,"nodeType":"CallExpression","endLine":215,"endColumn":7}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Loads and stores objects used by the extension.\n *\n * Contains functions for other modules to retrieve information\n * about the utterances.\n *\n * @class ext.wikispeech.Storage\n * @constructor\n */\n\nconst util = require( './ext.wikispeech.util.js' );\n\nclass Storage {\n\tconstructor() {\n\t\tthis.utterances = [];\n\t\tthis.utterancesLoaded = $.Deferred();\n\n\t\tconst producerUrl = mw.config.get( 'wgWikispeechProducerUrl' );\n\t\tif ( producerUrl ) {\n\t\t\tconst producerApiUrl = `${ producerUrl }/api.php`;\n\t\t\tthis.api = new mw.ForeignApi( producerApiUrl );\n\t\t} else {\n\t\t\tthis.api = new mw.Api();\n\t\t}\n\n\t}\n\n\t/**\n\t * Load all utterances.\n\t *\n\t * Uses the MediaWiki API to get the segments of the text.\n\t *\n\t * @param {Object} window\n\t */\n\n\tloadUtterances( window ) {\n\t\tconst page = mw.config.get( 'wgPageName' );\n\t\tconst options = {\n\t\t\taction: 'wikispeech-segment',\n\t\t\tpage: page,\n\t\t\t'part-of-content': mw.user.options.get( 'wikispeechPartOfContent' )\n\t\t};\n\t\tif ( mw.config.get( 'wgWikispeechProducerUrl' ) ) {\n\t\t\toptions[ 'consumer-url' ] = window.location.origin +\n\t\t\t\tmw.config.get( 'wgScriptPath' );\n\t\t}\n\t\tthis.api.get(\n\t\t\toptions,\n\t\t\t{\n\t\t\t\tbeforeSend: function ( jqXHR, settings ) {\n\t\t\t\t\tmw.log(\n\t\t\t\t\t\t'Requesting segments:', settings.url\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t).done( ( data ) => {\n\t\t\tmw.log( 'Segments received:', data );\n\t\t\tthis.utterances = data[ 'wikispeech-segment' ].segments;\n\n\t\t\t// Add extra offset to the title if it has leading\n\t\t\t// whitespaces. When using the new skin, there are\n\t\t\t// whitespaces around the title that do not appear in\n\t\t\t// the display title. This leads to highlighting being\n\t\t\t// wrong.\n\t\t\tconst titleUtterance = this.utterances[ 0 ];\n\t\t\tconst firstNode = this.getNodeForItem( titleUtterance.content[ 0 ] );\n\t\t\tconst leadingWhitespaces = firstNode.textContent.match( /^\\s+/ );\n\t\t\tif ( leadingWhitespaces ) {\n\t\t\t\tconst offset = leadingWhitespaces[ 0 ].length;\n\t\t\t\ttitleUtterance.startOffset += offset;\n\t\t\t\ttitleUtterance.endOffset += offset;\n\t\t\t}\n\n\t\t\tfor ( let i = 0; i < this.utterances.length; i++ ) {\n\t\t\t\tconst utterance = this.utterances[ i ];\n\t\t\t\tutterance.audio = $( '<audio>' ).get( 0 );\n\t\t\t}\n\t\t\tthis.utterancesLoaded.resolve();\n\t\t\tthis.prepareUtterance( this.utterances[ 0 ] );\n\t\t} );\n\t}\n\n\t/**\n\t * Prepare an utterance for playback.\n\t *\n\t * Audio for the utterance is requested from the Speechoid service\n\t * and event listeners are added. When an utterance starts\n\t * playing, the next one is prepared, and when an utterance is\n\t * done, the next utterance is played. This is meant to be a\n\t * balance between not having to pause between utterance and\n\t * not requesting more than needed.\n\t *\n\t * @param {Object} utterance The utterance to prepare.\n\t * @return {jQuery.Promise}\n\t */\n\n\tprepareUtterance( utterance ) {\n\t\tconst $audio = $( utterance.audio );\n\t\tif ( !utterance.request ) {\n\t\t\t// Add event listener only once.\n\t\t\t$audio.on( 'playing', () => {\n\t\t\t\tlet firstToken;\n\n\t\t\t\t// Highlight token only when the audio starts\n\t\t\t\t// playing, since we need the token info from the\n\t\t\t\t// response to know what to highlight.\n\t\t\t\tif (\n\t\t\t\t\t!this.player.playingSelection &&\n\t\t\t\t\t\t$audio.prop( 'currentTime' ) === 0\n\t\t\t\t) {\n\t\t\t\t\tfirstToken = utterance.tokens[ 0 ];\n\t\t\t\t\tthis.highlighter.startTokenHighlighting(\n\t\t\t\t\t\tfirstToken\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t\tconst nextUtterance = this.getNextUtterance( utterance );\n\t\t\tif ( nextUtterance ) {\n\t\t\t\t$audio.on( {\n\t\t\t\t\tplay: () => {\n\t\t\t\t\t\tthis.prepareUtterance( nextUtterance );\n\t\t\t\t\t},\n\t\t\t\t\tended: () => {\n\t\t\t\t\t\tthis.player.skipAheadUtterance();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t// For last utterance, just stop the playback when\n\t\t\t\t// done.\n\t\t\t\t$audio.on( 'ended', () => {\n\t\t\t\t\tthis.player.stop();\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\tif ( !utterance.request || utterance.request.state() === 'rejected' ) {\n\t\t\t// Only load audio for an utterance if it hasn't been\n\t\t\t// successfully loaded yet.\n\t\t\tutterance.request = this.loadAudio( utterance );\n\t\t}\n\t\treturn utterance.request;\n\t}\n\n\t/**\n\t * Load audio for an utterance.\n\t *\n\t * Sends a request to the Speechoid service and adds audio and tokens\n\t * when the response is received.\n\t *\n\t * @param {Object} utterance The utterance to load audio for.\n\t * @return {jQuery.Promise}\n\t */\n\n\tloadAudio( utterance ) {\n\t\tconst utteranceIndex = this.utterances.indexOf( utterance );\n\t\tmw.log(\n\t\t\t'Loading audio for utterance #' + utteranceIndex + ':',\n\t\t\tutterance\n\t\t);\n\t\treturn this.requestTts( utterance.hash, window )\n\t\t\t.done( ( response ) => {\n\t\t\t\tconst audioUrl = 'data:audio/ogg;base64,' +\n\t\t\t\t\tresponse[ 'wikispeech-listen' ].audio;\n\t\t\t\tmw.log(\n\t\t\t\t\t'Setting audio url for: [' + utteranceIndex + ']',\n\t\t\t\t\tutterance, '=',\n\t\t\t\t\tresponse[ 'wikispeech-listen' ].audio.length + ' base64 bytes'\n\t\t\t\t);\n\t\t\t\t$( utterance.audio ).attr( 'src', audioUrl );\n\t\t\t\tutterance.audio.playbackRate =\n\t\t\t\t\tmw.user.options.get( 'wikispeechSpeechRate' );\n\t\t\t\tthis.addTokens( utterance, response[ 'wikispeech-listen' ].tokens );\n\t\t\t} );\n\t}\n\n\t/**\n\t * Send a request to the Speechoid service.\n\t *\n\t * Request is sent via the \"wikispeech-listen\" API action. Language to\n\t * use is retrieved from the current page.\n\t *\n\t * @param {string} segmentHash\n\t * @param {Object} window\n\t * @return {jQuery.Promise}\n\t */\n\n\trequestTts( segmentHash, window ) {\n\t\tconst language = mw.config.get( 'wgPageContentLanguage' );\n\t\tconst voice = util.getUserVoice( language );\n\t\tconst options = {\n\t\t\taction: 'wikispeech-listen',\n\t\t\tlang: language,\n\t\t\trevision: mw.config.get( 'wgRevisionId' ),\n\t\t\tsegment: segmentHash\n\t\t};\n\t\tif ( voice !== '' ) {\n\t\t\t// Set voice if not default.\n\t\t\toptions.voice = voice;\n\t\t}\n\t\tif ( mw.config.get( 'wgWikispeechProducerUrl' ) ) {\n\t\t\toptions[ 'consumer-url' ] = window.location.origin +\n\t\t\t\tmw.config.get( 'wgScriptPath' );\n\t\t}\n\t\tconst request = this.api.get(\n\t\t\toptions,\n\t\t\t{\n\t\t\t\tbeforeSend: function ( jqXHR, settings ) {\n\t\t\t\t\tmw.log(\n\t\t\t\t\t\t'Sending TTS request: ' + settings.url\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t\t.done( ( data ) => {\n\t\t\t\tmw.log( 'Response received:', data );\n\t\t\t} );\n\t\treturn request;\n\t}\n\n\t/**\n\t * Add tokens to an utterance.\n\t *\n\t * @param {Object} utterance The utterance to add tokens to.\n\t * @param {Object[]} responseTokens Tokens from a Speechoid response,\n\t * where each token is an object. For these objects, the\n\t * property \"orth\" is the string used by the TTS to generate\n\t * audio for the token.\n\t */\n\n\taddTokens( utterance, responseTokens ) {\n\t\tutterance.tokens = [];\n\t\tlet searchOffset = 0;\n\t\tfor ( let i = 0; i < responseTokens.length; i++ ) {\n\t\t\tconst responseToken = responseTokens[ i ];\n\t\t\tlet startTime;\n\t\t\tif ( i === 0 ) {\n\t\t\t\t// The first token in an utterance always start on\n\t\t\t\t// time zero.\n\t\t\t\tstartTime = 0;\n\t\t\t} else {\n\t\t\t\t// Since the response only contains end times for\n\t\t\t\t// token, the start time for a token is set to the\n\t\t\t\t// end time of the previous one.\n\t\t\t\tstartTime = responseTokens[ i - 1 ].endtime;\n\t\t\t}\n\t\t\tconst token = {\n\t\t\t\tstring: responseToken.orth,\n\t\t\t\tstartTime: startTime,\n\t\t\t\tendTime: responseToken.endtime,\n\t\t\t\tutterance: utterance\n\t\t\t};\n\t\t\tutterance.tokens.push( token );\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Start looking for the next token after the\n\t\t\t\t// previous one, except for the first token, where\n\t\t\t\t// we want to start on zero.\n\t\t\t\tsearchOffset += 1;\n\t\t\t}\n\t\t\tsearchOffset = this.addOffsetsAndItems(\n\t\t\t\ttoken,\n\t\t\t\tsearchOffset\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Add properties for offsets and items to a token.\n\t *\n\t * The offsets are for the start and end of the token in the\n\t * text node which they appear. These text nodes are not\n\t * necessary the same.\n\t *\n\t * The items store information used to get the text nodes in\n\t * which the token starts, ends and any text nodes in between.\n\t *\n\t * @param {Object} token The token to add properties to.\n\t * @param {number} searchOffset The offset to start searching\n\t * from, in the concatenated string.\n\t * @return {number} The end offset in the concatenated string.\n\t */\n\n\taddOffsetsAndItems(\n\t\ttoken,\n\t\tsearchOffset\n\t) {\n\t\tconst utterance = token.utterance;\n\t\tlet items = [];\n\t\tconst startOffsetInUtteranceString =\n\t\t\tthis.getStartOffsetInUtteranceString(\n\t\t\t\ttoken.string,\n\t\t\t\tutterance.content,\n\t\t\t\titems,\n\t\t\t\tsearchOffset\n\t\t\t);\n\t\tconst endOffsetInUtteranceString =\n\t\t\tstartOffsetInUtteranceString +\n\t\t\ttoken.string.length - 1;\n\n\t\t// `items` now contains all the items in the utterance,\n\t\t// from the first one to the last, that contains at least\n\t\t// part of the token. To get only the ones that contain\n\t\t// part of the token, the items that appear before the\n\t\t// token are removed.\n\t\tlet endOffsetForItem = 0;\n\t\titems =\n\t\t\titems.filter( ( item ) => {\n\t\t\t\tendOffsetForItem += item.string.length;\n\t\t\t\treturn endOffsetForItem >\n\t\t\t\t\tstartOffsetInUtteranceString;\n\t\t\t} );\n\t\ttoken.items = items;\n\n\t\t// Calculate start and end offset for the token, in the\n\t\t// text nodes it appears in, and add them to the\n\t\t// token.\n\t\tconst firstItemIndex =\n\t\t\tutterance.content.indexOf( items[ 0 ] );\n\t\tconst itemsBeforeStart =\n\t\t\tutterance.content.slice( 0, firstItemIndex );\n\t\tlet itemsBeforeStartLength = 0;\n\t\titemsBeforeStart.forEach( ( item ) => {\n\t\t\titemsBeforeStartLength += item.string.length;\n\t\t} );\n\t\ttoken.startOffset =\n\t\t\tstartOffsetInUtteranceString -\n\t\t\titemsBeforeStartLength;\n\t\tif ( token.items[ 0 ] === utterance.content[ 0 ] ) {\n\t\t\ttoken.startOffset += utterance.startOffset;\n\t\t}\n\t\tconst lastItemIndex =\n\t\t\tutterance.content.indexOf(\n\t\t\t\tutil.getLast( items )\n\t\t\t);\n\t\tconst itemsBeforeEnd = utterance.content.slice( 0, lastItemIndex );\n\t\tlet itemsBeforeEndLength = 0;\n\t\titemsBeforeEnd.forEach( ( item ) => {\n\t\t\titemsBeforeEndLength += item.string.length;\n\t\t} );\n\t\ttoken.endOffset =\n\t\t\tendOffsetInUtteranceString - itemsBeforeEndLength;\n\t\tif (\n\t\t\tutil.getLast( token.items ) ===\n\t\t\t\tutterance.content[ 0 ]\n\t\t) {\n\t\t\ttoken.endOffset += utterance.startOffset;\n\t\t}\n\t\treturn endOffsetInUtteranceString;\n\t}\n\n\t/**\n\t * Calculate the start offset of a token in the utterance string.\n\t *\n\t * The token is the first match found, starting at\n\t * searchOffset.\n\t *\n\t * @param {string} token The token to search for.\n\t * @param {Object[]} content The content of the utterance where\n\t * the token appear.\n\t * @param {Object[]} items An array of items to which each\n\t * item, up to and including the last one that contains\n\t * part of the token, is added.\n\t * @param {number} searchOffset Where we want to start looking\n\t * for the token in the utterance string.\n\t * @return {number} The offset where the first character of\n\t * the token appears in the utterance string.\n\t */\n\n\tgetStartOffsetInUtteranceString(\n\t\ttoken,\n\t\tcontent,\n\t\titems,\n\t\tsearchOffset\n\t) {\n\t\tlet startOffsetInUtteranceString, stringBeforeReplace;\n\n\t\t// The concatenation of the strings from items. Used to\n\t\t// find tokens that span multiple text nodes.\n\t\tlet concatenatedText = '';\n\t\tcontent.every( ( item ) => {\n\t\t\t// Look through the items until we find a substring\n\t\t\t// matching the token.\n\t\t\t// The `replaceAll` replaces non-breaking space with a\n\t\t\t// normal space. This is required if Speechoid returns\n\t\t\t// normal spaces in \"orth\" for a token. See\n\t\t\t// https://phabricator.wikimedia.org/T286997\n\t\t\tconcatenatedText += item.string.replace( ' ', ' ' );\n\n\t\t\t// Eslint does not allow replaceAll().\n\t\t\tdo {\n\t\t\t\tstringBeforeReplace = concatenatedText;\n\t\t\t\tconcatenatedText = concatenatedText.replace( ' ', ' ' );\n\t\t\t} while ( stringBeforeReplace !== concatenatedText );\n\n\t\t\titems.push( item );\n\t\t\tif ( searchOffset > concatenatedText.length ) {\n\t\t\t\t// Don't look in text elements that end before\n\t\t\t\t// where we start looking.\n\t\t\t\t// continue\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tstartOffsetInUtteranceString = concatenatedText.indexOf(\n\t\t\t\ttoken, searchOffset\n\t\t\t);\n\t\t\tif ( startOffsetInUtteranceString >= 0 ) {\n\t\t\t\t// break\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t} );\n\t\treturn startOffsetInUtteranceString;\n\t}\n\n\t/**\n\t * Get the utterance after the given utterance.\n\t *\n\t * @param {Object} utterance The original utterance.\n\t * @return {Object} The utterance after the original\n\t * utterance. null if utterance is the last one.\n\t */\n\n\tgetNextUtterance( utterance ) {\n\t\treturn this.getUtteranceByOffset( utterance, 1 );\n\t}\n\n\t/**\n\t * Get the utterance by offset from another utterance.\n\t *\n\t * @param {Object} utterance The original utterance.\n\t * @param {number} offset The difference, in index, to the\n\t * wanted utterance. Can be negative for preceding\n\t * utterances.\n\t * @return {Object} The utterance on the position before or\n\t * after the original utterance, as specified by\n\t * `offset`. null if the original utterance is null.\n\t */\n\n\tgetUtteranceByOffset( utterance, offset ) {\n\t\tif ( utterance === null ) {\n\t\t\treturn null;\n\t\t}\n\t\tconst index = this.utterances.indexOf( utterance );\n\t\treturn this.utterances[ index + offset ];\n\t}\n\n\t/**\n\t * Get the utterance before the given utterance.\n\t *\n\t * @param {Object} utterance The original utterance.\n\t * @return {Object} The utterance before the original\n\t * utterance. null if the original utterance is the\n\t * first one.\n\t */\n\n\tgetPreviousUtterance( utterance ) {\n\t\treturn this.getUtteranceByOffset( utterance, -1 );\n\t}\n\n\t/**\n\t * Get the token following a given token.\n\t *\n\t * @param {Object} originalToken Find the next token after\n\t * this one.\n\t * @return {Object} The first token following originalToken\n\t * that has time greater than zero and a transcription. null\n\t * if no such token is found. Will not look beyond\n\t * originalToken's utterance.\n\t */\n\n\tgetNextToken( originalToken ) {\n\t\tconst index = originalToken.utterance.tokens.indexOf( originalToken );\n\t\tconst succeedingTokens =\n\t\t\toriginalToken.utterance.tokens.slice( index + 1 ).filter(\n\t\t\t\t( token ) => !this.isSilent( token ) );\n\t\tif ( succeedingTokens.length === 0 ) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn succeedingTokens[ 0 ];\n\t\t}\n\t}\n\n\t/**\n\t * Test if a token is silent.\n\t *\n\t * Silent is here defined as either having no transcription\n\t * (i.e. the empty string) or having no duration (i.e. start\n\t * and end time is the same).\n\t *\n\t * @param {Object} token The token to test.\n\t * @return {boolean} true if the token is silent, else false.\n\t */\n\n\tisSilent( token ) {\n\t\treturn token.startTime === token.endTime ||\n\t\t\ttoken.string === '';\n\t}\n\n\t/**\n\t * Get the token preceding a given token.\n\t *\n\t * @param {Object} originalToken Find the token before this one.\n\t * @return {Object} The first token following originalToken\n\t * that has time greater than zero and a transcription. null\n\t * if no such token is found. Will not look beyond\n\t * originalToken's utterance.\n\t */\n\n\tgetPreviousToken( originalToken ) {\n\t\tconst index = originalToken.utterance.tokens.indexOf( originalToken );\n\t\tconst precedingTokens =\n\t\t\toriginalToken.utterance.tokens.slice( 0, index ).filter(\n\t\t\t\t( token ) => !this.isSilent( token ) );\n\t\tif ( precedingTokens.length === 0 ) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tconst previousToken = util.getLast( precedingTokens );\n\t\t\treturn previousToken;\n\t\t}\n\t}\n\n\t/**\n\t * Get the last non silent token in an utterance.\n\t *\n\t * @param {Object} utterance The utterance to get the last\n\t * token from.\n\t * @return {Object} The last token in the utterance.\n\t */\n\n\tgetLastToken( utterance ) {\n\t\tconst nonSilentTokens = utterance.tokens.filter( ( token ) => !this.isSilent( token ) );\n\t\tconst lastToken = util.getLast( nonSilentTokens );\n\t\treturn lastToken;\n\t}\n\n\t/**\n\t * Get the first text node that is a descendant of the given node.\n\t *\n\t * Finds the depth first text node, i.e. in\n\t * `<a><b>1</b>2</a>`\n\t * the node with text \"1\" is the first one. If the given node is\n\t * itself a text node, it is simply returned.\n\t *\n\t * @param {HTMLElement} node The node under which to look for\n\t * text nodes.\n\t * @param {boolean} inUtterance If true, the first text node\n\t * that is also in an utterance is returned.\n\t * @return {Text} The first text node under `node`,\n\t * undefined if there are no text nodes.\n\t */\n\n\tgetFirstTextNode( node, inUtterance ) {\n\t\tif ( node.nodeType === 3 ) {\n\t\t\tif ( !inUtterance || this.isNodeInUtterance( node ) ) {\n\t\t\t\t// The given node is a text node. Check whether\n\t\t\t\t// the node is in an utterance, if that is\n\t\t\t\t// requested.\n\t\t\t\treturn node;\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( let i = 0; i < node.childNodes.length; i++ ) {\n\t\t\t\t// Check children if the given node is an element.\n\t\t\t\tconst child = node.childNodes[ i ];\n\t\t\t\tconst textNode = this.getFirstTextNode( child, inUtterance );\n\t\t\t\tif ( textNode ) {\n\t\t\t\t\treturn textNode;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check if a text node is in any utterance.\n\t *\n\t * Utterances don't have any direct references to nodes, but\n\t * rather use XPath expressions to find the nodes that were used\n\t * when creating them.\n\t *\n\t * @param {Text} node The text node to check.\n\t * @return {boolean} true if the node is in any utterance, else false.\n\t */\n\n\tisNodeInUtterance( node ) {\n\t\tfor ( let i = 0; i < this.utterances.length; i++ ) {\n\t\t\tconst utterance = this.utterances[ i ];\n\t\t\tfor ( let j = 0; j < utterance.content.length; j++ ) {\n\t\t\t\tconst item = utterance.content[ j ];\n\t\t\t\tif ( this.getNodeForItem( item ) === node ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get the utterance containing a point, searching forward.\n\t *\n\t * Finds the utterance that contains a point in the text,\n\t * specified by a node and an offset in that node. Several\n\t * utterances may contain parts of the same node, which is why\n\t * the offset is needed.\n\t *\n\t * If the offset can't be found in the given node, later nodes\n\t * are checked. This happens if the offset falls between two\n\t * utterances.\n\t *\n\t * @param {Text} node The first node to check.\n\t * @param {number} offset The offset in the node.\n\t * @return {Object} The matching utterance.\n\t */\n\n\tgetStartUtterance( node, offset ) {\n\t\tfor ( ; offset < node.textContent.length; offset++ ) {\n\t\t\tfor ( let i = 0; i < this.utterances.length; i++ ) {\n\t\t\t\tconst utterance = this.utterances[ i ];\n\t\t\t\tif (\n\t\t\t\t\tthis.isPointInItems(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tutterance.content,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tutterance.startOffset,\n\t\t\t\t\t\tutterance.endOffset\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn utterance;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// No match found in the given node, check the next one.\n\t\tconst nextTextNode = this.getNextTextNode( node );\n\t\treturn this.getStartUtterance( nextTextNode, 0 );\n\t}\n\n\t/**\n\t * Check if a point in the text is in any of a number of items.\n\t *\n\t * Checks if a node is present in any of the items. When a\n\t * matching item is found, checks if the offset falls between\n\t * the given min and max values.\n\t *\n\t * @param {Text} node The node to check.\n\t * @param {Object[]} items Item objects containing a path to\n\t * the node they were created from.\n\t * @param {number} offset Offset in the node.\n\t * @param {number} minOffset The minimum offset to be\n\t * considered a match.\n\t * @param {number} maxOffset The maximum offset to be\n\t * considered a match.\n\t */\n\n\tisPointInItems(\n\t\tnode,\n\t\titems,\n\t\toffset,\n\t\tminOffset,\n\t\tmaxOffset\n\t) {\n\t\tif ( items.length === 1 ) {\n\t\t\tconst item = items[ 0 ];\n\t\t\tif (\n\t\t\t\tthis.getNodeForItem( item ) === node &&\n\t\t\t\t\toffset >= minOffset &&\n\t\t\t\t\toffset <= maxOffset\n\t\t\t) {\n\t\t\t\t// Just check if the offset is within the min and\n\t\t\t\t// max offsets, if there is only one item.\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( let i = 0; i < items.length; i++ ) {\n\t\t\t\tconst item = items[ i ];\n\t\t\t\tif ( this.getNodeForItem( item ) !== node ) {\n\t\t\t\t\t// Skip items that don't match the node we're\n\t\t\t\t\t// looking for.\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst index = items.indexOf( item );\n\t\t\t\tif ( index === 0 ) {\n\t\t\t\t\tif ( offset >= minOffset ) {\n\t\t\t\t\t\t// For the first node, check if position is\n\t\t\t\t\t\t// after the start of the utterance.\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t} else if ( index === items.length - 1 ) {\n\t\t\t\t\tif ( offset <= maxOffset ) {\n\t\t\t\t\t\t// For the last node, check if position is\n\t\t\t\t\t\t// before end of utterance.\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Any other node should be entirely within the\n\t\t\t\t\t// utterance.\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get the first text node after a given node.\n\t *\n\t * @param {HTMLElement|Text} node Get the text node after\n\t * this one.\n\t * @return {Text} The first node after `node`.\n\t */\n\n\tgetNextTextNode( node ) {\n\t\tconst nextNode = node.nextSibling;\n\t\tif ( nextNode === null ) {\n\t\t\t// No more text nodes, start traversing the DOM\n\t\t\t// upward, checking sibling of ancestors.\n\t\t\treturn this.getNextTextNode( node.parentNode );\n\t\t} else if ( nextNode.nodeType === 1 ) {\n\t\t\t// Node is an element, find the first text node in\n\t\t\t// it's children.\n\t\t\tfor ( let i = 0; i < nextNode.childNodes.length; i++ ) {\n\t\t\t\tconst child = nextNode.childNodes[ i ];\n\t\t\t\tconst textNode = this.getFirstTextNode( child );\n\t\t\t\tif ( textNode ) {\n\t\t\t\t\treturn textNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.getNextTextNode( nextNode );\n\t\t} else if ( nextNode.nodeType === 3 ) {\n\t\t\treturn nextNode;\n\t\t}\n\t}\n\n\t/**\n\t * Get the token containing a point, searching forward.\n\t *\n\t * Finds the token that contains a point in the text,\n\t * specified by a node and an offset in that node. Several\n\t * tokens may contain parts of the same node, which is why\n\t * the offset is needed.\n\t *\n\t * If the offset can't be found in the given node, later nodes\n\t * are checked. This happens if the offset falls between two\n\t * tokens.\n\t *\n\t * @param {Object} utterance The utterance to look for tokens in.\n\t * @param {Text} node The node that contains the token.\n\t * @param {number} offset The offset in the node.\n\t * @param {Object} The first token found.\n\t */\n\n\tgetStartToken( utterance, node, offset ) {\n\t\tfor ( ; offset < node.textContent.length; offset++ ) {\n\t\t\tfor ( let i = 0; i < utterance.tokens.length; i++ ) {\n\t\t\t\tconst token = utterance.tokens[ i ];\n\t\t\t\tif (\n\t\t\t\t\tthis.isPointInItems(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ttoken.items,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\ttoken.startOffset,\n\t\t\t\t\t\ttoken.endOffset\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn token;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// If token wasn't found in the given node, check the next\n\t\t// one.\n\t\tconst nextTextNode = this.getNextTextNode( node );\n\t\treturn this.getStartToken( utterance, nextTextNode, 0 );\n\t}\n\n\t/**\n\t * Get the last text node that is a descendant of given node.\n\t *\n\t * Finds the depth first text node, i.e. in\n\t * `<a>1<b>2</b></a>`\n\t * the node with text \"2\" is the last one. If the given node\n\t * is itself a text node, it is simply returned.\n\t *\n\t * @param {HTMLElement} node The node under which to look for\n\t * text nodes.\n\t * @param {boolean} inUtterance If true, the last text node\n\t * that is also in an utterance is returned.\n\t * @return {Text} The last text node under `node`,\n\t * undefined if there are no text nodes.\n\t */\n\n\tgetLastTextNode( node, inUtterance ) {\n\t\tif ( node.nodeType === 3 ) {\n\t\t\tif ( !inUtterance || this.isNodeInUtterance( node ) ) {\n\t\t\t\t// The given node is a text node. Check whether\n\t\t\t\t// the node is in an utterance, if that is\n\t\t\t\t// requested.\n\t\t\t\treturn node;\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( let i = node.childNodes.length - 1; i >= 0; i-- ) {\n\t\t\t\t// Check children if the given node is an element.\n\t\t\t\tconst child = node.childNodes[ i ];\n\t\t\t\tconst textNode = this.getLastTextNode( child, inUtterance );\n\t\t\t\tif ( textNode ) {\n\t\t\t\t\treturn textNode;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the utterance containing a point, searching backward.\n\t *\n\t * Finds the utterance that contains a point in the text,\n\t * specified by a node and an offset in that node. Several\n\t * utterances may contain parts of the same node, which is why\n\t * the offset is needed.\n\t *\n\t * If the offset can't be found in the given node, preceding\n\t * nodes are checked. This happens if the offset falls between\n\t * two utterances.\n\t *\n\t * @param {Text} node The first node to check.\n\t * @param {number} offset The offset in the node.\n\t * @return {Object} The matching utterance.\n\t */\n\n\tgetEndUtterance( node, offset ) {\n\t\tfor ( ; offset >= 0; offset-- ) {\n\t\t\tfor ( let i = 0; i < this.utterances.length; i++ ) {\n\t\t\t\tconst utterance = this.utterances[ i ];\n\t\t\t\tif (\n\t\t\t\t\tthis.isPointInItems(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tutterance.content,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tutterance.startOffset,\n\t\t\t\t\t\tutterance.endOffset\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn utterance;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst previousTextNode = this.getPreviousTextNode( node );\n\t\treturn this.getEndUtterance(\n\t\t\tpreviousTextNode,\n\t\t\tpreviousTextNode.textContent.length\n\t\t);\n\t}\n\n\t/**\n\t * Get the first text node before a given node.\n\t *\n\t * @param {HTMLElement|Text} node Get the text node before\n\t * this one.\n\t * @return {Text} The first node before `node`.\n\t */\n\n\tgetPreviousTextNode( node ) {\n\t\tconst previousNode = node.previousSibling;\n\t\tif ( previousNode === null ) {\n\t\t\treturn this.getPreviousTextNode( node.parentNode );\n\t\t} else if ( previousNode.nodeType === 1 ) {\n\t\t\tfor ( let i = previousNode.childNodes.length - 1; i >= 0; i-- ) {\n\t\t\t\tconst child = previousNode.childNodes[ i ];\n\t\t\t\tconst textNode = this.getLastTextNode( child );\n\t\t\t\tif ( textNode ) {\n\t\t\t\t\treturn textNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.getPreviousTextNode( previousNode );\n\t\t} else if ( previousNode.nodeType === 3 ) {\n\t\t\treturn previousNode;\n\t\t}\n\t}\n\n\t/**\n\t * Get the token containing a point, searching backward.\n\t *\n\t * Finds the token that contains a point in the text,\n\t * specified by a node and an offset in that node. Several\n\t * tokens may contain parts of the same node, which is why\n\t * the offset is needed.\n\t *\n\t * If the offset can't be found in the given node, preceding\n\t * nodes are checked. This happens if the offset falls between\n\t * two tokens.\n\t *\n\t * @param {Object} utterance The utterance to look for tokens in.\n\t * @param {Text} node The node that contains the token.\n\t * @param {number} offset The offset in the node.\n\t * @param {Object} The first token found.\n\t */\n\n\tgetEndToken( utterance, node, offset ) {\n\t\tfor ( ; offset >= 0; offset-- ) {\n\t\t\tfor ( let i = 0; i < utterance.tokens.length; i++ ) {\n\t\t\t\tconst token = utterance.tokens[ i ];\n\t\t\t\tif (\n\t\t\t\t\tthis.isPointInItems(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ttoken.items,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\ttoken.startOffset,\n\t\t\t\t\t\ttoken.endOffset\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn token;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst previousTextNode = this.getPreviousTextNode( node );\n\t\treturn this.getEndToken(\n\t\t\tutterance,\n\t\t\tpreviousTextNode,\n\t\t\tpreviousTextNode.textContent.length\n\t\t);\n\t}\n\n\t/**\n\t * Find the text node from which a content item was created.\n\t *\n\t * The path property of the item is an XPath expression\n\t * that is used to traverse the DOM tree.\n\t *\n\t * @param {Object} item The item to find the text node for.\n\t * @return {Text} The text node associated with the item.\n\t */\n\n\tgetNodeForItem( item ) {\n\t\tif ( item.path === null ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// The path should be unambiguous, so just get the first\n\t\t// matching node.\n\t\tconst contentSelector = mw.config.get( 'wgWikispeechContentSelector' );\n\t\tconst result = document.evaluate(\n\t\t\titem.path,\n\t\t\t$( contentSelector ).get( 0 ),\n\t\t\tnull,\n\t\t\tXPathResult.FIRST_ORDERED_NODE_TYPE,\n\t\t\tnull\n\t\t);\n\t\tconst node = result.singleNodeValue;\n\t\treturn node;\n\t}\n}\n\nmodule.exports = Storage;\n","usedDeprecatedRules":[{"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/ext.wikispeech.transcriptionPreviewer.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":32,"column":1,"nodeType":"Block","endLine":32,"endColumn":1},{"ruleId":"max-len","severity":1,"message":"This line has a length of 103. Maximum allowed is 100.","line":37,"column":1,"nodeType":"Program","messageId":"max","endLine":37,"endColumn":98},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":57,"column":1,"nodeType":"Block","endLine":57,"endColumn":1},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":66,"column":19,"nodeType":"CallExpression","endLine":74,"endColumn":6},{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .fail","line":66,"column":19,"nodeType":"CallExpression","endLine":80,"endColumn":6}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"const util = require( './ext.wikispeech.util.js' );\n\n/**\n * Generates audio preview for the transcription in SpecialEditLexicon.\n *\n * @class TranscriptionPreviewer\n * @param {jQuery} $language\n * @param {jQuery} $transcription\n * @param {mw.Api} api\n * @param {jQuery} $player\n */\nclass TranscriptionPreviewer {\n\tconstructor(\n\t\t$language,\n\t\t$transcription,\n\t\tapi,\n\t\t$player\n\t) {\n\t\tthis.$language = $language;\n\t\tthis.$transcription = $transcription;\n\t\tthis.api = api;\n\t\tthis.$player = $player;\n\t\tthis.lastTranscription = null;\n\t}\n\n\t/**\n\t * Play the transcription using TTS.\n\t *\n\t * If the transcription has changed since last play, a new one\n\t * retrieved. Otherwise the previous one is replayed.\n\t *\n\t * @return {jQuery.Promise} Fulfilled when audio starts playing, rejected if\n\t * audio was not present.\n\t */\n\tplay() {\n\t\tconst transcription = this.$transcription.val();\n\t\t// Rewind in case it is already playing. Just calling play() is not enought to play from start.\n\t\tthis.$player.prop( 'currentTime', 0 );\n\n\t\tlet promise;\n\t\tif ( transcription !== this.lastTranscription || !this.$player.attr( 'src' ) ) {\n\t\t\tpromise = this.fetchAudio().then( () => {\n\t\t\t\tthis.$player.get( 0 ).play();\n\t\t\t} );\n\t\t\tthis.lastTranscription = transcription;\n\t\t} else {\n\t\t\tthis.$player.get( 0 ).play();\n\t\t\tpromise = $.Deferred().resolve().promise();\n\t\t}\n\n\t\treturn promise;\n\t}\n\n\t/**\n\t * Get audio for the player using the listen API\n\t *\n\t * @return {jQuery.Promise} Fulfilled when audio is fetched, rejected\n\t * if there was an error.\n\t */\n\tfetchAudio() {\n\t\tconst language = this.$language.val();\n\t\tconst voice = util.getUserVoice( language );\n\t\tconst transcription = this.$transcription.val();\n\t\tmw.log( 'Fetching transcription preview for (' + language + '): ' + transcription );\n\n\t\tconst request = this.api.get( {\n\t\t\taction: 'wikispeech-listen',\n\t\t\tlang: language,\n\t\t\tipa: transcription,\n\t\t\tvoice: voice\n\t\t} ).done( ( response ) => {\n\t\t\tconst audioData = response[ 'wikispeech-listen' ].audio;\n\t\t\tthis.$player.attr( 'src', 'data:audio/ogg;base64,' + audioData );\n\t\t} ).fail( ( code, result ) => {\n\t\t\tthis.$player.attr( 'src', '' );\n\t\t\tmw.log.error( 'Failed to synthesize:', code, result );\n\t\t\tconst message = result.error.info;\n\t\t\tconst title = mw.msg( 'wikispeech-error-generate-preview-title' );\n\t\t\tOO.ui.alert( message, { title: title, size: 'medium' } );\n\t\t} );\n\n\t\treturn request;\n\t}\n}\nmodule.exports = TranscriptionPreviewer;\n","usedDeprecatedRules":[{"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/ext.wikispeech.ui.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":126,"column":3,"nodeType":"CallExpression","endLine":134,"endColumn":7},{"ruleId":"max-len","severity":1,"message":"This line has a length of 119. Maximum allowed is 100.","line":240,"column":1,"nodeType":"Program","messageId":"max","endLine":240,"endColumn":114},{"ruleId":"mediawiki/no-unlabeled-buttonwidget","severity":2,"message":"OO.ui.ButtonWidget has no label. Even icon-only buttons should set a label with invisibleLabel set to true.","line":356,"column":27,"nodeType":"NewExpression","messageId":"noLabel","endLine":360,"endColumn":6},{"ruleId":"security/detect-non-literal-require","severity":1,"message":"Found non-literal argument in require","line":591,"column":21,"nodeType":"CallExpression","endLine":591,"endColumn":62},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":605,"column":1,"nodeType":"Block","endLine":605,"endColumn":1},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'jQuery.Promise' is undefined.","line":630,"column":1,"nodeType":"Block","endLine":630,"endColumn":1}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Creates and controls the UI for the extension.\n *\n * @class ext.wikispeech.Ui\n * @constructor\n */\nconst util = require( './ext.wikispeech.util.js' );\n\nclass Ui {\n\tconstructor() {\n\t// Resolves the UI is ready to be extended by consumer.\n\t\tthis.ready = $.Deferred();\n\t\tthis.selectionPlayer = null;\n\t\tthis.player = null;\n\t\tthis.storage = null;\n\t\tthis.highlighter = null;\n\t\tthis.selectionPlayer = null;\n\t}\n\n\t/**\n\t * Initialize elements and functionality for the UI.\n\t */\n\n\tinit() {\n\t\tthis.addSelectionPlayer();\n\t\tthis.addControlPanel();\n\t\tthis.addKeyboardShortcuts();\n\t\tthis.windowManager = new OO.ui.WindowManager();\n\t\tthis.addDialogs();\n\t\tthis.loadErrorAudio();\n\t\tthis.ready.resolve();\n\t}\n\n\t/**\n\t * Add a panel with controls for for Wikispeech.\n\t *\n\t * The panel contains buttons for controlling playback and\n\t * links to related pages.\n\t */\n\n\taddControlPanel() {\n\t\tconst toolFactory = new OO.ui.ToolFactory();\n\t\tconst toolGroupFactory = new OO.ui.ToolGroupFactory();\n\t\tthis.toolbar = new OO.ui.Toolbar(\n\t\t\ttoolFactory,\n\t\t\ttoolGroupFactory,\n\t\t\t{\n\t\t\t\tactions: true,\n\t\t\t\tclasses: [ 'ext-wikispeech-control-panel' ],\n\t\t\t\tposition: 'bottom'\n\t\t\t}\n\t\t);\n\n\t\tconst playerGroupPlayStop = this.addToolbarGroup();\n\t\tthis.playPauseButton = this.addButton(\n\t\t\tplayerGroupPlayStop,\n\t\t\t() => this.player.playOrPause(),\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-play' ),\n\t\t\t\ticon: 'play',\n\t\t\t\tflags: [\n\t\t\t\t\t'primary',\n\t\t\t\t\t'progressive'\n\t\t\t\t]\n\t\t\t}\n\t\t);\n\t\tthis.addButton(\n\t\t\tplayerGroupPlayStop,\n\t\t\t() => this.player.stop(),\n\t\t\t// TODO: add destructive flag when\n\t\t\t// https://gerrit.wikimedia.org/r/c/1194133 is done.\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-stop' ),\n\t\t\t\ticon: 'stop'\n\t\t\t}\n\t\t);\n\t\tconst playerGroup = this.addToolbarGroup();\n\t\tthis.addButton(\n\t\t\tplayerGroup,\n\t\t\t() => this.player.skipBackUtterance(),\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-skip-back' ),\n\t\t\t\ticon: 'doubleChevronStart'\n\t\t\t}\n\t\t);\n\t\tthis.addButton(\n\t\t\tplayerGroup,\n\t\t\t() => this.player.skipBackToken(),\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-skip-back' ),\n\t\t\t\ticon: 'previous'\n\t\t\t}\n\t\t);\n\t\tthis.addButton(\n\t\t\tplayerGroup,\n\t\t\t() => this.player.skipAheadToken(),\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-next' ),\n\t\t\t\ticon: 'next'\n\t\t\t}\n\t\t);\n\t\tthis.addButton(\n\t\t\tplayerGroup,\n\t\t\t() => this.player.skipAheadUtterance(),\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-skip-ahead' ),\n\t\t\t\ticon: 'doubleChevronEnd'\n\t\t\t}\n\t\t);\n\n\t\tthis.linkGroup = this.addToolbarGroup();\n\t\tthis.addLinkConfigButton(\n\t\t\tthis.linkGroup,\n\t\t\t'help',\n\t\t\t'wgWikispeechHelpPage',\n\t\t\tmw.msg( 'wikispeech-help' )\n\t\t);\n\t\tthis.addLinkConfigButton(\n\t\t\tthis.linkGroup,\n\t\t\t'feedback',\n\t\t\t'wgWikispeechFeedbackPage',\n\t\t\tmw.msg( 'wikispeech-feedback' )\n\n\t\t);\n\t\tconst api = new mw.Api();\n\t\tapi.getUserInfo()\n\t\t\t.done( ( info ) => {\n\t\t\t\tconst canEditLexicon = info.rights.includes( 'wikispeech-edit-lexicon' );\n\t\t\t\tif ( !canEditLexicon ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.addEditButton();\n\t\t\t} );\n\n\t\t$( document.body ).append( this.toolbar.$element );\n\t\tthis.toolbar.initialize();\n\n\t\t// Add extra padding at the bottom of the page to not have\n\t\t// the player cover anything.\n\t\tconst height = this.toolbar.$element.height();\n\t\tthis.$playerFooter = $( '<div>' )\n\t\t\t.height( height )\n\t\t\t// A bit of CSS is needed to make it interact properly\n\t\t\t// with the other floating elements in the footer.\n\t\t\t.css( {\n\t\t\t\tfloat: 'left',\n\t\t\t\twidth: '100%'\n\t\t\t} )\n\t\t\t.appendTo( '#footer' );\n\t\tthis.addBufferingIcon();\n\t}\n\n\t/**\n\t * Add button that takes the user to the lexicon editor.\n\t *\n\t * @param {string} If given, this is used to build the URL for\n\t * the editor page. It should be the URL to the script\n\t * endpoint of a wiki, i.e. \"...index.php\". If not given the\n\t * link will go to the page on the local wiki.\n\t */\n\n\taddEditButton( scriptUrl, consumerUrl ) {\n\t\tlet editUrl;\n\t\tif ( scriptUrl ) {\n\t\t\teditUrl = scriptUrl;\n\t\t} else {\n\t\t\teditUrl = mw.config.get( 'wgScript' );\n\t\t}\n\t\tconst params = {\n\t\t\ttitle: 'Special:EditLexicon',\n\t\t\tlanguage: mw.config.get( 'wgPageContentLanguage' ),\n\t\t\tpage: mw.config.get( 'wgArticleId' )\n\t\t};\n\n\t\tif ( consumerUrl ) {\n\t\t\tparams.consumerUrl = consumerUrl;\n\t\t}\n\n\t\teditUrl += '?' + new URLSearchParams( params );\n\n\t\tthis.addButton(\n\t\t\tthis.linkGroup,\n\t\t\teditUrl,\n\t\t\t{\n\t\t\t\ttitle: mw.msg( 'wikispeech-edit-lexicon-btn' ),\n\t\t\t\ticon: 'edit',\n\t\t\t\tid: 'wikispeech-edit'\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Add a group to the player toolbar.\n\t *\n\t * @return {OO.ui.ButtonGroupWidget}\n\t */\n\n\taddToolbarGroup() {\n\t\tconst group = new OO.ui.ButtonGroupWidget();\n\t\tthis.toolbar.$actions.append( group.$element );\n\t\treturn group;\n\t}\n\n\t/**\n\t * Add a control button.\n\t *\n\t * @param {OO.ui.ButtonGroupWidget} group Group to add button to.\n\t * @param {Function|string} onClick Function to call or link.\n\t * @param {string} label Labels, such as aria labels and titles\n\t * @param {Object} config Configuration for the button widget.\n\t * `title` is also used as `aria-label` attribute.\n\t * See {@link OO.ui.ButtonWidget}.\n\t * @return {OO.ui.ButtonWidget}\n\t */\n\n\taddButton( group, onClick, config ) {\n\t\tconfig = config || {};\n\t\tconst button = new OO.ui.ButtonWidget( config );\n\t\tif ( typeof onClick === 'function' ) {\n\t\t\tbutton.on( 'click', onClick );\n\t\t} else if ( typeof onClick === 'string' ) {\n\t\t\tbutton.setHref( onClick );\n\t\t\t// Open link in new tab or window.\n\t\t\tbutton.setTarget( '_blank' );\n\t\t}\n\t\tif ( config.title ) {\n\t\t\tbutton.$element.find( 'a' ).attr( 'aria-label', config.title );\n\t\t}\n\t\tgroup.addItems( [ button ] );\n\t\treturn button;\n\t}\n\n\t/**\n\t * Add buffering icon to the play/pause button.\n\t *\n\t * The icon shows when the waiting for audio to play.\n\t */\n\taddBufferingIcon() {\n\t\tconst $playPauseButtons = $().add( this.playPauseButton.$element ).add( this.selectionPlayer.button.$element );\n\t\tconst $containers = $( '<span>' )\n\t\t\t.addClass( 'ext-wikispeech-buffering-icon-container' )\n\t\t\t.appendTo( ( $playPauseButtons ).find( '.oo-ui-iconElement-icon' ) );\n\t\tthis.$bufferingIcons = $( '<span>' )\n\t\t\t.addClass( 'ext-wikispeech-buffering-icon' )\n\t\t\t.appendTo( $containers )\n\t\t\t.hide();\n\t}\n\n\t/**\n\t * Hide the buffering icon.\n\t */\n\n\thideBufferingIcon() {\n\t\tthis.$bufferingIcons.hide();\n\t}\n\n\t/**\n\t * Show the buffering icon if the current audio is loading.\n\t */\n\n\tshowBufferingIconIfAudioIsLoading( audio ) {\n\t\tif ( this.audioIsReady( audio ) ) {\n\t\t\tthis.hideBufferingIcon();\n\t\t} else {\n\t\t\t$( audio ).on( 'canplay', () => {\n\t\t\t\tthis.hideBufferingIcon();\n\t\t\t} );\n\t\t\tthis.$bufferingIcons.show();\n\t\t}\n\t}\n\n\t/**\n\t * Check if the current audio is ready to play.\n\t *\n\t * The audio is deemed ready to play as soon as any playable\n\t * data is available.\n\t *\n\t * @param {HTMLElement} audio The audio element to test.\n\t * @return {boolean} True if the audio is ready to play else false.\n\t */\n\n\taudioIsReady( audio ) {\n\t\treturn audio.readyState >= 2;\n\t}\n\n\t/**\n\t * Remove canplay listener for the audio to hide buffering icon.\n\t *\n\t * @param {jQuery} $audioElement Audio element from which the\n\t * listener is removed.\n\t */\n\n\tremoveCanPlayListener( $audioElement ) {\n\t\t$audioElement.off( 'canplay' );\n\t}\n\n\t/**\n\t * Change the icon of the play/pause button to pause.\n\t */\n\n\tsetPlayPauseIconToPause() {\n\t\tthis.playPauseButton.setIcon( 'pause' );\n\t\tthis.playPauseButton.setTitle( mw.msg( 'wikispeech-pause' ) );\n\t\tthis.playPauseButton.$element.find( 'a' ).attr( 'aria-label', mw.msg( 'wikispeech-pause' ) );\n\t}\n\n\t/**\n\t * Change the icon of the play/pause button to play.\n\t */\n\n\tsetAllPlayerIconsToPlay() {\n\t\tthis.playPauseButton.setIcon( 'play' );\n\t\tthis.playPauseButton.setTitle( mw.msg( 'wikispeech-play' ) );\n\t\tthis.playPauseButton.$element.find( 'a' ).attr( 'aria-label', mw.msg( 'wikispeech-play' ) );\n\t\tthis.selectionPlayer.button.setIcon( 'play' );\n\t}\n\n\t/**\n\t * Change the icon of the selectionPlayer to stop.\n\t */\n\n\tsetSelectionPlayerIconToStop() {\n\t\tthis.selectionPlayer.button.setIcon( 'stop' );\n\t\tthis.selectionPlayer.button.setTitle( mw.msg( 'wikispeech-stop' ) );\n\t\tthis.selectionPlayer.button.$element.find( 'a' ).attr( 'aria-label', mw.msg( 'wikispeech-stop' ) );\n\n\t}\n\t/**\n\t * Add a button that takes the user to another page.\n\t *\n\t * The button gets the link destination from a supplied\n\t * config variable. If the variable isn't specified, the button\n\t * isn't added.\n\t *\n\t * @param {OO.ui.ButtonGroupWidget} group Group to add button to.\n\t * @param {string} icon Name of button icon.\n\t * @param {string} configVariable The config variable to get\n\t * link destination from.\n\t * @param {string} label Label for aria labels and titles\n\t */\n\n\taddLinkConfigButton( group, icon, configVariable, label ) {\n\t\tconst url = mw.config.get( configVariable );\n\t\tif ( url ) {\n\t\t\tthis.addButton( group, url, { title: label, icon: icon } );\n\t\t}\n\t}\n\n\t/**\n\t * Add a small player that appears when text is selected.\n\t */\n\n\taddSelectionPlayer() {\n\t\tconst label = mw.msg( 'wikispeech-play-selection' );\n\t\tconst selectionButton = new OO.ui.ButtonWidget( {\n\t\t\ticon: 'play',\n\t\t\tclasses: [ 'ext-wikispeech-selection-player' ],\n\t\t\ttitle: label\n\t\t} );\n\t\tselectionButton.$element.find( 'a' ).attr( 'aria-label', label );\n\t\tselectionButton.on( 'click', () => this.player.playOrStop() );\n\t\tthis.selectionPlayer.button = selectionButton;\n\t\tthis.selectionPlayer.button.toggle( false );\n\t\t$( document.body ).append( this.selectionPlayer.button.$element );\n\t\t$( document ).on( 'mouseup', () => {\n\t\t\tif (\n\t\t\t\tthis.isShown() &&\n\t\t\t\tthis.selectionPlayer.isSelectionValid()\n\t\t\t) {\n\t\t\t\tthis.showSelectionPlayer();\n\t\t\t} else {\n\t\t\t\tthis.selectionPlayer.button.toggle( false );\n\t\t\t}\n\t\t} );\n\t\t$( document ).on( 'click', () => {\n\t\t\t// A click listener is also needed because of the\n\t\t\t// order of events when text is deselected by clicking\n\t\t\t// it.\n\t\t\tif ( !this.selectionPlayer.isSelectionValid() ) {\n\t\t\t\tthis.selectionPlayer.button.toggle( false );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Check if control panel is shown\n\t *\n\t * @return {boolean} Visibility of control panel.\n\t */\n\n\tisShown() {\n\t\treturn this.toolbar.isVisible();\n\t}\n\n\t/**\n\t * Show the selection player below the end of the selection.\n\t */\n\n\tshowSelectionPlayer() {\n\n\t\tthis.selectionPlayer.button.toggle( true );\n\t\tconst selection = window.getSelection();\n\t\tconst lastRange = selection.getRangeAt( selection.rangeCount - 1 );\n\t\tconst lastRect =\n\t\t\tutil.getLast( lastRange.getClientRects() );\n\n\t\t// Place the player under the end of the selected text.\n\t\tlet left;\n\t\tif ( this.getTextDirection( lastRange.endContainer ) === 'rtl' ) {\n\t\t\t// For RTL languages, the end of the text is the far left.\n\t\t\tleft = lastRect.left + $( document ).scrollLeft();\n\t\t} else {\n\t\t\t// For LTR languages, the end of the text is the far\n\t\t\t// right. This is the default value for the direction\n\t\t\t// property.\n\t\t\tleft =\n\t\t\t\tlastRect.right +\n\t\t\t\t$( document ).scrollLeft() -\n\t\t\t\tthis.selectionPlayer.button.$element.width();\n\t\t}\n\t\tconst top = lastRect.bottom + $( document ).scrollTop();\n\t\tthis.selectionPlayer.button.$element.css( {\n\t\t\tleft: left + 'px',\n\t\t\ttop: top + 'px'\n\t\t} );\n\t}\n\n\t/**\n\t * Get the text direction for a node.\n\t *\n\t * @return {string} The CSS value of the `direction` property\n\t * for the node, or for its parent if it is a text node.\n\t */\n\n\tgetTextDirection( node ) {\n\t\tif ( node.nodeType === 3 ) {\n\t\t\t// For text nodes, get the property of the parent element.\n\t\t\treturn $( node ).parent().css( 'direction' );\n\t\t} else {\n\t\t\treturn $( node ).css( 'direction' );\n\t\t}\n\t}\n\n\t/**\n\t * Register listeners for keyboard shortcuts.\n\t */\n\n\taddKeyboardShortcuts() {\n\t\tconst shortcuts = mw.config.get( 'wgWikispeechKeyboardShortcuts' );\n\t\t$( document ).on( 'keydown', ( event ) => {\n\t\t\tif ( this.eventMatchShortcut( event, shortcuts.playPause ) ) {\n\t\t\t\tthis.player.playOrPause();\n\t\t\t\treturn false;\n\t\t\t} else if (\n\t\t\t\tthis.eventMatchShortcut(\n\t\t\t\t\tevent,\n\t\t\t\t\tshortcuts.stop\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthis.player.stop();\n\t\t\t\treturn false;\n\t\t\t} else if (\n\t\t\t\tthis.eventMatchShortcut(\n\t\t\t\t\tevent,\n\t\t\t\t\tshortcuts.skipAheadSentence\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthis.player.skipAheadUtterance();\n\t\t\t\treturn false;\n\t\t\t} else if (\n\t\t\t\tthis.eventMatchShortcut(\n\t\t\t\t\tevent,\n\t\t\t\t\tshortcuts.skipBackSentence\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthis.player.skipBackUtterance();\n\t\t\t\treturn false;\n\t\t\t} else if (\n\t\t\t\tthis.eventMatchShortcut( event, shortcuts.skipAheadWord )\n\t\t\t) {\n\t\t\t\tthis.player.skipAheadToken();\n\t\t\t\treturn false;\n\t\t\t} else if (\n\t\t\t\tthis.eventMatchShortcut( event, shortcuts.skipBackWord )\n\t\t\t) {\n\t\t\t\tthis.player.skipBackToken();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\t\t// Prevent keyup events from triggering if there is\n\t\t// keydown event for the same key combination. This caused\n\t\t// buttons in focus to trigger if a shortcut had space as\n\t\t// key.\n\t\t$( document ).on( 'keyup', ( event ) => {\n\t\t\tfor ( const name in shortcuts ) {\n\t\t\t\tconst shortcut = shortcuts[ name ];\n\t\t\t\tif ( this.eventMatchShortcut( event, shortcut ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Check if a keydown event matches a shortcut from the\n\t * configuration.\n\t *\n\t * Compare the key and modifier state (of ctrl, alt and shift)\n\t * for an event, to those of a shortcut from the\n\t * configuration.\n\t *\n\t * @param {Event} event The event to compare.\n\t * @param {Object} shortcut The shortcut object from the\n\t * config to compare to.\n\t * @return {boolean} true if key and all the modifiers match\n\t * with the shortcut, else false.\n\t */\n\n\teventMatchShortcut( event, shortcut ) {\n\t\treturn event.which === shortcut.key &&\n\t\t\tevent.ctrlKey === shortcut.modifiers.includes( 'ctrl' ) &&\n\t\t\tevent.altKey === shortcut.modifiers.includes( 'alt' ) &&\n\t\t\tevent.shiftKey === shortcut.modifiers.includes( 'shift' );\n\t}\n\n\t/**\n\t * Create dialogs and add them to a window manager\n\t */\n\n\taddDialogs() {\n\t\t$( document.body ).append( this.windowManager.$element );\n\t\tthis.messageDialog = new OO.ui.MessageDialog();\n\t\tthis.errorLoadAudioDialogData = {\n\t\t\ttitle: mw.msg( 'wikispeech-error-loading-audio-title' ),\n\t\t\tmessage: mw.msg( 'wikispeech-error-loading-audio-message' ),\n\t\t\tactions: [\n\t\t\t\t{\n\t\t\t\t\taction: 'retry',\n\t\t\t\t\tlabel: mw.msg( 'wikispeech-retry' ),\n\t\t\t\t\tflags: 'primary'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\taction: 'stop',\n\t\t\t\t\tlabel: mw.msg( 'wikispeech-stop' ),\n\t\t\t\t\tflags: 'destructive'\n\t\t\t\t}\n\t\t\t]\n\t\t};\n\t\tthis.addWindow( this.messageDialog );\n\t}\n\n\t/**\n\t * Add a window to the window manager.\n\t *\n\t * @param {OO.ui.Window} window\n\t */\n\n\taddWindow( window ) {\n\t\tthis.windowManager.addWindows( [ window ] );\n\t}\n\n\t/**\n\t * Toggle GUI visibility\n\t *\n\t * Hides or shows control panel which also dictates whether\n\t * the selection player should be shown.\n\t */\n\n\ttoggleVisibility() {\n\t\tif ( this.isShown() ) {\n\t\t\tthis.toolbar.toggle( false );\n\t\t\tthis.selectionPlayer.button.toggle( false );\n\t\t\tthis.$playerFooter.hide();\n\t\t} else {\n\t\t\tthis.toolbar.toggle( true );\n\t\t\tthis.selectionPlayer.button.toggle( true );\n\t\t\tthis.$playerFooter.show();\n\t\t}\n\t}\n\n\t/**\n\t * Loads the error audio once and calls it in init()\n\t */\n\n\tloadErrorAudio() {\n\t\tconst lang = mw.config.get( 'wgUserLanguage' ) || 'en';\n\t\tlet errorAudioData;\n\n\t\ttry {\n\t\t\terrorAudioData = require( `./audio/error.${ lang }.json` );\n\t\t} catch ( e ) {\n\t\t\terrorAudioData = require( './audio/error.en.json' );\n\t\t}\n\t\tconst src = 'data:audio/ogg;base64,' + errorAudioData[ 'wikispeech-listen' ].audio;\n\n\t\tthis.errorAudio = new Audio( src );\n\t}\n\n\t/**\n\t * Show an error dialog for when audio could not be loaded\n\t *\n\t * Has buttons for retrying and stopping playback.\n\t *\n\t * @return {jQuery.Promise} Resolves when dialog is closed.\n\t */\n\n\tshowLoadAudioError() {\n\t\tif ( this.errorAudio ) {\n\t\t\tthis.errorAudio.play();\n\t\t}\n\n\t\treturn this.openWindow(\n\t\t\tthis.messageDialog,\n\t\t\tthis.errorLoadAudioDialogData\n\t\t).then( ( data ) => {\n\t\t\tif ( this.errorAudio ) {\n\t\t\t\tthis.errorAudio.pause();\n\t\t\t\tthis.errorAudio.currentTime = 0;\n\t\t\t}\n\t\t\treturn data;\n\t\t} );\n\t}\n\n\t/**\n\t * Open a window.\n\t *\n\t * @param {OO.ui.Window} window\n\t * @param {Object} data\n\t * @return {jQuery.Promise} Resolves when window is closed.\n\t */\n\n\topenWindow( window, data ) {\n\t\treturn this.windowManager.openWindow( window, data ).closed;\n\t}\n}\n\nmodule.exports = Ui;\n","usedDeprecatedRules":[{"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/ext.wikispeech.userOptionsDialog.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":84,"column":3,"nodeType":"CallExpression","endLine":104,"endColumn":6}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Popup dialog for Wikispeech user options.\n *\n * Replaces the normal user options when running on\n * consumer wiki.\n *\n * @class ext.wikispeech.UserOptionsDialog\n */\n\nconst util = require( './ext.wikispeech.util.js' );\n\nclass UserOptionsDialog extends OO.ui.ProcessDialog {\n\tconstructor( config ) {\n\t\tsuper( config );\n\n\t\tthis.languageSelect = null;\n\t\tthis.voiceSelect = null;\n\t\tthis.speechRateInput = null;\n\t}\n\n\tinitialize() {\n\t\tsuper.initialize();\n\t\tconst panel = new OO.ui.PanelLayout( { padded: true, expanded: false } );\n\t\tconst content = new OO.ui.FieldsetLayout();\n\t\tconst voiceFieldset = this.addVoiceFieldset();\n\n\t\t// Add input field for speech rate, shown in percent.\n\t\tthis.speechRateInput = new OO.ui.NumberInputWidget( {\n\t\t\tmin: 0,\n\t\t\tstep: 25,\n\t\t\tvalue: mw.user.options.get( 'wikispeechSpeechRate' ) * 100\n\t\t} );\n\t\tconst speechRateFieldset = new OO.ui.FieldsetLayout( {\n\t\t\tlabel: mw.msg( 'prefs-wikispeech-speech-rate-percent' )\n\t\t} );\n\t\tconst speechRateField = new OO.ui.FieldLayout( this.speechRateInput );\n\t\tspeechRateFieldset.addItems( [ speechRateField ] );\n\n\t\t// Add a notice about needing to reload the page before\n\t\t// preferences kick in.\n\t\tconst notice = new OO.ui.MessageWidget( {\n\t\t\ttype: 'notice',\n\t\t\tlabel: mw.msg( 'wikispeech-notice-prefs-apply-on-next-page-load' )\n\t\t} );\n\t\tconst noticeFieldset = new OO.ui.FieldsetLayout();\n\t\tnoticeFieldset.addItems( [ new OO.ui.FieldLayout( notice ) ] );\n\n\t\tcontent.addItems( [\n\t\t\tvoiceFieldset,\n\t\t\tspeechRateFieldset,\n\t\t\tnoticeFieldset\n\t\t] );\n\t\tpanel.$element.append( content.$element );\n\t\tthis.$body.append( panel.$element );\n\t}\n\n\t/**\n\t * Add fields for selecting voice.\n\t *\n\t * Adds two fields: language and voice. When a language is\n\t * selected, the voice is populated by the available voices for\n\t * that language. Language defaults to the language of the current\n\t * page. Voices are labeled with language code and autonym.\n\t *\n\t * @return {OO.ui.FieldsetLayout}\n\t */\n\n\taddVoiceFieldset() {\n\t\tconst voices = mw.config.get( 'wgWikispeechVoices' );\n\t\tconst languageItems = [];\n\t\tconst languageCodes = Object.keys( voices );\n\t\tlanguageCodes.sort();\n\t\tlanguageCodes.forEach( ( language ) => {\n\t\t\tlanguageItems.push(\n\t\t\t\tnew OO.ui.MenuOptionWidget( {\n\t\t\t\t\tdata: language,\n\t\t\t\t\tlabel: language\n\t\t\t\t} )\n\t\t\t);\n\t\t} );\n\t\t// Add autonyms to labels. Do this separately to not break if\n\t\t// the request fails. If it does, we still have the language\n\t\t// codes as labels.\n\t\tnew mw.Api().get( {\n\t\t\taction: 'query',\n\t\t\tformat: 'json',\n\t\t\tformatversion: 2,\n\t\t\tmeta: 'languageinfo',\n\t\t\tliprop: 'autonym',\n\t\t\tlicode: languageCodes\n\t\t} ).done( ( response ) => {\n\t\t\tconst info = response.query.languageinfo;\n\t\t\tObject.keys( info ).forEach( ( code ) => {\n\t\t\t\tlanguageItems.forEach( ( item ) => {\n\t\t\t\t\tif ( item.label === code ) {\n\t\t\t\t\t\titem.setLabel( code + ' - ' + info[ code ].autonym );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\t\t\t// Reselect the language to show the new label.\n\t\t\tthis.languageSelect.getMenu().selectItemByData(\n\t\t\t\tmw.config.get( 'wgPageContentLanguage' )\n\t\t\t);\n\t\t} );\n\t\tthis.languageSelect = new OO.ui.DropdownWidget( {\n\t\t\tmenu: {\n\t\t\t\titems: languageItems\n\t\t\t}\n\t\t} );\n\n\t\tthis.voiceSelect = new OO.ui.DropdownWidget();\n\t\t// Update the voice items when language is selected.\n\t\tthis.languageSelect.getMenu().on( 'select', ( item ) => {\n\t\t\tconst voiceItems = [\n\t\t\t\tnew OO.ui.MenuOptionWidget( {\n\t\t\t\t\tdata: '',\n\t\t\t\t\tlabel: mw.msg( 'default' )\n\t\t\t\t} )\n\t\t\t];\n\t\t\tconst language = item.data;\n\t\t\tvoices[ language ].forEach( ( voice ) => {\n\t\t\t\tvoiceItems.push(\n\t\t\t\t\tnew OO.ui.MenuOptionWidget( {\n\t\t\t\t\t\tdata: voice,\n\t\t\t\t\t\tlabel: voice\n\t\t\t\t\t} )\n\t\t\t\t);\n\t\t\t} );\n\t\t\tthis.voiceSelect.getMenu().clearItems();\n\t\t\tthis.voiceSelect.getMenu().addItems( voiceItems );\n\t\t\tconst currentVoice = util.getUserVoice( language );\n\t\t\tthis.voiceSelect.getMenu().selectItemByData( currentVoice );\n\t\t} );\n\t\t// Select the language for the current page, since that is\n\t\t// probably the one the user is interested in.\n\t\tthis.languageSelect.getMenu().selectItemByData(\n\t\t\tmw.config.get( 'wgPageContentLanguage' )\n\t\t);\n\n\t\tconst fieldset = new OO.ui.FieldsetLayout(\n\t\t\t{ label: mw.msg( 'prefs-wikispeech-voice' ) }\n\t\t);\n\t\tconst languageField = new OO.ui.FieldLayout(\n\t\t\tthis.languageSelect,\n\t\t\t{ label: mw.msg( 'wikispeech-language' ) }\n\t\t);\n\t\tconst voiceField = new OO.ui.FieldLayout(\n\t\t\tthis.voiceSelect,\n\t\t\t{ label: mw.msg( 'prefs-wikispeech-voice' ) }\n\t\t);\n\t\tfieldset.addItems( [ languageField, voiceField ] );\n\t\treturn fieldset;\n\t}\n\n\t/**\n\t * Handle actions.\n\t *\n\t * Closes the dialog when \"Save\" is clicked.\n\t *\n\t * @param {Object} action\n\t * @return {OO.ui.Process}\n\t */\n\n\tgetActionProcess( action ) {\n\t\tif ( action ) {\n\t\t\treturn new OO.ui.Process( () => {\n\t\t\t\tthis.close( { action: action } );\n\t\t\t} );\n\t\t}\n\t\treturn UserOptionsDialog.super.prototype.getActionProcess.call( this, action );\n\t}\n\n\t/**\n\t * Get the selected language and voice.\n\t *\n\t * @return {Object}\n\t * @return {string} return.variable User option variable name.\n\t * @return {string} return.voice Name of voice.\n\t */\n\n\tgetVoice() {\n\t\tconst language = this.languageSelect.getMenu().findSelectedItem().data;\n\t\tconst voiceVariable = util.getVoiceConfigVariable( language );\n\t\tconst voice = this.voiceSelect.getMenu().findSelectedItem().data;\n\t\treturn { variable: voiceVariable, voice: voice };\n\t}\n\n\t/**\n\t * Get the selected speech rate.\n\t *\n\t * @return {number} Speech rate as a decimal number, i.e. 100% =\n\t * 1.0.\n\t */\n\n\tgetSpeechRate() {\n\t\treturn this.speechRateInput.value / 100;\n\t}\n}\n\nUserOptionsDialog.static.name = 'UserOptionsDialog';\nUserOptionsDialog.static.title = mw.msg( 'preferences' );\nUserOptionsDialog.static.actions = [\n\t{\n\t\taction: 'save',\n\t\tlabel: mw.msg( 'saveprefs' ),\n\t\tflags: [ 'primary', 'progressive' ]\n\t},\n\t{\n\t\tflags: [ 'safe', 'close' ]\n\t}\n];\n\nmodule.exports = UserOptionsDialog;\n","usedDeprecatedRules":[{"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/ext.wikispeech.util.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/sql/abstractSchemaChanges/patch-wikispeech_utterance-wsu_date_stored.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/sql/abstractSchemaChanges/patch-wikispeech_utterance-wsu_message_key.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/sql/tables.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/qunit/.eslintrc.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.highlighter.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.player.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.selectionPlayer.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.storage.test.js","messages":[],"suppressedMessages":[{"ruleId":"no-jquery/no-parse-html-literal","severity":2,"message":"Prefer DOM building to parsing HTML literals","line":40,"column":56,"nodeType":"CallExpression","endLine":40,"endColumn":76,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-parse-html-literal","severity":2,"message":"Prefer DOM building to parsing HTML literals","line":88,"column":56,"nodeType":"CallExpression","endLine":88,"endColumn":76,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-parse-html-literal","severity":2,"message":"Prefer DOM building to parsing HTML literals","line":118,"column":56,"nodeType":"CallExpression","endLine":118,"endColumn":76,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-parse-html-literal","severity":2,"message":"Prefer DOM building to parsing HTML literals","line":148,"column":56,"nodeType":"CallExpression","endLine":148,"endColumn":79,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.test.util.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.transcriptionPreviewer.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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/ext.wikispeech.ui.test.js","messages":[{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'QUnit.assert' is undefined.","line":339,"column":1,"nodeType":"Block","endLine":339,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"const Ui = require( 'ext.wikispeech/ext.wikispeech.ui.js' );\nconst Player = require( 'ext.wikispeech/ext.wikispeech.player.js' );\nconst SelectionPlayer = require( 'ext.wikispeech/ext.wikispeech.selectionPlayer.js' );\nconst util = require( './ext.wikispeech.test.util.js' );\n\nQUnit.module( 'ext.wikispeech.ui', QUnit.newMwEnvironment( {\n\tbeforeEach: function () {\n\t\tthis.ui = new Ui();\n\t\tthis.ui.player = sinon.createStubInstance( Player );\n\t\tthis.selectionPlayer = sinon.stub( new SelectionPlayer() );\n\t\tthis.ui.selectionPlayer = this.selectionPlayer;\n\t\t$( '#qunit-fixture' ).append(\n\t\t\t$( '<div>' ).attr( 'id', 'content' ),\n\t\t\t$( '<div>' ).attr( 'id', 'footer' )\n\t\t);\n\t\tthis.contentSelector = '#mw-content-text';\n\t\tmw.config.set( 'wgWikispeechContentSelector', this.contentSelector );\n\n\t\t/**\n\t\t * Stub window.getSelection\n\t\t *\n\t\t * @param {Node} startContainer Node where selection starts.\n\t\t * @param {Node} endContainer Node where selection ends.\n\t\t * @param {DOMRect} rect The selection rectangle.\n\t\t */\n\t\tthis.stubGetSelection = ( startContainer, endContainer, rect ) => {\n\t\t\tthis.sandbox.stub( window, 'getSelection' ).returns( {\n\t\t\t\trangeCount: 1,\n\t\t\t\tgetRangeAt: function () {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tgetClientRects: function () {\n\t\t\t\t\t\t\treturn [ rect ];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstartContainer: startContainer,\n\t\t\t\t\t\tendContainer: endContainer\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t},\n\tafterEach: function () {\n\t\t// Remove the event listeners to not trigger them after\n\t\t// the tests have run.\n\t\t$( document ).off( 'mouseup' );\n\t\t$( '#qunit-fixture' ).empty();\n\t\t$( '.ext-wikispeech-control-panel, .ext-wikispeech-selection-player' ).remove();\n\t}\n} ) );\n\nQUnit.test( 'addControlPanel(): add help button if page is set', function ( assert ) {\n\tmw.config.set( 'wgArticlePath', '/wiki/$1' );\n\tmw.config.set( 'wgWikispeechHelpPage', 'Help' );\n\tsinon.stub( this.ui, 'addBufferingIcon' );\n\n\tthis.ui.addControlPanel();\n\n\tassert.strictEqual(\n\t\t$( '.ext-wikispeech-control-panel' )\n\t\t\t.find( '.oo-ui-buttonElement-button[href=\"./Help\"]' )\n\t\t\t.length,\n\t\t1\n\t);\n} );\n\nQUnit.test( 'addControlPanel(): add feedback button', function ( assert ) {\n\tmw.config.set( 'wgArticlePath', '/wiki/$1' );\n\tmw.config.set( 'wgWikispeechFeedbackPage', 'Feedback' );\n\tsinon.stub( this.ui, 'addBufferingIcon' );\n\n\tthis.ui.addControlPanel();\n\n\tassert.strictEqual(\n\t\t$( '.ext-wikispeech-control-panel' )\n\t\t\t.find( '.oo-ui-buttonElement-button[href=\"./Feedback\"]' )\n\t\t\t.length,\n\t\t1\n\t);\n} );\n\nQUnit.test( 'addEditButton(): add edit button with link to local URL', function () {\n\tmw.config.set( 'wgPageContentLanguage', 'en' );\n\tmw.config.set( 'wgArticleId', 1 );\n\tmw.config.set( 'wgScript', '/wiki/index.php' );\n\n\tthis.ui.linkGroup = sinon.stub( new OO.ui.ButtonGroupWidget() );\n\tconst addButton = sinon.stub( this.ui, 'addButton' );\n\n\tthis.ui.addEditButton();\n\n\tsinon.assert.calledWith(\n\t\taddButton,\n\t\tthis.ui.linkGroup,\n\t\t// The colon in \"Special:EditLexicon\" is URL encoded, see:\n\t\t// https://url.spec.whatwg.org/#concept-urlencoded-serializer.\n\t\t'/wiki/index.php?title=Special%3AEditLexicon&language=en&page=1',\n\t\t{\n\t\t\ttitle: mw.msg( 'wikispeech-edit-lexicon-btn' ),\n\t\t\ticon: 'edit',\n\t\t\tid: 'wikispeech-edit'\n\t\t}\n\t);\n} );\n\nQUnit.test( 'addEditButton(): add edit button with link to given script URL', function () {\n\tmw.config.set( 'wgWikispeechAllowConsumerEdits', true );\n\tmw.config.set( 'wgPageContentLanguage', 'en' );\n\tmw.config.set( 'wgArticleId', 1 );\n\tthis.ui.linkGroup = sinon.stub( new OO.ui.ButtonGroupWidget() );\n\tconst addButton = sinon.stub( this.ui, 'addButton' );\n\n\tthis.ui.addEditButton( 'http://producer.url/w/index.php' );\n\n\tsinon.assert.calledWith(\n\t\taddButton,\n\t\tthis.ui.linkGroup,\n\t\t// The colon in \"Special:EditLexicon\" is URL encoded, see:\n\t\t// https://url.spec.whatwg.org/#concept-urlencoded-serializer.\n\t\t'http://producer.url/w/index.php?title=Special%3AEditLexicon&language=en&page=1',\n\t\t{\n\t\t\ttitle: mw.msg( 'wikispeech-edit-lexicon-btn' ),\n\t\t\ticon: 'edit',\n\t\t\tid: 'wikispeech-edit'\n\t\t}\n\t);\n} );\n\nQUnit.test( 'addEditButton(): add edit button with link to given script URL, with consumerUrl parameter', function () {\n\tmw.config.set( 'wgWikispeechAllowConsumerEdits', true );\n\tmw.config.set( 'wgPageContentLanguage', 'en' );\n\tmw.config.set( 'wgArticleId', 1 );\n\tmw.config.set( 'wgScriptPath', '/' );\n\n\tthis.ui.linkGroup = this.sandbox.stub( new OO.ui.ButtonGroupWidget() );\n\tconst addButton = this.sandbox.stub( this.ui, 'addButton' );\n\n\tconst scriptUrl = 'http://producer.url/w/index.php';\n\tconst consumerUrl = window.location.origin + '/';\n\n\tthis.ui.addEditButton( scriptUrl, consumerUrl );\n\tconst expectedUrl = scriptUrl + '?' + new URLSearchParams( {\n\t\ttitle: 'Special:EditLexicon',\n\t\tlanguage: 'en',\n\t\tpage: 1,\n\t\tconsumerUrl: consumerUrl\n\t} ).toString();\n\n\tsinon.assert.calledWith(\n\t\taddButton,\n\t\tthis.ui.linkGroup,\n\t\texpectedUrl,\n\t\t{\n\t\t\ttitle: mw.msg( 'wikispeech-edit-lexicon-btn' ),\n\t\t\ticon: 'edit',\n\t\t\tid: 'wikispeech-edit'\n\t\t}\n\t);\n} );\n\nQUnit.test( 'showBufferingIconIfAudioIsLoading()', function () {\n\tthis.ui.$bufferingIcons = sinon.stub( $( '<div>' ) );\n\tconst mockAudio = { readyState: 0 };\n\n\tthis.ui.showBufferingIconIfAudioIsLoading( mockAudio );\n\n\tsinon.assert.called( this.ui.$bufferingIcons.show );\n} );\n\nQUnit.test( 'showBufferingIconIfAudioIsLoading(): already loaded', function () {\n\tthis.ui.$bufferingIcons = sinon.stub( $( '<div>' ) );\n\tconst mockAudio = { readyState: 2 };\n\n\tthis.ui.showBufferingIconIfAudioIsLoading( mockAudio );\n\n\tsinon.assert.notCalled( this.ui.$bufferingIcons.show );\n} );\n\nQUnit.test( 'addSelectionPlayer(): mouse up shows selection player', function () {\n\tutil.setContentHtml( 'LTR text.' );\n\tconst textNode = $( this.contentSelector ).contents().get( 0 );\n\tthis.selectionPlayer.isSelectionValid.returns( true );\n\tthis.stubGetSelection( textNode, textNode, { right: 50, bottom: 10 } );\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\tthis.ui.addSelectionPlayer();\n\tthis.ui.selectionPlayer.button.$element.width( 30 );\n\tsinon.spy( this.ui.selectionPlayer.button.$element, 'css' );\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, true );\n\tsinon.assert.calledWith(\n\t\tthis.ui.selectionPlayer.button.$element.css,\n\t\t{\n\t\t\tleft: '20px',\n\t\t\ttop: 10 + $( document ).scrollTop() + 'px'\n\t\t}\n\t);\n} );\n\n/**\n * Add a mocked control panel for tests that need to check if it's visible\n */\nthis.addControlPanel = function () {\n\t$( '<div>' ).addClass( 'ext-wikispeech-control-panel' )\n\t\t.appendTo( $( '#qunit-fixture' ) );\n};\n\nQUnit.test( 'addSelectionPlayer(): mouse up shows selection player, RTL', function () {\n\tutil.setContentHtml(\n\t\t'<b style=\"direction: rtl\">RTL text.</b>'\n\t);\n\tconst textNode = $( this.contentSelector + ' b' ).contents().get( 0 );\n\tthis.selectionPlayer.isSelectionValid.returns( true );\n\tthis.stubGetSelection( textNode, textNode, { left: 15, bottom: 10 } );\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\tthis.ui.addSelectionPlayer();\n\tsinon.spy( this.ui.selectionPlayer.button.$element, 'css' );\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, true );\n\tsinon.assert.calledWith(\n\t\tthis.ui.selectionPlayer.button.$element.css,\n\t\t{\n\t\t\tleft: '15px',\n\t\t\ttop: 10 + $( document ).scrollTop() + 'px'\n\t\t}\n\t);\n} );\n\nQUnit.test( 'addSelectionPlayer(): mouse up hides selection player when text is not selected', function () {\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\tthis.ui.addSelectionPlayer();\n\tthis.selectionPlayer.isSelectionValid.returns( false );\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, false );\n} );\n\nQUnit.test( 'addSelectionPlayer(): mouse up hides selection player when start of selection is not in an utterance node', function () {\n\tutil.setContentHtml(\n\t\t'<del>Not an utterance.</del> An utterance.'\n\t);\n\tconst notUtteranceNode = $( this.contentSelector + ' del' ).contents().get( 0 );\n\tconst utteranceNode = $( this.contentSelector ).contents().get( 1 );\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\tthis.ui.addSelectionPlayer();\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tthis.stubGetSelection( notUtteranceNode, utteranceNode );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, false );\n} );\n\nQUnit.test( 'addSelectionPlayer(): mouse up hides selection player when end of selection is not in an utterance node', function () {\n\tutil.setContentHtml(\n\t\t'An utterance. <del>Not an utterance.</del>'\n\t);\n\tconst notUtteranceNode = $( this.contentSelector + ' del' ).contents().get( 0 );\n\tconst utteranceNode = $( this.contentSelector ).contents().get( 0 );\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\tthis.ui.addSelectionPlayer();\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tthis.stubGetSelection( utteranceNode, notUtteranceNode );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, false );\n} );\n\nQUnit.test( 'addSelectionPlayer(): do not show if UI is hidden', function () {\n\tutil.setContentHtml( 'LTR text.' );\n\tconst textNode = $( this.contentSelector ).contents().get( 0 );\n\tsinon.stub( this.ui, 'isShown' ).returns( false );\n\tthis.ui.addSelectionPlayer();\n\tthis.selectionPlayer.isSelectionValid.returns( true );\n\tsinon.spy( this.ui.selectionPlayer.button, 'toggle' );\n\tthis.stubGetSelection( textNode, textNode );\n\tconst event = $.Event( 'mouseup' );\n\n\t$( document ).triggerHandler( event );\n\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, false );\n} );\n\nQUnit.test( 'addSelectionPlayer(): hide selection player initially', function ( assert ) {\n\tthis.ui.addSelectionPlayer();\n\n\tassert.false( this.ui.selectionPlayer.button.isVisible() );\n} );\n\nQUnit.test( 'showLoadAudioError(): plays and stops the error audio', function ( assert ) {\n\tconst done = assert.async();\n\tconst audioMock = {\n\t\tplay: sinon.stub(),\n\t\tpause: sinon.stub(),\n\t\tcurrentTime: 123\n\t};\n\tthis.ui.errorAudio = audioMock;\n\tsinon.stub( this.ui, 'openWindow' ).resolves( { action: 'stop' } );\n\tthis.ui.showLoadAudioError().then( () => {\n\t\tassert.strictEqual( audioMock.play.calledOnce, true );\n\t\tassert.strictEqual( audioMock.pause.calledOnce, true );\n\t\tassert.strictEqual( audioMock.currentTime, 0 );\n\t\tdone();\n\t} );\n} );\n\n/**\n * Create a keydown event.\n *\n * @param {number} keyCode The key code for the event.\n * @param {string} modifiers A string that defines the\n * modifiers. The characters c, a and s triggers the modifiers\n * for ctrl, alt and shift, respectively.\n * @return {jQuery} The created keydown event.\n */\nfunction createKeydownEvent( keyCode, modifiers ) {\n\tconst event = $.Event( 'keydown' );\n\tevent.which = keyCode;\n\tevent.ctrlKey = modifiers.includes( 'c' );\n\tevent.altKey = modifiers.includes( 'a' );\n\tevent.shiftKey = modifiers.includes( 's' );\n\treturn event;\n}\n\n/**\n * Test that a keyboard event triggers the correct function.\n *\n * @param {QUnit.assert} assert\n * @param {string} functionName Name of the function that should\n * be called.\n * @param {number} keyCode The key code for the event.\n * @param {string} modifiers A string that defines the\n * modifiers. The characters c, a and s triggers the modifiers\n * for ctrl, alt and shift, respectively.\n */\nfunction testKeyboardShortcut( assert, functionName, keyCode, modifiers ) {\n\tmw.config.set(\n\t\t'wgWikispeechKeyboardShortcuts', {\n\t\t\tplayPause: {\n\t\t\t\tkey: 13,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t},\n\t\t\tstop: {\n\t\t\t\tkey: 8,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t},\n\t\t\tskipAheadSentence: {\n\t\t\t\tkey: 39,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t},\n\t\t\tskipBackSentence: {\n\t\t\t\tkey: 37,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t},\n\t\t\tskipAheadWord: {\n\t\t\t\tkey: 40,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t},\n\t\t\tskipBackWord: {\n\t\t\t\tkey: 38,\n\t\t\t\tmodifiers: [ 'ctrl' ]\n\t\t\t}\n\t\t}\n\t);\n\tthis.ui.addKeyboardShortcuts();\n\n\t$( document ).triggerHandler( createKeydownEvent( keyCode, modifiers ) );\n\n\tassert.strictEqual( this.ui.player[ functionName ].called, true );\n}\n\nQUnit.test( 'Pressing keyboard shortcut for play/pause', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'playOrPause', 13, 'c' );\n} );\n\nQUnit.test( 'Pressing keyboard shortcut for stop', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'stop', 8, 'c' );\n} );\n\nQUnit.test( 'Pressing keyboard shortcut for skipping ahead sentence', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'skipAheadUtterance', 39, 'c' );\n} );\n\nQUnit.test( 'Pressing keyboard shortcut for skipping back sentence', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'skipBackUtterance', 37, 'c' );\n} );\n\nQUnit.test( 'Pressing keyboard shortcut for skipping ahead word', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'skipAheadToken', 40, 'c' );\n} );\n\nQUnit.test( 'Pressing keyboard shortcut for skipping back word', function ( assert ) {\n\ttestKeyboardShortcut.call( this, assert, 'skipBackToken', 38, 'c' );\n} );\n\nQUnit.test( 'toggleVisibility(): hide', function () {\n\tthis.ui.toolbar = sinon.stub( new OO.ui.Toolbar() );\n\tthis.ui.selectionPlayer.button = sinon.stub( new OO.ui.ButtonWidget() );\n\tthis.ui.$playerFooter = sinon.stub( $( '<div>' ) );\n\tsinon.stub( this.ui, 'isShown' ).returns( true );\n\n\tthis.ui.toggleVisibility();\n\n\tsinon.assert.calledWith( this.ui.toolbar.toggle, false );\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, false );\n\tsinon.assert.called( this.ui.$playerFooter.hide );\n} );\n\nQUnit.test( 'toggleVisibility(): show', function () {\n\tthis.ui.toolbar = sinon.stub( new OO.ui.Toolbar() );\n\tthis.ui.selectionPlayer.button = sinon.stub( new OO.ui.ButtonWidget() );\n\tthis.ui.$playerFooter = sinon.stub( $( '<div>' ) );\n\tsinon.stub( this.ui, 'isShown' ).returns( false );\n\n\tthis.ui.toggleVisibility();\n\n\tsinon.assert.calledWith( this.ui.toolbar.toggle, true );\n\tsinon.assert.calledWith( this.ui.selectionPlayer.button.toggle, true );\n\tsinon.assert.called( this.ui.$playerFooter.show );\n} );\n","usedDeprecatedRules":[{"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/index.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"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":[]}]}]
--- end ---
Disabling eslint rule 'mediawiki/no-unlabeled-buttonwidget' (broken in modules/.eslintrc.json) on modules/.eslintrc.json
$ /usr/bin/npm ci
--- stderr ---
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
--- stdout ---
added 458 packages, and audited 459 packages in 5s
102 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
--- end ---
$ /usr/bin/npm test
--- stdout ---
> test
> grunt test && npm run doc
Running "eslint:all" (eslint) task
/src/repo/dev/speechoid-docker-compose/docker-compose.yml
19:1 warning This line has a length of 118. Maximum allowed is 100 max-len
24:1 warning This line has a length of 117. Maximum allowed is 100 max-len
30:1 warning This line has a length of 118. Maximum allowed is 100 max-len
49:1 warning This line has a length of 119. Maximum allowed is 100 max-len
56:1 warning This line has a length of 117. Maximum allowed is 100 max-len
70:1 warning This line has a length of 107. Maximum allowed is 100 max-len
79:1 warning This line has a length of 127. Maximum allowed is 100 max-len
/src/repo/modules/ext.wikispeech.gadget.js
29:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
39:3 warning Prefer .then to .done no-jquery/no-done-fail
39:3 warning Prefer .then to .fail no-jquery/no-done-fail
77:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
83:2 warning Prefer .then to .done no-jquery/no-done-fail
107:1 warning The type 'ext.wikispeech.UserOptionsDialog' is undefined jsdoc/no-undefined-types
115:2 warning Prefer .then to .done no-jquery/no-done-fail
115:2 warning Prefer .then to .fail no-jquery/no-done-fail
159:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.loader.js
10:2 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.main.js
109:1 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.player.js
111:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .fail no-jquery/no-done-fail
169:5 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.selectionPlayer.js
148:3 warning Prefer .then to .done no-jquery/no-done-fail
184:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.storage.js
47:3 warning Prefer .then to .done no-jquery/no-done-fail
94:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
150:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
159:10 warning Prefer .then to .done no-jquery/no-done-fail
183:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
203:19 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.transcriptionPreviewer.js
32:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
37:1 warning This line has a length of 103. Maximum allowed is 100 max-len
57:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
66:19 warning Prefer .then to .done no-jquery/no-done-fail
66:19 warning Prefer .then to .fail no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.ui.js
126:3 warning Prefer .then to .done no-jquery/no-done-fail
240:1 warning This line has a length of 119. Maximum allowed is 100 max-len
356:27 warning OO.ui.ButtonWidget has no label. Even icon-only buttons should set a label with invisibleLabel set to true mediawiki/no-unlabeled-buttonwidget
591:21 warning Found non-literal argument in require security/detect-non-literal-require
605:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
630:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
/src/repo/modules/ext.wikispeech.userOptionsDialog.js
84:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/tests/qunit/ext.wikispeech.ui.test.js
339:1 warning The type 'QUnit.assert' is undefined jsdoc/no-undefined-types
✖ 43 problems (0 errors, 43 warnings)
Running "banana:Wikispeech" (banana) task
>> 2 message directories checked.
Running "stylelint:all" (stylelint) task
>> Linted 1 files without errors
Done.
> doc
> jsdoc -c jsdoc.json
--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
"auditReportVersion": 2,
"vulnerabilities": {
"grunt": {
"name": "grunt",
"severity": "moderate",
"isDirect": true,
"via": [
"js-yaml"
],
"effects": [
"grunt-eslint"
],
"range": ">=0.4.0-a",
"nodes": [
"node_modules/grunt"
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
},
"grunt-eslint": {
"name": "grunt-eslint",
"severity": "moderate",
"isDirect": true,
"via": [
"grunt"
],
"effects": [],
"range": "<=1.0.0 || >=18.1.0",
"nodes": [
"node_modules/grunt-eslint"
],
"fixAvailable": {
"name": "grunt-eslint",
"version": "18.0.0",
"isSemVerMajor": true
}
},
"js-yaml": {
"name": "js-yaml",
"severity": "moderate",
"isDirect": false,
"via": [
{
"source": 1109754,
"name": "js-yaml",
"dependency": "js-yaml",
"title": "js-yaml has prototype pollution in merge (<<)",
"url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m",
"severity": "moderate",
"cwe": [
"CWE-1321"
],
"cvss": {
"score": 5.3,
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
},
"range": "<4.1.1"
}
],
"effects": [
"grunt"
],
"range": "<4.1.1",
"nodes": [
"node_modules/@eslint/eslintrc/node_modules/js-yaml",
"node_modules/cosmiconfig/node_modules/js-yaml",
"node_modules/eslint/node_modules/js-yaml",
"node_modules/js-yaml"
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
}
},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 3,
"high": 0,
"critical": 0,
"total": 3
},
"dependencies": {
"prod": 1,
"dev": 458,
"optional": 0,
"peer": 1,
"peerOptional": 0,
"total": 458
}
}
}
--- 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": 0,
"removed": 0,
"changed": 4,
"audited": 459,
"funding": 102,
"audit": {
"auditReportVersion": 2,
"vulnerabilities": {
"grunt": {
"name": "grunt",
"severity": "moderate",
"isDirect": true,
"via": [
"js-yaml"
],
"effects": [
"grunt-eslint"
],
"range": ">=0.4.0-a",
"nodes": [
"node_modules/grunt"
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
},
"grunt-eslint": {
"name": "grunt-eslint",
"severity": "moderate",
"isDirect": true,
"via": [
"grunt"
],
"effects": [],
"range": "<=1.0.0 || >=18.1.0",
"nodes": [
"node_modules/grunt-eslint"
],
"fixAvailable": {
"name": "grunt-eslint",
"version": "18.0.0",
"isSemVerMajor": true
}
},
"js-yaml": {
"name": "js-yaml",
"severity": "moderate",
"isDirect": false,
"via": [
{
"source": 1109754,
"name": "js-yaml",
"dependency": "js-yaml",
"title": "js-yaml has prototype pollution in merge (<<)",
"url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m",
"severity": "moderate",
"cwe": [
"CWE-1321"
],
"cvss": {
"score": 5.3,
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
},
"range": "<4.1.1"
}
],
"effects": [
"grunt"
],
"range": "<4.1.1",
"nodes": [
"",
"",
"",
""
],
"fixAvailable": {
"name": "grunt",
"version": "0.3.17",
"isSemVerMajor": true
}
}
},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 3,
"high": 0,
"critical": 0,
"total": 3
},
"dependencies": {
"prod": 1,
"dev": 458,
"optional": 0,
"peer": 1,
"peerOptional": 0,
"total": 458
}
}
}
}
--- end ---
{"added": 0, "removed": 0, "changed": 4, "audited": 459, "funding": 102, "audit": {"auditReportVersion": 2, "vulnerabilities": {"grunt": {"name": "grunt", "severity": "moderate", "isDirect": true, "via": ["js-yaml"], "effects": ["grunt-eslint"], "range": ">=0.4.0-a", "nodes": ["node_modules/grunt"], "fixAvailable": {"name": "grunt", "version": "0.3.17", "isSemVerMajor": true}}, "grunt-eslint": {"name": "grunt-eslint", "severity": "moderate", "isDirect": true, "via": ["grunt"], "effects": [], "range": "<=1.0.0 || >=18.1.0", "nodes": ["node_modules/grunt-eslint"], "fixAvailable": {"name": "grunt-eslint", "version": "18.0.0", "isSemVerMajor": true}}, "js-yaml": {"name": "js-yaml", "severity": "moderate", "isDirect": false, "via": [{"source": 1109754, "name": "js-yaml", "dependency": "js-yaml", "title": "js-yaml has prototype pollution in merge (<<)", "url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m", "severity": "moderate", "cwe": ["CWE-1321"], "cvss": {"score": 5.3, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"}, "range": "<4.1.1"}], "effects": ["grunt"], "range": "<4.1.1", "nodes": ["", "", "", ""], "fixAvailable": {"name": "grunt", "version": "0.3.17", "isSemVerMajor": true}}}, "metadata": {"vulnerabilities": {"info": 0, "low": 0, "moderate": 3, "high": 0, "critical": 0, "total": 3}, "dependencies": {"prod": 1, "dev": 458, "optional": 0, "peer": 1, "peerOptional": 0, "total": 458}}}}
$ /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 ---
up to date, audited 459 packages in 2s
102 packages are looking for funding
run `npm fund` for details
# npm audit report
js-yaml <4.1.1
Severity: moderate
js-yaml has prototype pollution in merge (<<) - https://github.com/advisories/GHSA-mh29-5h37-fv8m
fix available via `npm audit fix --force`
Will install grunt@0.3.17, which is a breaking change
node_modules/js-yaml
grunt >=0.4.0-a
Depends on vulnerable versions of js-yaml
node_modules/grunt
grunt-eslint <=1.0.0 || >=18.1.0
Depends on vulnerable versions of grunt
node_modules/grunt-eslint
3 moderate severity vulnerabilities
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 @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
--- stdout ---
added 458 packages, and audited 459 packages in 5s
102 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
--- end ---
$ /usr/bin/npm test
--- stdout ---
> test
> grunt test && npm run doc
Running "eslint:all" (eslint) task
/src/repo/dev/speechoid-docker-compose/docker-compose.yml
19:1 warning This line has a length of 118. Maximum allowed is 100 max-len
24:1 warning This line has a length of 117. Maximum allowed is 100 max-len
30:1 warning This line has a length of 118. Maximum allowed is 100 max-len
49:1 warning This line has a length of 119. Maximum allowed is 100 max-len
56:1 warning This line has a length of 117. Maximum allowed is 100 max-len
70:1 warning This line has a length of 107. Maximum allowed is 100 max-len
79:1 warning This line has a length of 127. Maximum allowed is 100 max-len
/src/repo/modules/ext.wikispeech.gadget.js
29:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
39:3 warning Prefer .then to .done no-jquery/no-done-fail
39:3 warning Prefer .then to .fail no-jquery/no-done-fail
77:1 warning The type 'jQuery.Deferred' is undefined jsdoc/no-undefined-types
83:2 warning Prefer .then to .done no-jquery/no-done-fail
107:1 warning The type 'ext.wikispeech.UserOptionsDialog' is undefined jsdoc/no-undefined-types
115:2 warning Prefer .then to .done no-jquery/no-done-fail
115:2 warning Prefer .then to .fail no-jquery/no-done-fail
159:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.loader.js
10:2 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.main.js
109:1 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.player.js
111:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .done no-jquery/no-done-fail
156:3 warning Prefer .then to .fail no-jquery/no-done-fail
169:5 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.selectionPlayer.js
148:3 warning Prefer .then to .done no-jquery/no-done-fail
184:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.storage.js
47:3 warning Prefer .then to .done no-jquery/no-done-fail
94:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
150:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
159:10 warning Prefer .then to .done no-jquery/no-done-fail
183:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
203:19 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.transcriptionPreviewer.js
32:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
37:1 warning This line has a length of 103. Maximum allowed is 100 max-len
57:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
66:19 warning Prefer .then to .done no-jquery/no-done-fail
66:19 warning Prefer .then to .fail no-jquery/no-done-fail
/src/repo/modules/ext.wikispeech.ui.js
126:3 warning Prefer .then to .done no-jquery/no-done-fail
240:1 warning This line has a length of 119. Maximum allowed is 100 max-len
356:27 warning OO.ui.ButtonWidget has no label. Even icon-only buttons should set a label with invisibleLabel set to true mediawiki/no-unlabeled-buttonwidget
591:21 warning Found non-literal argument in require security/detect-non-literal-require
605:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
630:1 warning The type 'jQuery.Promise' is undefined jsdoc/no-undefined-types
/src/repo/modules/ext.wikispeech.userOptionsDialog.js
84:3 warning Prefer .then to .done no-jquery/no-done-fail
/src/repo/tests/qunit/ext.wikispeech.ui.test.js
339:1 warning The type 'QUnit.assert' is undefined jsdoc/no-undefined-types
✖ 43 problems (0 errors, 43 warnings)
Running "banana:Wikispeech" (banana) task
>> 2 message directories checked.
Running "stylelint:all" (stylelint) task
>> Linted 1 files without errors
Done.
> doc
> jsdoc -c jsdoc.json
--- end ---
$ package-lock-lint package-lock.json
--- stdout ---
Checking package-lock.json
--- end ---
build: Updating npm dependencies
* eslint-config-wikimedia: 0.31.0 → 0.32.1
The following rules are failing and were disabled:
* modules:
* mediawiki/no-unlabeled-buttonwidget
* jsdoc: ^4.0.4 → 4.0.5
$ git add .
--- stdout ---
--- end ---
$ git commit -F /tmp/tmpxku_81za
--- stdout ---
[master db674fd] build: Updating npm dependencies
3 files changed, 465 insertions(+), 545 deletions(-)
--- end ---
$ git format-patch HEAD~1 --stdout
--- stdout ---
From db674fdf6aec619bea89d094811840959aa283dd Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Sat, 15 Nov 2025 15:47:12 +0000
Subject: [PATCH] build: Updating npm dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* eslint-config-wikimedia: 0.31.0 → 0.32.1
The following rules are failing and were disabled:
* modules:
* mediawiki/no-unlabeled-buttonwidget
* jsdoc: ^4.0.4 → 4.0.5
Change-Id: I468d68ffeae00d2b55276b3a794c66f6ecc30352
---
modules/.eslintrc.json | 3 +-
package-lock.json | 1003 ++++++++++++++++++----------------------
package.json | 4 +-
3 files changed, 465 insertions(+), 545 deletions(-)
diff --git a/modules/.eslintrc.json b/modules/.eslintrc.json
index 54d1204..c7539ee 100644
--- a/modules/.eslintrc.json
+++ b/modules/.eslintrc.json
@@ -10,6 +10,7 @@
},
"rules": {
"compat/compat": "warn",
- "no-jquery/no-done-fail": "warn"
+ "no-jquery/no-done-fail": "warn",
+ "mediawiki/no-unlabeled-buttonwidget": "warn"
}
}
diff --git a/package-lock.json b/package-lock.json
index d07cb9a..5306fd9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,12 +6,12 @@
"": {
"name": "wikispeech",
"devDependencies": {
- "eslint-config-wikimedia": "0.31.0",
+ "eslint-config-wikimedia": "0.32.1",
"grunt": "1.6.1",
"grunt-banana-checker": "0.13.0",
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
- "jsdoc": "^4.0.4",
+ "jsdoc": "4.0.5",
"jsdoc-wmf-theme": "^1.1.0",
"stylelint-config-wikimedia": "0.18.0"
}
@@ -245,33 +245,19 @@
}
},
"node_modules/@es-joy/jsdoccomment": {
- "version": "0.43.1",
- "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz",
- "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==",
+ "version": "0.75.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.75.0.tgz",
+ "integrity": "sha512-Bj+oF8reFb4b+6LUmG6ETpDsBU/28y/bAAzioyIR4VK/V6UodYBNGbtxRyGxk0aJJQqpZZ6jz82vVZWCX6Mwmg==",
"dev": true,
"dependencies": {
- "@types/eslint": "^8.56.5",
- "@types/estree": "^1.0.5",
- "@typescript-eslint/types": "^7.2.0",
+ "@types/estree": "^1.0.8",
+ "@typescript-eslint/types": "^8.46.0",
"comment-parser": "1.4.1",
- "esquery": "^1.5.0",
- "jsdoc-type-pratt-parser": "~4.0.0"
+ "esquery": "^1.6.0",
+ "jsdoc-type-pratt-parser": "~6.9.1"
},
"engines": {
- "node": ">=16"
- }
- },
- "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
- "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">=20.11.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
@@ -293,9 +279,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
- "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
+ "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"
@@ -331,9 +317,9 @@
"dev": true
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -399,9 +385,9 @@
}
},
"node_modules/@mdn/browser-compat-data": {
- "version": "5.5.9",
- "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.9.tgz",
- "integrity": "sha512-36jBin7kGrMn+RC/8k9IKeKvZyMweA0sDNIthUbzSGTQasfMIp2naJ1e+ISUtzu/7RrpDjRh4BkVTSO6f0XArA==",
+ "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/@nodelib/fs.scandir": {
@@ -458,150 +444,6 @@
"eslint": ">=8.40.0"
}
},
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/project-service": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz",
- "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.38.0",
- "@typescript-eslint/types": "^8.38.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz",
- "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/visitor-keys": "8.38.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz",
- "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/types": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz",
- "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz",
- "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/project-service": "8.38.0",
- "@typescript-eslint/tsconfig-utils": "8.38.0",
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/visitor-keys": "8.38.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"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/utils": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz",
- "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.38.0",
- "@typescript-eslint/types": "8.38.0",
- "@typescript-eslint/typescript-estree": "8.38.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.38.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz",
- "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "8.38.0",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
"node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
@@ -631,21 +473,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@stylistic/eslint-plugin/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
@@ -704,26 +531,10 @@
"node": ">=0.10.0"
}
},
- "node_modules/@types/eslint": {
- "version": "8.56.12",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz",
- "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==",
- "dev": true,
- "dependencies": {
- "@types/estree": "*",
- "@types/json-schema": "*"
- }
- },
"node_modules/@types/estree": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true
},
"node_modules/@types/linkify-it": {
@@ -761,16 +572,16 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.1.tgz",
- "integrity": "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
+ "integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/type-utils": "8.35.1",
- "@typescript-eslint/utils": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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",
"natural-compare": "^1.4.0",
@@ -784,9 +595,9 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.35.1",
+ "@typescript-eslint/parser": "^8.46.0",
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
@@ -799,15 +610,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.1.tgz",
- "integrity": "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
+ "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/typescript-estree": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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"
},
"engines": {
@@ -819,17 +630,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.1.tgz",
- "integrity": "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.35.1",
- "@typescript-eslint/types": "^8.35.1",
+ "@typescript-eslint/tsconfig-utils": "^8.46.0",
+ "@typescript-eslint/types": "^8.46.0",
"debug": "^4.3.4"
},
"engines": {
@@ -840,17 +651,17 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.1.tgz",
- "integrity": "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
+ "integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1"
+ "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/visitor-keys": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -861,9 +672,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.1.tgz",
- "integrity": "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==",
+ "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==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -873,17 +684,18 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.1.tgz",
- "integrity": "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.35.1",
- "@typescript-eslint/utils": "8.35.1",
+ "@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"
},
@@ -896,13 +708,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.1.tgz",
- "integrity": "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==",
+ "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==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -913,15 +725,15 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.1.tgz",
- "integrity": "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/project-service": "8.35.1",
- "@typescript-eslint/tsconfig-utils": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/visitor-keys": "8.35.1",
+ "@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",
@@ -937,7 +749,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
@@ -965,15 +777,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.1.tgz",
- "integrity": "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==",
+ "version": "8.46.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
+ "integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.35.1",
- "@typescript-eslint/types": "8.35.1",
- "@typescript-eslint/typescript-estree": "8.35.1"
+ "@typescript-eslint/scope-manager": "8.46.0",
+ "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/typescript-estree": "8.46.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -984,16 +796,16 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.9.0"
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.35.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.1.tgz",
- "integrity": "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==",
+ "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==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "8.35.1",
+ "@typescript-eslint/types": "8.46.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -1163,12 +975,12 @@
}
},
"node_modules/ast-metadata-inferer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz",
- "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.1.tgz",
+ "integrity": "sha512-ht3Dm6Zr7SXv6t1Ra6gFo0+kLDglHGrEbYihTkcycrbHw7WCcuhBzPlJYHEsIpycaUwzsJHje+vUcxXUX4ztTA==",
"dev": true,
"dependencies": {
- "@mdn/browser-compat-data": "^5.2.34"
+ "@mdn/browser-compat-data": "^5.6.19"
}
},
"node_modules/astral-regex": {
@@ -1192,6 +1004,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.28",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz",
+ "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==",
+ "dev": true,
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -1227,9 +1048,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
- "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
+ "version": "4.28.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
+ "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
"dev": true,
"funding": [
{
@@ -1246,10 +1067,11 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001663",
- "electron-to-chromium": "^1.5.28",
- "node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "baseline-browser-mapping": "^2.8.25",
+ "caniuse-lite": "^1.0.30001754",
+ "electron-to-chromium": "^1.5.249",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.1.4"
},
"bin": {
"browserslist": "cli.js"
@@ -1286,9 +1108,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001692",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz",
- "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==",
+ "version": "1.0.30001754",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz",
+ "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==",
"dev": true,
"funding": [
{
@@ -1334,9 +1156,9 @@
}
},
"node_modules/ci-info": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz",
- "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz",
+ "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==",
"dev": true,
"funding": [
{
@@ -1432,12 +1254,12 @@
"dev": true
},
"node_modules/core-js-compat": {
- "version": "3.38.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
- "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
+ "version": "3.46.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz",
+ "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==",
"dev": true,
"dependencies": {
- "browserslist": "^4.23.3"
+ "browserslist": "^4.26.3"
},
"funding": {
"type": "opencollective",
@@ -1483,9 +1305,9 @@
"dev": true
},
"node_modules/cosmiconfig/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -1562,9 +1384,9 @@
}
},
"node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"dependencies": {
"ms": "^2.1.3"
@@ -1593,6 +1415,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/diff-sequences": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz",
+ "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
+ "dev": true,
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -1736,9 +1567,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.29",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
- "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==",
+ "version": "1.5.253",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.253.tgz",
+ "integrity": "sha512-O0tpQ/35rrgdiGQ0/OFWhy1itmd9A6TY9uQzlqj3hKSu/aYpe7UIn5d7CU2N9myH6biZiWF3VMZVuup8pw5U9w==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -1757,9 +1588,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.17.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
- "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "version": "5.18.3",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
+ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -1876,9 +1707,9 @@
}
},
"node_modules/eslint-compat-utils": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
- "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz",
+ "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==",
"dev": true,
"dependencies": {
"semver": "^7.5.4"
@@ -1891,61 +1722,74 @@
}
},
"node_modules/eslint-config-wikimedia": {
- "version": "0.31.0",
- "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.31.0.tgz",
- "integrity": "sha512-Z/t/zGPdxs/ehxb0EM6THNWAzueT7GtuqzjUvmBpkxcTKzZPJEXWnnpswdj/hgv8Ce8PIeDp0zwQxR4e3c9CIw==",
+ "version": "0.32.1",
+ "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.1.tgz",
+ "integrity": "sha512-gPvhyVFNlpKFOcJfoVTNlzg3A0b6qjhAbjjBIJ9xp5m+om0oqix5gkqIIEav5BaGxdDxYNmrY4ge3DAPP3u/lg==",
"dev": true,
"dependencies": {
"@stylistic/eslint-plugin": "^3.1.0",
- "@typescript-eslint/eslint-plugin": "8.35.1",
- "@typescript-eslint/parser": "8.35.1",
+ "@typescript-eslint/eslint-plugin": "8.46.0",
+ "@typescript-eslint/parser": "8.46.0",
"browserslist-config-wikimedia": "^0.7.0",
"eslint": "^8.57.0",
- "eslint-plugin-compat": "^4.2.0",
- "eslint-plugin-es-x": "^7.6.0",
- "eslint-plugin-jest": "^28.5.0",
- "eslint-plugin-jsdoc": "48.2.5",
+ "eslint-plugin-compat": "^6.0.2",
+ "eslint-plugin-es-x": "^8.7.0",
+ "eslint-plugin-jest": "^29.0.1",
+ "eslint-plugin-jsdoc": "61.0.0",
"eslint-plugin-json-es": "^1.6.0",
- "eslint-plugin-mediawiki": "^0.7.0",
- "eslint-plugin-mocha": "^10.4.3",
- "eslint-plugin-n": "^17.7.0",
+ "eslint-plugin-mediawiki": "^0.8.1",
+ "eslint-plugin-mocha": "^10.5.0",
+ "eslint-plugin-n": "^17.23.1",
"eslint-plugin-no-jquery": "^3.1.1",
- "eslint-plugin-qunit": "^8.1.1",
- "eslint-plugin-security": "^1.7.1",
- "eslint-plugin-unicorn": "^53.0.0",
- "eslint-plugin-vue": "^9.26.0",
- "eslint-plugin-wdio": "^8.24.12",
- "eslint-plugin-yml": "^1.14.0"
+ "eslint-plugin-qunit": "^8.2.5",
+ "eslint-plugin-security": "^3.0.1",
+ "eslint-plugin-unicorn": "^56.0.1",
+ "eslint-plugin-vue": "^9.33.0",
+ "eslint-plugin-wdio": "^9.16.2",
+ "eslint-plugin-yml": "^1.19.0"
},
"engines": {
- "node": ">=18 <25"
+ "node": ">=20 <25"
}
},
"node_modules/eslint-plugin-compat": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz",
- "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==",
+ "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==",
"dev": true,
"dependencies": {
- "@mdn/browser-compat-data": "^5.3.13",
- "ast-metadata-inferer": "^0.8.0",
- "browserslist": "^4.21.10",
- "caniuse-lite": "^1.0.30001524",
+ "@mdn/browser-compat-data": "^5.5.35",
+ "ast-metadata-inferer": "^0.8.1",
+ "browserslist": "^4.24.2",
+ "caniuse-lite": "^1.0.30001687",
"find-up": "^5.0.0",
+ "globals": "^15.7.0",
"lodash.memoize": "^4.1.2",
- "semver": "^7.5.4"
+ "semver": "^7.6.2"
},
"engines": {
- "node": ">=14.x"
+ "node": ">=18.x"
},
"peerDependencies": {
- "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-compat/node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-es-x": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz",
- "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==",
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-8.7.0.tgz",
+ "integrity": "sha512-Du5Sb067sjqzmglaPhsfcEQgE1EYfL8sko+4jOMcAB/XKGoCxntSrOmTYuVzswA1rzM9+MZwH6+GOp0G3/wVCg==",
"dev": true,
"funding": [
"https://github.com/sponsors/ota-meshi",
@@ -1953,8 +1797,8 @@
],
"dependencies": {
"@eslint-community/eslint-utils": "^4.1.2",
- "@eslint-community/regexpp": "^4.11.0",
- "eslint-compat-utils": "^0.5.1"
+ "@eslint-community/regexpp": "^4.12.1",
+ "eslint-compat-utils": "^0.6.3"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
@@ -1964,19 +1808,19 @@
}
},
"node_modules/eslint-plugin-jest": {
- "version": "28.8.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz",
- "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==",
+ "version": "29.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz",
+ "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "@typescript-eslint/utils": "^8.0.0"
},
"engines": {
- "node": "^16.10.0 || ^18.12.0 || >=20.0.0"
+ "node": "^20.12.0 || ^22.0.0 || >=24.0.0"
},
"peerDependencies": {
- "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0",
- "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0",
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
+ "eslint": "^8.57.0 || ^9.0.0",
"jest": "*"
},
"peerDependenciesMeta": {
@@ -1989,28 +1833,60 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
- "version": "48.2.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.5.tgz",
- "integrity": "sha512-ZeTfKV474W1N9niWfawpwsXGu+ZoMXu4417eBROX31d7ZuOk8zyG66SO77DpJ2+A9Wa2scw/jRqBPnnQo7VbcQ==",
+ "version": "61.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.0.0.tgz",
+ "integrity": "sha512-YxvOY3A9H8usnOfOEH82y71yHR7zVNWZJpQbjkC+rWqrADQtM+Gza3+db/j9euNNWCNKnN+/gBrowg16n9lwgg==",
"dev": true,
"dependencies": {
- "@es-joy/jsdoccomment": "~0.43.0",
+ "@es-joy/jsdoccomment": "~0.75.0",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.1",
- "debug": "^4.3.4",
+ "debug": "^4.4.3",
"escape-string-regexp": "^4.0.0",
- "esquery": "^1.5.0",
- "is-builtin-module": "^3.2.1",
- "semver": "^7.6.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.6.0",
+ "html-entities": "^2.6.0",
+ "object-deep-merge": "^1.0.5",
+ "parse-imports-exports": "^0.2.4",
+ "semver": "^7.7.3",
"spdx-expression-parse": "^4.0.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=20.11.0"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/eslint-plugin-json-es": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-json-es/-/eslint-plugin-json-es-1.6.0.tgz",
@@ -2025,12 +1901,11 @@
}
},
"node_modules/eslint-plugin-mediawiki": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.7.0.tgz",
- "integrity": "sha512-1Y2nsFDPp96xOZCB5ivZAgqYe9i6w2u64VoCIaAzPyZnd/2h8VQR3CtD+u4Yk/KrpbKq9AAJjrs5LS8VAz6KOA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.1.tgz",
+ "integrity": "sha512-zjTg3hh375lkztKhOYEmPeYiIhKooAu92BkZf2F/fr+5Htvb2i8MNB3gImhM98aTBbkyHTjXoyTHNUrjSjPhmw==",
"dev": true,
"dependencies": {
- "eslint-plugin-vue": "^9.23.0",
"upath": "^2.0.1"
},
"peerDependencies": {
@@ -2055,19 +1930,20 @@
}
},
"node_modules/eslint-plugin-n": {
- "version": "17.10.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.3.tgz",
- "integrity": "sha512-ySZBfKe49nQZWR1yFaA0v/GsH6Fgp8ah6XV0WDz6CN8WO0ek4McMzb7A2xnf4DCYV43frjCygvb9f/wx7UUxRw==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "enhanced-resolve": "^5.17.0",
- "eslint-plugin-es-x": "^7.5.0",
- "get-tsconfig": "^4.7.0",
- "globals": "^15.8.0",
- "ignore": "^5.2.4",
- "minimatch": "^9.0.5",
- "semver": "^7.5.3"
+ "version": "17.23.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
+ "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.5.0",
+ "enhanced-resolve": "^5.17.1",
+ "eslint-plugin-es-x": "^7.8.0",
+ "get-tsconfig": "^4.8.1",
+ "globals": "^15.11.0",
+ "globrex": "^0.1.2",
+ "ignore": "^5.3.2",
+ "semver": "^7.6.3",
+ "ts-declaration-location": "^1.0.6"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2079,40 +1955,52 @@
"eslint": ">=8.23.0"
}
},
- "node_modules/eslint-plugin-n/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "node_modules/eslint-plugin-n/node_modules/eslint-compat-utils": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
+ "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
"dev": true,
"dependencies": {
- "balanced-match": "^1.0.0"
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
}
},
- "node_modules/eslint-plugin-n/node_modules/globals": {
- "version": "15.9.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz",
- "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==",
+ "node_modules/eslint-plugin-n/node_modules/eslint-plugin-es-x": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz",
+ "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==",
"dev": true,
+ "funding": [
+ "https://github.com/sponsors/ota-meshi",
+ "https://opencollective.com/eslint"
+ ],
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.1.2",
+ "@eslint-community/regexpp": "^4.11.0",
+ "eslint-compat-utils": "^0.5.1"
+ },
"engines": {
- "node": ">=18"
+ "node": "^14.18.0 || >=16.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "eslint": ">=8"
}
},
- "node_modules/eslint-plugin-n/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/eslint-plugin-n/node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=18"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-no-jquery": {
@@ -2125,9 +2013,9 @@
}
},
"node_modules/eslint-plugin-qunit": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.1.2.tgz",
- "integrity": "sha512-2gDQdHlQW8GVXD7YYkO8vbm9Ldc60JeGMuQN5QlD48OeZ8znBvvoHWZZMeXjvoDPReGaLEvyuWrDtrI8bDbcqw==",
+ "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==",
"dev": true,
"dependencies": {
"eslint-utils": "^3.0.0",
@@ -2138,27 +2026,33 @@
}
},
"node_modules/eslint-plugin-security": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz",
- "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
+ "integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
"dev": true,
"dependencies": {
"safe-regex": "^2.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-plugin-unicorn": {
- "version": "53.0.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz",
- "integrity": "sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==",
+ "version": "56.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz",
+ "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.5",
+ "@babel/helper-validator-identifier": "^7.24.7",
"@eslint-community/eslint-utils": "^4.4.0",
- "@eslint/eslintrc": "^3.0.2",
"ci-info": "^4.0.0",
"clean-regexp": "^1.0.0",
- "core-js-compat": "^3.37.0",
- "esquery": "^1.5.0",
+ "core-js-compat": "^3.38.1",
+ "esquery": "^1.6.0",
+ "globals": "^15.9.0",
"indent-string": "^4.0.0",
"is-builtin-module": "^3.2.1",
"jsesc": "^3.0.2",
@@ -2166,7 +2060,7 @@
"read-pkg-up": "^7.0.1",
"regexp-tree": "^0.1.27",
"regjsparser": "^0.10.0",
- "semver": "^7.6.1",
+ "semver": "^7.6.3",
"strip-indent": "^3.0.0"
},
"engines": {
@@ -2179,68 +2073,10 @@
"eslint": ">=8.56.0"
}
},
- "node_modules/eslint-plugin-unicorn/node_modules/@eslint/eslintrc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
- "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^10.0.1",
- "globals": "^14.0.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-unicorn/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
- "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-unicorn/node_modules/espree": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
- "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.12.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.0.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
"node_modules/eslint-plugin-unicorn/node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
"engines": {
"node": ">=18"
@@ -2249,22 +2085,10 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint-plugin-unicorn/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
"node_modules/eslint-plugin-vue": {
- "version": "9.28.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.28.0.tgz",
- "integrity": "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g==",
+ "version": "9.33.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz",
+ "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
@@ -2284,23 +2108,24 @@
}
},
"node_modules/eslint-plugin-wdio": {
- "version": "8.37.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-8.37.0.tgz",
- "integrity": "sha512-X217zXxSqj1IPWu3bxN7D/xEUmNk7Jg5lBf2JwYH3mCogaqL2tnHZnwt0EQ5D9oEejfEl2+4zqHSzhXq1X7F2A==",
+ "version": "9.16.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
+ "integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
"dev": true,
"engines": {
- "node": "^16.13 || >=18"
+ "node": ">=18.20.0"
}
},
"node_modules/eslint-plugin-yml": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.14.0.tgz",
- "integrity": "sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.19.0.tgz",
+ "integrity": "sha512-S+4GbcCWksFKAvFJtf0vpdiCkZZvDJCV4Zsi9ahmYkYOYcf+LRqqzvzkb/ST7vTYV6sFwXOvawzYyL/jFT2nQA==",
"dev": true,
"dependencies": {
"debug": "^4.3.2",
- "eslint-compat-utils": "^0.5.0",
- "lodash": "^4.17.21",
+ "diff-sequences": "^27.5.1",
+ "escape-string-regexp": "4.0.0",
+ "eslint-compat-utils": "^0.6.0",
"natural-compare": "^1.4.0",
"yaml-eslint-parser": "^1.2.1"
},
@@ -2388,9 +2213,9 @@
}
},
"node_modules/eslint/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
@@ -2430,9 +2255,9 @@
}
},
"node_modules/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
"dependencies": {
"estraverse": "^5.1.0"
@@ -2718,9 +2543,9 @@
}
},
"node_modules/get-tsconfig": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
- "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
+ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
"dev": true,
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
@@ -2849,6 +2674,12 @@
"integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
"dev": true
},
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -3084,6 +2915,22 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
+ "node_modules/html-entities": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
+ "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ]
+ },
"node_modules/html-tags": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
@@ -3365,9 +3212,9 @@
"dev": true
},
"node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"dependencies": {
"argparse": "^1.0.7",
@@ -3387,11 +3234,10 @@
}
},
"node_modules/jsdoc": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
- "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.5.tgz",
+ "integrity": "sha512-P4C6MWP9yIlMiK8nwoZvxN84vb6MsnXcHuy7XzVOvQoCizWX5JFCBsWIIWKXBltpoRZXddUOVQmCTOZt9yDj9g==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@babel/parser": "^7.20.15",
"@jsdoc/salty": "^0.2.1",
@@ -3423,12 +3269,12 @@
"dev": true
},
"node_modules/jsdoc-type-pratt-parser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
- "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
+ "version": "6.9.1",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.9.1.tgz",
+ "integrity": "sha512-HbYNAorY51GnpKvgDf4YINSY+V1segv0qEeijvTSI6OWMCmqah0W6mVwBFeWskJ81uTJJVnDQlwhpJMREvGsXg==",
"dev": true,
"engines": {
- "node": ">=12.0.0"
+ "node": ">=20.0.0"
}
},
"node_modules/jsdoc-wmf-theme": {
@@ -3469,9 +3315,9 @@
}
},
"node_modules/jsesc": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
- "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"bin": {
"jsesc": "bin/jsesc"
@@ -3849,9 +3695,9 @@
"dev": true
},
"node_modules/node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
"dev": true
},
"node_modules/nopt": {
@@ -3914,6 +3760,27 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/object-deep-merge": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz",
+ "integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "4.2.0"
+ }
+ },
+ "node_modules/object-deep-merge/node_modules/type-fest": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz",
+ "integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/object.defaults": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
@@ -4073,6 +3940,15 @@
"node": ">=0.8"
}
},
+ "node_modules/parse-imports-exports": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz",
+ "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==",
+ "dev": true,
+ "dependencies": {
+ "parse-statements": "1.0.11"
+ }
+ },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -4100,6 +3976,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/parse-statements": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz",
+ "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==",
+ "dev": true
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -4699,9 +4581,9 @@
"dev": true
},
"node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -4824,9 +4706,9 @@
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.20",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
- "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
+ "version": "3.0.22",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz",
+ "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==",
"dev": true
},
"node_modules/sprintf-js": {
@@ -5261,12 +5143,16 @@
"dev": true
},
"node_modules/tapable": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
- "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
"dev": true,
"engines": {
"node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/text-table": {
@@ -5299,6 +5185,40 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-declaration-location": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz",
+ "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "ko-fi",
+ "url": "https://ko-fi.com/rebeccastevens"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/ts-declaration-location"
+ }
+ ],
+ "dependencies": {
+ "picomatch": "^4.0.2"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.0.0"
+ }
+ },
+ "node_modules/ts-declaration-location/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -5388,9 +5308,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
"dev": true,
"funding": [
{
@@ -5407,8 +5327,8 @@
}
],
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@@ -5564,25 +5484,24 @@
}
},
"node_modules/yaml": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
- "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"dev": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 14.6"
}
},
"node_modules/yaml-eslint-parser": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz",
- "integrity": "sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz",
+ "integrity": "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==",
"dev": true,
"dependencies": {
"eslint-visitor-keys": "^3.0.0",
- "lodash": "^4.17.21",
"yaml": "^2.0.0"
},
"engines": {
diff --git a/package.json b/package.json
index df7205f..1d32837 100644
--- a/package.json
+++ b/package.json
@@ -7,12 +7,12 @@
"doc": "jsdoc -c jsdoc.json"
},
"devDependencies": {
- "eslint-config-wikimedia": "0.31.0",
+ "eslint-config-wikimedia": "0.32.1",
"grunt": "1.6.1",
"grunt-banana-checker": "0.13.0",
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
- "jsdoc": "^4.0.4",
+ "jsdoc": "4.0.5",
"jsdoc-wmf-theme": "^1.1.0",
"stylelint-config-wikimedia": "0.18.0"
}
--
2.47.3
--- end ---