From 085b1c716144ded627d9c448406a565609249533 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 19:55:46 +0200 Subject: [PATCH 01/27] chore: add pre-commit hook to run lint-staged for code quality --- .husky/pre-commit | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..60599ae3 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,6 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# Run lint-staged (will autofix and stage fixed files). +# Exit non-zero only if non-fixable problems remain. +npx --no-install lint-staged From b9782879f0143d98d7636c837953b9b74f2cf7ee Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 19:55:52 +0200 Subject: [PATCH 02/27] chore: add pre-commit hooks for automatic linting and autofixing --- CONTRIBUTING.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b543a3b..c52e4fba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,6 +69,44 @@ command: npm run watch ``` +## Pre-commit hooks (automatic linting & autofix) πŸ”§ + +We use Husky + lint-staged to run linters only on the files being committed. The hook will: + +- Run the appropriate autofix for the changed files (PHP, JS/TS, CSS/SCSS). +- Automatically stage any files that were fixed so the fixes are included in the same commit. +- Block the commit only if non-fixable linter errors remain. + +Files β†’ actions (configured in this repository): + +- `*.php` β†’ `npm run lint:php:fix` (phpcbf) +- `*.{js,ts,jsx,tsx}` β†’ `npm run lint:js:fix` (ESLint --fix) +- `*.{css,scss}` β†’ `npm run lint:styles:fix` (Stylelint --fix) + +Setup + +1. Install node deps (this will also prepare Husky via the `prepare` script): + +```shell +npm install +``` + +2. If you already have the repo checked out, activate the Git hooks (run once): + +```shell +npm run prepare +``` + +Usage notes + +- To bypass hooks in an emergency: `git commit --no-verify` (not recommended). +- To run the same checks locally on staged files: `npx lint-staged`. +- If fixes were applied by the hook they will be included automatically in the commit; the commit is only blocked when + a non-autofixable problem remains. + +If you need to change which linters run for a filetype, see `package.json` -> `lint-staged`. + + ## Managing Composer dependencies Code Snippets uses the [Imposter plugin](https://github.com/TypistTech/imposter) to namespace-prefix all vendor From 1a5ded649ad13d0ea07e72d5f431b6eafa3c1534 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 19:55:58 +0200 Subject: [PATCH 03/27] chore: update package.json and package-lock.json to add husky and lint-staged for pre-commit hooks --- package-lock.json | 657 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 10 +- 2 files changed, 665 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b0bfa872..02e0a234 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,6 +58,8 @@ "eslint-webpack-plugin": "^4.2.0", "glob": "^11.0.1", "globals": "^15.14.0", + "husky": "^8.0.0", + "lint-staged": "^15.5.2", "mini-css-extract-plugin": "^2.9.2", "postcss": "^8.5.2", "postcss-color-hsl": "^2.0.0", @@ -4942,6 +4944,120 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cli-width": { "version": "3.0.0", "dev": true, @@ -5844,6 +5960,19 @@ "node": ">=4" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/equivalent-key-map": { "version": "0.2.2", "license": "MIT" @@ -6530,6 +6659,13 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, "node_modules/events": { "version": "3.3.0", "dev": true, @@ -6538,6 +6674,85 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/external-editor": { "version": "3.1.0", "dev": true, @@ -6890,6 +7105,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.7", "dev": true, @@ -7360,6 +7588,32 @@ "node": ">=10.19.0" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "license": "MIT", @@ -8126,7 +8380,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.2", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { @@ -8140,6 +8396,75 @@ "version": "1.2.4", "license": "MIT" }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "dev": true, @@ -8267,6 +8592,166 @@ "node": ">=4" } }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "license": "MIT", @@ -8396,6 +8881,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "dev": true, @@ -8556,6 +9054,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nth-check": { "version": "2.1.1", "dev": true, @@ -8957,6 +9484,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "dev": true, @@ -10288,6 +10828,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "3.0.2", "dev": true, @@ -10815,6 +11362,16 @@ "dev": true, "license": "MIT" }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", "dev": true, @@ -10971,6 +11528,19 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "dev": true, @@ -12410,6 +12980,24 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", @@ -12427,6 +13015,73 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "dev": true, diff --git a/package.json b/package.json index 1c2a9892..65ef63e3 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "test": "tests" }, "scripts": { + "prepare": "husky install", "test:php": "WP_TESTS_DIR=./.wp-tests-lib WP_DEVELOP_DIR=./.wp-core src/vendor/bin/phpunit -c phpunit.xml", "test:php:watch": "npm run test:php -- --testdox", "test:playwright": "playwright test -c tests/playwright/playwright.config.ts", @@ -119,7 +120,14 @@ "webpack-merge": "^6.0.1", "webpack-remove-empty-scripts": "^1.0.4", "@playwright/test": "^1.48.0", - "@wordpress/env": "^9.0.0" + "@wordpress/env": "^9.0.0", + "husky": "^8.0.0", + "lint-staged": "^15.5.2" + }, + "lint-staged": { + "*.{js,ts,jsx,tsx}": "npm run lint:js:fix --", + "*.{css,scss}": "npm run lint:styles:fix --", + "*.php": "npm run lint:php:fix --" }, "overrides": { "eslint": "^9.20.1", From 05804b9008ae97b3faf2c31e80fda599e2f907d5 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 20:07:48 +0200 Subject: [PATCH 04/27] chore: update dependencies --- package-lock.json | 2084 ++++++++++++++++++++++++++++++--------------- package.json | 12 +- 2 files changed, 1407 insertions(+), 689 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02e0a234..a4bcd81e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@wordpress/element": "^6.28.0", "@wordpress/i18n": "^5.17.0", "@wordpress/url": "^4.20.0", - "axios": "^1.7.9", + "axios": "^1.13.5", "classnames": "^2.5.1", "codemirror": "^5.29", "php-parser": "^3.2.2", @@ -56,7 +56,7 @@ "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "eslint-webpack-plugin": "^4.2.0", - "glob": "^11.0.1", + "glob": "^11.1.0", "globals": "^15.14.0", "husky": "^8.0.0", "lint-staged": "^15.5.2", @@ -1913,6 +1913,40 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/@emnapi/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", "license": "MIT", @@ -2049,21 +2083,28 @@ "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", + "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, "license": "MIT", "engines": { @@ -2071,11 +2112,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -2083,8 +2126,23 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.11.0", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2095,7 +2153,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2105,7 +2165,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -2116,21 +2176,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "dev": true, @@ -2142,21 +2187,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, "node_modules/@eslint/js": { - "version": "9.20.0", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2164,28 +2211,19 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.10.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@floating-ui/core": { "version": "1.5.0", "license": "MIT", @@ -2261,7 +2299,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2410,7 +2450,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.6", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -2462,6 +2504,19 @@ "@lezer/common": "^0.15.0" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -2566,11 +2621,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.55.0", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.55.0" + "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -2618,17 +2675,6 @@ "eslint": ">=8.40.0" } }, - "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { "version": "4.0.2", "dev": true, @@ -2717,6 +2763,12 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/@tannin/sprintf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@tannin/sprintf/-/sprintf-1.3.3.tgz", + "integrity": "sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==", + "license": "MIT" + }, "node_modules/@trysound/sax": { "version": "0.2.0", "dev": true, @@ -2750,6 +2802,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/archiver": { "version": "6.0.3", "dev": true, @@ -2796,7 +2859,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -2862,6 +2927,8 @@ }, "node_modules/@types/mousetrap": { "version": "1.6.15", + "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz", + "integrity": "sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==", "license": "MIT" }, "node_modules/@types/node": { @@ -2886,11 +2953,13 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.12", + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", "dependencies": { "@types/prop-types": "*", - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { @@ -2963,19 +3032,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", + "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/type-utils": "8.24.0", - "@typescript-eslint/utils": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/type-utils": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2985,21 +3055,120 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.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/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", + "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.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/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", + "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.56.0", + "@typescript-eslint/types": "^8.56.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3009,35 +3178,88 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", + "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.55.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/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", + "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", + "dev": true, + "license": "MIT", "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 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", + "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/utils": "8.24.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3047,12 +3269,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", + "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", "dev": true, "license": "MIT", "engines": { @@ -3064,18 +3288,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", + "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.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.0.1" + "@typescript-eslint/project-service": "8.56.0", + "@typescript-eslint/tsconfig-utils": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3085,19 +3312,45 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@typescript-eslint/types": "8.55.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/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@typescript-eslint/typescript-estree/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, "license": "ISC", "dependencies": { @@ -3111,7 +3364,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.1", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -3122,14 +3377,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", + "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3139,36 +3396,278 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.0", + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@typescript-eslint/types": "8.24.0", - "eslint-visitor-keys": "^4.2.0" + "@napi-rs/wasm-runtime": "^0.2.11" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=14.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@use-gesture/core": { "version": "10.3.1", @@ -3357,12 +3856,33 @@ } }, "node_modules/@wordpress/a11y": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/a11y/-/a11y-4.40.0.tgz", + "integrity": "sha512-WhBuBgJTvanbBMNeflgCvwQLOU9ToITdYSzOvWg0kzz1i/e138NlCxrVpcXGUc6MQulduKhOWOtjizSdotaQRA==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/dom-ready": "^4.23.0", - "@wordpress/i18n": "^5.23.0" + "@wordpress/dom-ready": "^4.40.0", + "@wordpress/i18n": "^6.13.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/a11y/node_modules/@wordpress/i18n": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.13.0.tgz", + "integrity": "sha512-Yx882uFxcg6QpB13fv8UhvM6k5NwMQGfNXKB9SVSNL/APvDWn2m/n4n+5GZYi+wOV+KJLojQZbdRpHWCnX/jFg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.40.0", + "gettext-parser": "^1.3.1", + "memize": "^2.1.0", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" }, "engines": { "node": ">=18.12.0", @@ -3370,18 +3890,20 @@ } }, "node_modules/@wordpress/babel-preset-default": { - "version": "8.23.0", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-8.40.0.tgz", + "integrity": "sha512-UzSwDaxsMarnlfFUmEWW2qvkJy4JupW49uH0JztFobCamQ5QCL71M75zIspIXffiZVjQMBWruR7/+5QTJklewA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", + "@babel/plugin-syntax-import-attributes": "7.26.0", "@babel/plugin-transform-react-jsx": "7.25.7", "@babel/plugin-transform-runtime": "7.25.7", "@babel/preset-env": "7.25.7", "@babel/preset-typescript": "7.25.7", - "@babel/runtime": "7.25.7", - "@wordpress/browserslist-config": "^6.23.0", - "@wordpress/warning": "^3.23.0", + "@wordpress/browserslist-config": "^6.40.0", + "@wordpress/warning": "^3.40.0", "browserslist": "^4.21.10", "core-js": "^3.31.0", "react": "^18.3.0" @@ -3392,7 +3914,9 @@ } }, "node_modules/@wordpress/browserslist-config": { - "version": "6.23.0", + "version": "6.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-6.40.0.tgz", + "integrity": "sha512-aX44MD4Kcr4LZT1YWa3VkMUUJjNfAgt7UECs/qrNGM8tC3l4/2Z4zRkJfpK3AoaXusb1J8+r5ZXWJWhxYK1JMQ==", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -3401,7 +3925,9 @@ } }, "node_modules/@wordpress/components": { - "version": "29.9.0", + "version": "29.12.0", + "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-29.12.0.tgz", + "integrity": "sha512-jE96pUj84OZya54VusRdEIdTiLjbe2Qst3GbHZcQpA5GiSkPBmGjKWpO6FxR7kRDT4GMnZoVxgtV6xJk4IaNQw==", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.15", @@ -3416,23 +3942,23 @@ "@types/gradient-parser": "0.1.3", "@types/highlight-words-core": "1.2.1", "@use-gesture/react": "^10.3.1", - "@wordpress/a11y": "^4.23.0", - "@wordpress/compose": "^7.23.0", - "@wordpress/date": "^5.23.0", - "@wordpress/deprecated": "^4.23.0", - "@wordpress/dom": "^4.23.0", - "@wordpress/element": "^6.23.0", - "@wordpress/escape-html": "^3.23.0", - "@wordpress/hooks": "^4.23.0", - "@wordpress/html-entities": "^4.23.0", - "@wordpress/i18n": "^5.23.0", - "@wordpress/icons": "^10.23.0", - "@wordpress/is-shallow-equal": "^5.23.0", - "@wordpress/keycodes": "^4.23.0", - "@wordpress/primitives": "^4.23.0", - "@wordpress/private-apis": "^1.23.0", - "@wordpress/rich-text": "^7.23.0", - "@wordpress/warning": "^3.23.0", + "@wordpress/a11y": "^4.26.0", + "@wordpress/compose": "^7.26.0", + "@wordpress/date": "^5.26.0", + "@wordpress/deprecated": "^4.26.0", + "@wordpress/dom": "^4.26.0", + "@wordpress/element": "^6.26.0", + "@wordpress/escape-html": "^3.26.0", + "@wordpress/hooks": "^4.26.0", + "@wordpress/html-entities": "^4.26.0", + "@wordpress/i18n": "^5.26.0", + "@wordpress/icons": "^10.26.0", + "@wordpress/is-shallow-equal": "^5.26.0", + "@wordpress/keycodes": "^4.26.0", + "@wordpress/primitives": "^4.26.0", + "@wordpress/private-apis": "^1.26.0", + "@wordpress/rich-text": "^7.26.0", + "@wordpress/warning": "^3.26.0", "change-case": "^4.1.2", "clsx": "^2.1.1", "colord": "^2.7.0", @@ -3460,18 +3986,19 @@ } }, "node_modules/@wordpress/compose": { - "version": "7.23.0", + "version": "7.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-7.40.0.tgz", + "integrity": "sha512-u8LR5dxJd8KsiEv8eKG+aIgyRrp0lH0oOJy7cK9Jh721zc24TBu8vpxCADL7LbgmpPjQrjHh3LmPoCBtWL+FMg==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", "@types/mousetrap": "^1.6.8", - "@wordpress/deprecated": "^4.23.0", - "@wordpress/dom": "^4.23.0", - "@wordpress/element": "^6.23.0", - "@wordpress/is-shallow-equal": "^5.23.0", - "@wordpress/keycodes": "^4.23.0", - "@wordpress/priority-queue": "^3.23.0", - "@wordpress/undo-manager": "^1.23.0", + "@wordpress/deprecated": "^4.40.0", + "@wordpress/dom": "^4.40.0", + "@wordpress/element": "^6.40.0", + "@wordpress/is-shallow-equal": "^5.40.0", + "@wordpress/keycodes": "^4.40.0", + "@wordpress/priority-queue": "^3.40.0", + "@wordpress/undo-manager": "^1.40.0", "change-case": "^4.1.2", "clipboard": "^2.0.11", "mousetrap": "^1.6.5", @@ -3486,17 +4013,18 @@ } }, "node_modules/@wordpress/data": { - "version": "10.23.0", + "version": "10.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/data/-/data-10.40.0.tgz", + "integrity": "sha512-wwqkMc9iLteRO1zNxL/R3COWnijsdC5TIjenmd2JivReUmdA4ulAN3Tq7QiHkhwOV4jzZkuWW7DgR2ynxf55lw==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/compose": "^7.23.0", - "@wordpress/deprecated": "^4.23.0", - "@wordpress/element": "^6.23.0", - "@wordpress/is-shallow-equal": "^5.23.0", - "@wordpress/priority-queue": "^3.23.0", - "@wordpress/private-apis": "^1.23.0", - "@wordpress/redux-routine": "^5.23.0", + "@wordpress/compose": "^7.40.0", + "@wordpress/deprecated": "^4.40.0", + "@wordpress/element": "^6.40.0", + "@wordpress/is-shallow-equal": "^5.40.0", + "@wordpress/priority-queue": "^3.40.0", + "@wordpress/private-apis": "^1.40.0", + "@wordpress/redux-routine": "^5.40.0", "deepmerge": "^4.3.0", "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", @@ -3514,11 +4042,12 @@ } }, "node_modules/@wordpress/date": { - "version": "5.23.0", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/date/-/date-5.40.0.tgz", + "integrity": "sha512-hlla3+3IVucwhFdOKFGnbeTf4XF0g6ZOdLvzDyTsXQqMT3/ozZ43e6uGwZdG7jrIbdIRicwwKONQsb8E4V6Cyw==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "^4.23.0", + "@wordpress/deprecated": "^4.40.0", "moment": "^2.29.4", "moment-timezone": "^0.5.40" }, @@ -3528,11 +4057,12 @@ } }, "node_modules/@wordpress/deprecated": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.40.0.tgz", + "integrity": "sha512-/PAHeyxIlx/0J1jAfUS/v5x23ssMBXHtWNY3q/P8+GqmDkGTC/7SfkK9FFnT9aQecM1nK8vMgrgizicJBEzDdQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/hooks": "^4.23.0" + "@wordpress/hooks": "^4.40.0" }, "engines": { "node": ">=18.12.0", @@ -3540,11 +4070,12 @@ } }, "node_modules/@wordpress/dom": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-4.40.0.tgz", + "integrity": "sha512-JBF1sRjJMFgLn0pet0tmPzO1kNaa35/DwAAtG81zzjikctR1PzE3EK8o6ZGPtUY1sTa9l7aB1Lxfcum/eroyRg==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/deprecated": "^4.23.0" + "@wordpress/deprecated": "^4.40.0" }, "engines": { "node": ">=18.12.0", @@ -3552,24 +4083,24 @@ } }, "node_modules/@wordpress/dom-ready": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-4.40.0.tgz", + "integrity": "sha512-mHVy4P6yc0XLmGgnccxptMKg83TwcbYKfYrQH8pTcIu43P24zONTd44eZFjkfz7c/b+RLJg1Kj+d5mKh1xqH1A==", "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, "node_modules/@wordpress/element": { - "version": "6.28.0", + "version": "6.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-6.40.0.tgz", + "integrity": "sha512-OhU8B2xEGg7c41rh/VRiJLOz6TnM/r5r8sraAg5ISc2bF7s2oAFqLwvlR0/U6ervyYwbK644osWZGQxFyL3huA==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@types/react": "^18.2.79", - "@types/react-dom": "^18.2.25", - "@wordpress/escape-html": "^3.28.0", + "@types/react": "^18.3.27", + "@types/react-dom": "^18.3.1", + "@wordpress/escape-html": "^3.40.0", "change-case": "^4.1.2", "is-plain-object": "^5.0.0", "react": "^18.3.0", @@ -3602,14 +4133,6 @@ "wp-env": "bin/wp-env" } }, - "node_modules/@wordpress/env/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@wordpress/env/node_modules/cliui": { "version": "8.0.1", "dev": true, @@ -3623,23 +4146,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/env/node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@wordpress/env/node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@wordpress/env/node_modules/wrap-ansi": { "version": "7.0.0", "dev": true, @@ -3690,44 +4196,43 @@ } }, "node_modules/@wordpress/escape-html": { - "version": "3.28.0", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-3.40.0.tgz", + "integrity": "sha512-DD6xWVbnw4fGGgO6DFDTJiLj52om0OG4cYHLz7ZhuipmOlEUGljPYOcrj8uxtlh5EFrqHCIPkOya+qQXUHUSBw==", "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, "node_modules/@wordpress/hooks": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.40.0.tgz", + "integrity": "sha512-Lz89uHQaMKM2TAdwafCPJr6px5qodZt/wdLmRrGkrItvtbikLdf9l29BrjpSMmRbJY6jiYtOTVF4sg5rwJv2Pw==", "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, "node_modules/@wordpress/html-entities": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-4.40.0.tgz", + "integrity": "sha512-bsJrwZk22On8gNhUd84yyWKt/nrNZtACNZpXmkpyue/oTlFqNenLfhqRkvTKJzjbLxrrcUPsXlskbPcS7mxwTQ==", "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, "node_modules/@wordpress/i18n": { - "version": "5.23.0", + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-5.26.0.tgz", + "integrity": "sha512-YHzaUWlCuN2ynl47qbsdMkTGtP52+E1giDOdWBgUaSexUYjbeFxKFUzRMB0Wuh1psL80+VzvJOH/mU440KAJnA==", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/hooks": "^4.23.0", + "@wordpress/hooks": "^4.26.0", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "sprintf-js": "^1.1.1", @@ -3742,12 +4247,14 @@ } }, "node_modules/@wordpress/icons": { - "version": "10.23.0", + "version": "10.32.0", + "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-10.32.0.tgz", + "integrity": "sha512-1WvJdT361X1LnetYBpBWUjAVXZzl+pBdIwHbYRAp8ej47EI/igPmNxmq81nFd40s8fer/9qtipielcqSI6H2rA==", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", - "@wordpress/element": "^6.23.0", - "@wordpress/primitives": "^4.23.0" + "@wordpress/element": "^6.32.0", + "@wordpress/primitives": "^4.32.0" }, "engines": { "node": ">=18.12.0", @@ -3755,22 +4262,42 @@ } }, "node_modules/@wordpress/is-shallow-equal": { - "version": "5.23.0", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-5.40.0.tgz", + "integrity": "sha512-IU11xOcHIGqDLxx9X+8RIk4WFo0qqba0bpeLqrVKsQXNGjP7tXSo2ufylxE9K9CEYXFMF0C65k83XpRZtEkA8g==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, + "node_modules/@wordpress/keycodes": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-4.40.0.tgz", + "integrity": "sha512-laLkfjwkhMdreCl/KQdHucBIQAYwSjkyk3BToq/PCrcxFJBwWK2NgEtSl/t1CEw2HJwe0H2ne3FEWtipY4iDrA==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7" + "@wordpress/i18n": "^6.13.0" }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, - "node_modules/@wordpress/keycodes": { - "version": "4.23.0", + "node_modules/@wordpress/keycodes/node_modules/@wordpress/i18n": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.13.0.tgz", + "integrity": "sha512-Yx882uFxcg6QpB13fv8UhvM6k5NwMQGfNXKB9SVSNL/APvDWn2m/n4n+5GZYi+wOV+KJLojQZbdRpHWCnX/jFg==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/i18n": "^5.23.0" + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.40.0", + "gettext-parser": "^1.3.1", + "memize": "^2.1.0", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" }, "engines": { "node": ">=18.12.0", @@ -3778,11 +4305,12 @@ } }, "node_modules/@wordpress/primitives": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-4.40.0.tgz", + "integrity": "sha512-0gOw3n3kSUsAPo91xNDS9J4GGTrNXU90XmuWn7mNfXAl5uRAMRnxgkfL+pwd0ng0rmdPtjPqrJpljnP2oy3K2w==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/element": "^6.23.0", + "@wordpress/element": "^6.40.0", "clsx": "^2.1.1" }, "engines": { @@ -3794,10 +4322,11 @@ } }, "node_modules/@wordpress/priority-queue": { - "version": "3.23.0", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-3.40.0.tgz", + "integrity": "sha512-85km9+I7RWi7P73BU/yom41gpdu0watdQ1GscQhQBel6BjHOXO5qWG6P9i3sEH47bz7EyO248l4LC/h8oHqpfQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", "requestidlecallback": "^0.3.0" }, "engines": { @@ -3806,21 +4335,21 @@ } }, "node_modules/@wordpress/private-apis": { - "version": "1.23.0", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/private-apis/-/private-apis-1.40.0.tgz", + "integrity": "sha512-68cwZKVq8Xy8GBzKoDRuV4b3pQ4nJFItY689HXp+poc0XXrnAeC4ZhjeSgS1qGRpFo6RVvLjjcaZsN2OrSSMvQ==", "license": "GPL-2.0-or-later", - "dependencies": { - "@babel/runtime": "7.25.7" - }, "engines": { "node": ">=18.12.0", "npm": ">=8.19.2" } }, "node_modules/@wordpress/redux-routine": { - "version": "5.23.0", + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-5.40.0.tgz", + "integrity": "sha512-V+c1yCBl4i7qvRsWtQpGevbFCGtrRlzDe++4bwnrYJUiu79wbSXWRrmiSFr/EQie2KNM680t2MeFcfO7nsDVoA==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "rungen": "^0.3.2" @@ -3834,18 +4363,22 @@ } }, "node_modules/@wordpress/rich-text": { - "version": "7.23.0", + "version": "7.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-7.40.0.tgz", + "integrity": "sha512-eHImTvzPEg4GWAuzcagyc2tArc6neA2sbqvybpd5JzhEpgv/Q0zcKwLfUKI05kYaaPI/Rg5WXgeXDxjGYpq5hA==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/a11y": "^4.23.0", - "@wordpress/compose": "^7.23.0", - "@wordpress/data": "^10.23.0", - "@wordpress/deprecated": "^4.23.0", - "@wordpress/element": "^6.23.0", - "@wordpress/escape-html": "^3.23.0", - "@wordpress/i18n": "^5.23.0", - "@wordpress/keycodes": "^4.23.0", + "@wordpress/a11y": "^4.40.0", + "@wordpress/compose": "^7.40.0", + "@wordpress/data": "^10.40.0", + "@wordpress/deprecated": "^4.40.0", + "@wordpress/dom": "^4.40.0", + "@wordpress/element": "^6.40.0", + "@wordpress/escape-html": "^3.40.0", + "@wordpress/i18n": "^6.13.0", + "@wordpress/keycodes": "^4.40.0", + "@wordpress/private-apis": "^1.40.0", + "colord": "2.9.3", "memize": "^2.1.0" }, "engines": { @@ -3856,12 +4389,33 @@ "react": "^18.0.0" } }, + "node_modules/@wordpress/rich-text/node_modules/@wordpress/i18n": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.13.0.tgz", + "integrity": "sha512-Yx882uFxcg6QpB13fv8UhvM6k5NwMQGfNXKB9SVSNL/APvDWn2m/n4n+5GZYi+wOV+KJLojQZbdRpHWCnX/jFg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@tannin/sprintf": "^1.3.2", + "@wordpress/hooks": "^4.40.0", + "gettext-parser": "^1.3.1", + "memize": "^2.1.0", + "tannin": "^1.2.0" + }, + "bin": { + "pot-to-php": "tools/pot-to-php.js" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/undo-manager": { - "version": "1.23.0", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/undo-manager/-/undo-manager-1.40.0.tgz", + "integrity": "sha512-QvhHke/bVaOSPeaV5mNvsuIQpc2dJFDhXZ7gUnpuzyuNHh74Xk6Ar0vvYcfXiALst4ejKqWCoKOBi7ve1h2ppg==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", - "@wordpress/is-shallow-equal": "^5.23.0" + "@wordpress/is-shallow-equal": "^5.40.0" }, "engines": { "node": ">=18.12.0", @@ -3869,10 +4423,11 @@ } }, "node_modules/@wordpress/url": { - "version": "4.23.0", + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-4.40.0.tgz", + "integrity": "sha512-DVAJlW7bdocKfQp8G7tS73vnobAC8TBbIHHdxeLQKwzT8mOkG4W/rpzN2KTxkiJKFXUu5in4F8a6T+Cy/Lt1eQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "7.25.7", "remove-accents": "^0.5.0" }, "engines": { @@ -3881,7 +4436,9 @@ } }, "node_modules/@wordpress/warning": { - "version": "3.23.0", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-3.40.0.tgz", + "integrity": "sha512-0l3OFa1Z+UdhWRRHX9JWWKofo7Lbi2MqOFzzzn0MC26HOyfieQycjLVLNVNXaaodIKUhap6uDQq+JXbbHm881A==", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -3910,7 +4467,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3920,6 +4479,19 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "dev": true, @@ -3940,14 +4512,16 @@ } }, "node_modules/ajv": { - "version": "8.12.0", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -4059,16 +4633,11 @@ "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/archiver-utils/node_modules/glob": { - "version": "10.4.5", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -4188,16 +4757,20 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4234,16 +4807,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4253,14 +4829,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4344,6 +4922,8 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/autoprefixer": { @@ -4397,11 +4977,13 @@ } }, "node_modules/axios": { - "version": "1.8.4", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -4612,13 +5194,25 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/boolbase": { "version": "1.0.0", "dev": true, "license": "ISC" }, "node_modules/brace-expansion": { - "version": "1.1.11", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -4638,7 +5232,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -4656,10 +5252,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -4764,8 +5361,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4776,12 +5374,14 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -4817,7 +5417,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001727", + "version": "1.0.30001770", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", + "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", "dev": true, "funding": [ { @@ -5068,6 +5670,8 @@ }, "node_modules/clipboard": { "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", "license": "MIT", "dependencies": { "good-listener": "^1.2.2", @@ -5120,6 +5724,8 @@ }, "node_modules/clsx": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -5156,6 +5762,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -5582,7 +6190,9 @@ "license": "CC0-1.0" }, "node_modules/csstype": { - "version": "3.1.2", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/data-view-buffer": { @@ -5642,7 +6252,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5688,6 +6300,8 @@ }, "node_modules/deepmerge": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5746,6 +6360,8 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -5753,6 +6369,8 @@ }, "node_modules/delegate": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", "license": "MIT" }, "node_modules/detect-libc": { @@ -5768,7 +6386,9 @@ } }, "node_modules/diff": { - "version": "4.0.2", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5877,7 +6497,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -5894,7 +6513,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.68", + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, "license": "ISC" }, @@ -5919,12 +6540,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.1", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -5975,6 +6598,8 @@ }, "node_modules/equivalent-key-map": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz", + "integrity": "sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew==", "license": "MIT" }, "node_modules/error-ex": { @@ -5985,7 +6610,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, "license": "MIT", "dependencies": { @@ -5993,18 +6620,18 @@ "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -6016,21 +6643,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -6039,7 +6669,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -6050,7 +6680,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6058,7 +6687,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6091,13 +6719,16 @@ } }, "node_modules/es-module-lexer": { - "version": "1.4.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -6108,7 +6739,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -6121,11 +6751,16 @@ } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -6163,30 +6798,32 @@ } }, "node_modules/eslint": { - "version": "9.20.1", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.11.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.20.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -6239,24 +6876,25 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.7.0", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", "dev": true, "license": "ISC", "dependencies": { "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3", - "stable-hash": "^0.0.4" + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", @@ -6273,7 +6911,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { @@ -6290,6 +6930,8 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6297,28 +6939,30 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -6359,7 +7003,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -6373,7 +7019,7 @@ "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.8", + "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", @@ -6390,7 +7036,9 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.1.0", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { @@ -6437,11 +7085,13 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", + "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, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6498,31 +7148,10 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/eslint/node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.2.0", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6536,17 +7165,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "dev": true, @@ -6558,42 +7176,17 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, "node_modules/espree": { - "version": "10.3.0", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "8.14.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "eslint-visitor-keys": "^4.2.1" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -6601,18 +7194,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.6.0", "dev": true, @@ -6828,16 +7409,28 @@ "node": ">=8.6.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/fast-levenshtein": { "version": "2.0.6", "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "dev": true, @@ -6951,7 +7544,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -6969,19 +7564,29 @@ } }, "node_modules/for-each": { - "version": "0.3.3", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { - "version": "3.3.0", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -6992,11 +7597,15 @@ } }, "node_modules/form-data": { - "version": "4.0.0", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -7045,7 +7654,10 @@ }, "node_modules/fsevents": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -7119,16 +7731,17 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -7143,7 +7756,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -7184,7 +7796,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.6", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -7203,13 +7817,16 @@ } }, "node_modules/glob": { - "version": "11.0.1", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -7237,32 +7854,35 @@ }, "node_modules/glob-to-regexp": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, "license": "BSD-2-Clause" }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", + "node_modules/glob/node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/glob/node_modules/jackspeak": { - "version": "4.0.1", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@isaacs/cliui": "^9.0.0" }, "engines": { "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/glob/node_modules/lru-cache": { @@ -7274,11 +7894,13 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "10.0.1", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -7397,6 +8019,8 @@ }, "node_modules/good-listener": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", "license": "MIT", "dependencies": { "delegate": "^3.1.2" @@ -7404,7 +8028,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7448,11 +8071,6 @@ "node": ">=0.10.0" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/has-bigints": { "version": "1.1.0", "dev": true, @@ -7499,7 +8117,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7510,7 +8127,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -7838,15 +8454,19 @@ } }, "node_modules/is-bun-module": { - "version": "1.1.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.6.3" + "semver": "^7.7.1" } }, "node_modules/is-bun-module/node_modules/semver": { - "version": "7.6.3", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -7868,7 +8488,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -7988,6 +8610,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "dev": true, @@ -8020,6 +8655,8 @@ }, "node_modules/is-promise": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, "node_modules/is-regex": { @@ -8132,11 +8769,13 @@ } }, "node_modules/is-weakref": { - "version": "1.1.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -8233,6 +8872,8 @@ }, "node_modules/jest-worker": { "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", "dependencies": { @@ -8246,6 +8887,8 @@ }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -8271,7 +8914,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -8466,11 +9111,17 @@ } }, "node_modules/loader-runner": { - "version": "4.3.0", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -8488,7 +9139,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, @@ -8792,7 +9445,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8953,6 +9605,8 @@ }, "node_modules/moment": { "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "license": "MIT", "engines": { "node": "*" @@ -8960,6 +9614,8 @@ }, "node_modules/moment-timezone": { "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -8970,6 +9626,8 @@ }, "node_modules/mousetrap": { "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==", "license": "Apache-2.0 WITH LLVM-exception" }, "node_modules/ms": { @@ -8998,6 +9656,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -9023,7 +9697,9 @@ "optional": true }, "node_modules/node-releases": { - "version": "2.0.18", + "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, "license": "MIT" }, @@ -9102,7 +9778,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -9140,13 +9818,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -9270,14 +9951,6 @@ "node": ">=8" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/own-keys": { "version": "1.0.1", "dev": true, @@ -9557,11 +10230,13 @@ } }, "node_modules/playwright": { - "version": "1.55.0", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.55.0" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -9574,7 +10249,9 @@ } }, "node_modules/playwright-core": { - "version": "1.55.0", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10407,14 +11084,6 @@ "once": "^1.3.1" } }, - "node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "dev": true, @@ -10452,6 +11121,8 @@ }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10565,14 +11236,6 @@ "minimatch": "^5.1.0" } }, - "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", "dev": true, @@ -10609,6 +11272,8 @@ }, "node_modules/redux": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "license": "MIT" }, "node_modules/reflect.getprototypeof": { @@ -10661,13 +11326,17 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -10711,6 +11380,8 @@ }, "node_modules/rememo": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rememo/-/rememo-4.0.2.tgz", + "integrity": "sha512-NVfSP9NstE3QPNs/TnegQY0vnJnstKQSpcrsI2kBTB3dB2PkdfKdTa+abbjMIDqpc63fE5LfjLgfMst0ULMFxQ==", "license": "MIT" }, "node_modules/remove-accents": { @@ -10719,6 +11390,8 @@ }, "node_modules/requestidlecallback": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz", + "integrity": "sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==", "license": "MIT" }, "node_modules/require-directory": { @@ -10785,6 +11458,8 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -10900,6 +11575,8 @@ }, "node_modules/rungen": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/rungen/-/rungen-0.3.2.tgz", + "integrity": "sha512-zWl10xu2D7zoR8zSC2U6bg5bYF6T/Wk7rxwp8IPaJH7f0Ge21G03kNHVgHR7tyVkSSfAOG0Rqf/Cl38JftSmtw==", "license": "MIT" }, "node_modules/rxjs": { @@ -11055,7 +11732,9 @@ } }, "node_modules/schema-utils": { - "version": "4.2.0", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", "dependencies": { @@ -11065,7 +11744,7 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -11074,6 +11753,8 @@ }, "node_modules/select": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", "license": "MIT" }, "node_modules/semver": { @@ -11095,6 +11776,8 @@ }, "node_modules/serialize-javascript": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -11316,6 +11999,8 @@ }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { @@ -11325,6 +12010,8 @@ }, "node_modules/source-map-support/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -11336,10 +12023,26 @@ "license": "BSD-3-Clause" }, "node_modules/stable-hash": { - "version": "0.0.4", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", "dev": true, "license": "MIT" }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/streamx": { "version": "2.15.4", "dev": true, @@ -12077,11 +12780,17 @@ } }, "node_modules/tapable": { - "version": "2.2.1", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar-stream": { @@ -12122,12 +12831,14 @@ } }, "node_modules/terser": { - "version": "5.31.6", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -12139,15 +12850,17 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -12171,74 +12884,80 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } + "license": "MIT" }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", + "node_modules/through": { + "version": "2.3.8", "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } + "license": "MIT" }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "license": "MIT" }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">= 10.13.0" + "node": ">=12.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } }, - "node_modules/through": { - "version": "2.3.8", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "license": "MIT" - }, - "node_modules/tiny-emitter": { - "version": "2.1.0", - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, "node_modules/tmp": { - "version": "0.0.33", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=14.14" } }, "node_modules/to-regex-range": { @@ -12253,7 +12972,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.1", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -12470,13 +13191,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.24.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.0.tgz", + "integrity": "sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.24.0", - "@typescript-eslint/parser": "8.24.0", - "@typescript-eslint/utils": "8.24.0" + "@typescript-eslint/eslint-plugin": "8.56.0", + "@typescript-eslint/parser": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -12486,8 +13210,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/unbox-primitive": { @@ -12557,8 +13281,45 @@ "viewport-dimensions": "^0.2.0" } }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, "node_modules/update-browserslist-db": { - "version": "1.1.1", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -12577,7 +13338,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -12600,14 +13361,6 @@ "tslib": "^2.0.3" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/use-isomorphic-layout-effect": { "version": "1.2.0", "license": "MIT", @@ -12622,6 +13375,8 @@ }, "node_modules/use-memo-one": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" @@ -12665,7 +13420,9 @@ "license": "MIT" }, "node_modules/watchpack": { - "version": "2.4.2", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -12685,33 +13442,37 @@ } }, "node_modules/webpack": { - "version": "5.97.1", + "version": "5.105.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz", + "integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -12810,69 +13571,15 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", + "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.14.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/which": { "version": "2.0.2", "dev": true, @@ -12949,14 +13656,17 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.18", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, diff --git a/package.json b/package.json index 65ef63e3..596e4e8f 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@wordpress/element": "^6.28.0", "@wordpress/i18n": "^5.17.0", "@wordpress/url": "^4.20.0", - "axios": "^1.7.9", + "axios": "^1.13.5", "classnames": "^2.5.1", "codemirror": "^5.29", "php-parser": "^3.2.2", @@ -94,7 +94,7 @@ "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "eslint-webpack-plugin": "^4.2.0", - "glob": "^11.0.1", + "glob": "^11.1.0", "globals": "^15.14.0", "mini-css-extract-plugin": "^2.9.2", "postcss": "^8.5.2", @@ -130,6 +130,14 @@ "*.php": "npm run lint:php:fix --" }, "overrides": { + "ajv": "8.18.0", + "js-yaml": "4.1.1", + "lodash": "4.17.23", + "brace-expansion": "1.1.12", + "form-data": "4.0.5", + "tmp": "0.2.5", + "eslint-visitor-keys": "4.2.1", + "@typescript-eslint/visitor-keys": "8.55.0", "eslint": "^9.20.1", "react": "^18.3.1", "react-dom": "^18.3.1" From 737dd0865ef0868c1cc71652b63bcbc8733b50c7 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 20:51:20 +0200 Subject: [PATCH 05/27] feat: add linting script for readme.txt to enforce WordPress.org formatting --- scripts/linters/lint-readme.ts | 325 +++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 scripts/linters/lint-readme.ts diff --git a/scripts/linters/lint-readme.ts b/scripts/linters/lint-readme.ts new file mode 100644 index 00000000..a2b1f797 --- /dev/null +++ b/scripts/linters/lint-readme.ts @@ -0,0 +1,325 @@ +/** + * lint-readme.ts + * + * Lints and auto-fixes src/readme.txt for WordPress.org formatting consistency. + * + * Rules enforced (based on current file conventions + WordPress.org spec): + * + * Header block + * - First line: === Plugin Name === + * - Each header field: "Key: Value" (single space after colon, no trailing whitespace) + * - Exactly 1 blank line between the last header field and the short description + * - Required fields must be present: Contributors, Donate link, Tags, License, + * License URI, Stable tag, Requires at least, Tested up to, Requires PHP + * - Short description line immediately follows header (non-empty, ≀ 150 chars, no markup) + * + * Sections + * - Top-level: == Section Name == (known names normalised, title-case otherwise) + * - Sub-sections: = Sub Section = (title-case) + * - Known section names: Description, Installation, Frequently Asked Questions, + * Screenshots, Changelog, Upgrade Notice + * + * Changelog section (inside readme.txt) + * - Version sub-headers: = X.Y.Z (YYYY-MM-DD) = + * - Change-type labels: __Added__, __Changed__, __Fixed__, __Removed__, + * __Deprecated__, __Security__ + * (### headings and **Bold** variants are demoted / normalised) + * + * Lists + * - Items start with "* " (not "- ") + * - No trailing whitespace + * + * Spacing + * - Exactly 1 blank line before every == section (not the very first) + * - Exactly 1 blank line after every == section heading + * - Exactly 1 blank line before every = sub-section (not right after == heading) + * - Exactly 1 blank line after every = sub-section inside == Changelog == only + * - Exactly 1 blank line before __Type__ labels inside Changelog (not right after = heading) + * - Exactly 1 blank line after __Type__ labels inside Changelog + * - No consecutive blank lines (max 1) + * - File ends with exactly one newline + */ + +import { readFileSync, writeFileSync, existsSync } from 'fs'; +import { resolve } from 'path'; + +/* ── helpers ─────────────────────────────────────────────────────────── */ + +const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security']; + +const RE_DATE_SRC = '\\d{4}-\\d{2}-\\d{2}'; +const RE_VERSION_SRC = '\\d+\\.\\d+(?:\\.\\d+)*(?:-[a-zA-Z0-9.]+)?'; + +/** Known == Section == names (canonical capitalisation). */ +const KNOWN_SECTIONS: Record = { + 'description': 'Description', + 'installation': 'Installation', + 'frequently asked questions': 'Frequently Asked Questions', + 'faq': 'Frequently Asked Questions', + 'screenshots': 'Screenshots', + 'changelog': 'Changelog', + 'upgrade notice': 'Upgrade Notice', +}; + +function titleCase(s: string): string { + return s.replace(/\w\S*/g, t => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase()); +} + +/** Sentence-case: capitalise only the first word. */ +function sentenceCase(s: string): string { + return s.charAt(0).toUpperCase() + s.slice(1); +} + +/** Title-case for ≀ 2 words, sentence-case for 3+ words. */ +function subsectionCase(s: string): string { + const wordCount = s.trim().split(/\s+/).length; + return wordCount <= 2 ? titleCase(s) : sentenceCase(s); +} + +function normaliseSectionName(raw: string): string { + const key = raw.trim().toLowerCase(); + return KNOWN_SECTIONS[key] ?? titleCase(raw.trim()); +} + +function trimTrailing(lines: string[]): string[] { + return lines.map(l => l.trimEnd()); +} + +function collapseBlankLines(lines: string[]): string[] { + const out: string[] = []; + let prevBlank = false; + for (const l of lines) { + const blank = l.trim() === ''; + if (blank && prevBlank) continue; + out.push(l); + prevBlank = blank; + } + return out; +} + +/** + * Ensure exactly `n` blank lines appear immediately before every line matching + * `headingRe`. Lines matching `skipAfterRe` reset the "just-saw-section-start" + * flag, suppressing spacing for the immediately following heading. + */ +function normaliseBlanksBefore( + lines: string[], + headingRe: RegExp, + n: number, + skipAfterRe?: RegExp +): string[] { + const out: string[] = []; + let suppressNext = true; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (skipAfterRe && skipAfterRe.test(line)) { + suppressNext = true; + out.push(line); + continue; + } + + if (headingRe.test(line)) { + if (!suppressNext) { + while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); + for (let b = 0; b < n; b++) out.push(''); + } + out.push(line); + suppressNext = false; + continue; + } + + if (line.trim() !== '') suppressNext = false; + out.push(line); + } + return out; +} + +/** Ensure exactly 1 blank line immediately after every line matching `headingRe`. */ +function normaliseBlankAfter(lines: string[], headingRe: RegExp): string[] { + const out: string[] = []; + let i = 0; + while (i < lines.length) { + const line = lines[i]; + out.push(line); + if (headingRe.test(line)) { + i++; + while (i < lines.length && lines[i].trim() === '') i++; + if (i < lines.length) out.push(''); + continue; + } + i++; + } + return out; +} + +/** + * Like normaliseBlankAfter but only operates on lines that fall within a + * specific section (between `sectionStartRe` and the next `== ... ==` heading). + */ +function normaliseBlankAfterInSection( + lines: string[], + sectionStartRe: RegExp, + headingRe: RegExp +): string[] { + const out: string[] = []; + let inSection = false; + let i = 0; + while (i < lines.length) { + const line = lines[i]; + if (sectionStartRe.test(line)) inSection = true; + else if (/^== .+ ==$/.test(line)) inSection = false; + + out.push(line); + if (inSection && headingRe.test(line)) { + i++; + while (i < lines.length && lines[i].trim() === '') i++; + if (i < lines.length) out.push(''); + continue; + } + i++; + } + return out; +} + +/* ── linter ─────────────────────────────────────────────────────────── */ + +export function lintReadme(src: string): { fixed: string; errors: string[] } { + const errors: string[] = []; + let lines = src.split('\n'); + + /* 1. Plugin name header */ + if (!/^=== .+ ===$/.test(lines[0])) { + errors.push('readme.txt: First line must be "=== Plugin Name ==="'); + } + + lines = trimTrailing(lines); + + /* 2. Normalise header field spacing: "Key: Value" */ + let inHeader = true; + lines = lines.map((line, i) => { + if (inHeader && i > 0 && line.trim() === '') { inHeader = false; return line; } + if (!inHeader) return line; + const m = line.match(/^([A-Za-z][A-Za-z ]+):\s*(.*)$/); + if (m) return `${m[1].trim()}: ${m[2].trim()}`; + return line; + }); + + /* 2a. Ensure exactly one blank line after the last header field (before short description). + * If the blank was removed the header parser above never terminates, so we fix it here + * by finding the last "Key: Value" line and inserting a blank after it when missing. */ + { + const FIELD_RE = /^[A-Za-z][A-Za-z ]+: /; + let lastFieldIdx = -1; + for (let i = 1; i < lines.length; i++) { + if (/^== /.test(lines[i])) break; // hit a section heading – header is long gone + if (FIELD_RE.test(lines[i])) lastFieldIdx = i; + } + if (lastFieldIdx !== -1) { + const afterField = lines[lastFieldIdx + 1]; + if (afterField !== undefined && afterField.trim() !== '') { + // No blank line after last field – insert one + lines.splice(lastFieldIdx + 1, 0, ''); + } + } + } + + /* 3. Normalise == Section == headings */ + lines = lines.map(line => { + const m = line.match(/^==\s+(.+?)\s+==$/); + if (m) return `== ${normaliseSectionName(m[1])} ==`; + return line; + }); + + /* 4. Normalise = Sub Section = headings */ + lines = lines.map(line => { + const m = line.match(/^=\s+(.+?)\s+=$/); + if (!m) return line; + const inner = m[1].trim(); + // Version entry inside Changelog: "= X.Y.Z (YYYY-MM-DD) =" + const ver = inner.match(new RegExp(`^(${RE_VERSION_SRC})\\s+\\((${RE_DATE_SRC})\\)$`)); + if (ver) return `= ${ver[1]} (${ver[2]}) =`; + return `= ${subsectionCase(inner)} =`; + }); + + /* 5. Inside Changelog section: demote ### headings and **Bold** to __Type__ */ + let inChangelog = false; + lines = lines.map(line => { + if (/^== Changelog ==$/.test(line)) { inChangelog = true; return line; } + if (/^== /.test(line)) { inChangelog = false; return line; } + if (!inChangelog) return line; + + const hashM = line.match(/^###\s+(\w+)\s*$/); + if (hashM) { + const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === hashM[1].toLowerCase()); + if (n) return `__${n}__`; + } + const boldM = line.match(/^\*\*(\w+)\*\*\s*$/); + if (boldM) { + const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === boldM[1].toLowerCase()); + if (n) return `__${n}__`; + } + // Normalise existing __type__ casing + const underM = line.match(/^__(\w+)__\s*$/); + if (underM) { + const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === underM[1].toLowerCase()); + if (n) return `__${n}__`; + } + return line; + }); + + /* 6. List items: "- " β†’ "* " */ + lines = lines.map(line => (/^- /.test(line) ? '* ' + line.slice(2) : line)); + + /* 7. Spacing rules */ + const SECTION_RE = /^== .+ ==$/; + const SUBSECTION_RE = /^= .+ =$/; + const CHANGETYPE_RE = /^__(?:Added|Changed|Fixed|Removed|Deprecated|Security)__$/; + + lines = normaliseBlanksBefore(lines, SECTION_RE, 1, /^=== .+ ===/); + lines = normaliseBlankAfter(lines, SECTION_RE); + lines = normaliseBlanksBefore(lines, SUBSECTION_RE, 1, SECTION_RE); + lines = normaliseBlankAfterInSection(lines, /^== Changelog ==$/, SUBSECTION_RE); + lines = normaliseBlanksBefore(lines, CHANGETYPE_RE, 1, SUBSECTION_RE); + lines = normaliseBlankAfterInSection(lines, /^== Changelog ==$/, CHANGETYPE_RE); + + /* 8. Collapse multiple blank lines, trailing newline */ + lines = collapseBlankLines(lines); + while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop(); + lines.push(''); + + return { fixed: lines.join('\n'), errors }; +} + +/* ── entry point ─────────────────────────────────────────────────────── */ + +const root = resolve(__dirname, '../..'); +const args = process.argv.slice(2); +const files = args.length > 0 ? args : [resolve(root, 'src/readme.txt')]; +let anyErrors = false; +let anyProcessed = false; + +for (const f of files) { + const abs = resolve(f); + if (!abs.endsWith('readme.txt')) continue; + anyProcessed = true; + + if (!existsSync(abs)) { console.error(`lint-readme: file not found – ${abs}`); anyErrors = true; continue; } + + const src = readFileSync(abs, 'utf8'); + const { fixed, errors } = lintReadme(src); + + errors.forEach(e => console.error(` βœ— ${e}`)); + if (errors.length > 0) anyErrors = true; + + if (fixed !== src) { + writeFileSync(abs, fixed, 'utf8'); + console.log(` βœ” auto-fixed: ${abs}`); + } else { + console.log(` βœ” no changes: ${abs}`); + } +} + +if (!anyProcessed) process.exit(0); +process.exit(anyErrors ? 1 : 0); From abfcb515650fe5381d6703293037497baae1fb3a Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 20:51:27 +0200 Subject: [PATCH 06/27] feat: add linting script for CHANGELOG.md to ensure formatting consistency --- scripts/linters/lint-changelog.ts | 227 ++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 scripts/linters/lint-changelog.ts diff --git a/scripts/linters/lint-changelog.ts b/scripts/linters/lint-changelog.ts new file mode 100644 index 00000000..f341cc27 --- /dev/null +++ b/scripts/linters/lint-changelog.ts @@ -0,0 +1,227 @@ +/** + * lint-changelog.ts + * + * Lints and auto-fixes CHANGELOG.md for formatting consistency. + * + * Rules enforced (based on current file conventions): + * + * File title + * - First line must be exactly: # Changelog + * + * Release headers + * - Format: ## [X.Y.Z] (YYYY-MM-DD) + * or: ## [X.Y.Z-modifier.N] (YYYY-MM-DD) + * - Non-bracketed versions (e.g. "## 3.6.5.1 (...)") are normalised to the + * bracketed form: ## [3.6.5.1] (YYYY-MM-DD) + * - Date format: YYYY-MM-DD (required) + * + * Section sub-headings + * - Allowed: ### Added, ### Changed, ### Fixed, ### Removed, + * ### Deprecated, ### Security + * - Bold variants (**Added**, __Added__) are promoted to ### headings + * - Casing is normalised to the canonical form above + * + * Lists + * - Items start with "* " (not "- ") + * - No trailing whitespace + * + * Spacing + * - Exactly 1 blank line before every ## heading (not before the first one) + * - Exactly 1 blank line after every ## heading + * - Exactly 1 blank line before every ### heading (not immediately after ##) + * - Exactly 1 blank line after every ### heading + * - No consecutive blank lines (max 1) + * - File ends with exactly one newline + */ + +import { readFileSync, writeFileSync, existsSync } from 'fs'; +import { resolve } from 'path'; + +/* ── helpers ─────────────────────────────────────────────────────────── */ + +const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security']; + +function trimTrailing(lines: string[]): string[] { + return lines.map(l => l.trimEnd()); +} + +function collapseBlankLines(lines: string[]): string[] { + const out: string[] = []; + let prevBlank = false; + for (const l of lines) { + const blank = l.trim() === ''; + if (blank && prevBlank) continue; + out.push(l); + prevBlank = blank; + } + return out; +} + +/** + * Ensure exactly `n` blank lines appear immediately before every line matching + * `headingRe`. Lines matching `skipAfterRe` suppress spacing for the immediately + * following heading (used to avoid a blank line between a ## and its first ###). + */ +function normaliseBlanksBefore( + lines: string[], + headingRe: RegExp, + n: number, + skipAfterRe?: RegExp +): string[] { + const out: string[] = []; + let suppressNext = true; // suppress before very first heading + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (skipAfterRe && skipAfterRe.test(line)) { + suppressNext = true; + out.push(line); + continue; + } + + if (headingRe.test(line)) { + if (!suppressNext) { + while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); + for (let b = 0; b < n; b++) out.push(''); + } + out.push(line); + suppressNext = false; + continue; + } + + if (line.trim() !== '') suppressNext = false; + out.push(line); + } + return out; +} + +/** Ensure exactly 1 blank line immediately after every line matching `headingRe`. */ +function normaliseBlankAfter(lines: string[], headingRe: RegExp): string[] { + const out: string[] = []; + let i = 0; + while (i < lines.length) { + const line = lines[i]; + out.push(line); + if (headingRe.test(line)) { + i++; + while (i < lines.length && lines[i].trim() === '') i++; + if (i < lines.length) out.push(''); + continue; + } + i++; + } + return out; +} + +/* ── linter ─────────────────────────────────────────────────────────── */ + +export function lintChangelog(src: string): { fixed: string; errors: string[] } { + const errors: string[] = []; + let lines = src.split('\n'); + + /* 1. File title */ + if (lines[0] !== '# Changelog') { + if (/^#\s+changelog/i.test(lines[0])) { + lines[0] = '# Changelog'; + } else { + errors.push('CHANGELOG.md: First line must be "# Changelog"'); + } + } + + lines = trimTrailing(lines); + + /* 2. Promote bold change-type labels to ### headings */ + lines = lines.map(line => { + const m = line.match(/^\s*(?:\*\*|__)(\w+)(?:\*\*|__)\s*$/); + if (m) { + const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === m[1].toLowerCase()); + if (n) return `### ${n}`; + } + return line; + }); + + /* 3. Normalise release headers to ## [X.Y.Z] (YYYY-MM-DD) */ + lines = lines.map(line => { + // Already bracketed: ## [X.Y.Z] (YYYY-MM-DD) + const bracketed = line.match(/^## \[([^\]]+)\]\s*\((\d{4}-\d{2}-\d{2})\)/); + if (bracketed) return `## [${bracketed[1]}] (${bracketed[2]})`; + + // Bracketed but missing / malformed date + const bracketedNoDate = line.match(/^## \[([^\]]+)\]/); + if (bracketedNoDate) { + errors.push(`CHANGELOG.md: Release header missing or malformed date: ${line}`); + return line; + } + + // Non-bracketed: ## X.Y.Z (YYYY-MM-DD) + const plain = line.match(/^## (\d[^\s(]+)\s*(?:\((\d{4}-\d{2}-\d{2})\))?/); + if (plain) { + if (plain[2]) return `## [${plain[1]}] (${plain[2]})`; + errors.push(`CHANGELOG.md: Release header missing date: ${line}`); + return `## [${plain[1]}]`; + } + + return line; + }); + + /* 4. Normalise ### section names */ + lines = lines.map(line => { + const m = line.match(/^###\s+(.+)$/); + if (!m) return line; + const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === m[1].trim().toLowerCase()); + return n ? `### ${n}` : `### ${m[1].trim()}`; + }); + + /* 5. List items: "- " β†’ "* " */ + lines = lines.map(line => (/^- /.test(line) ? '* ' + line.slice(2) : line)); + + /* 6. Spacing rules */ + const RELEASE_RE = /^## /; + const SECTION_RE = /^### /; + const TITLE_RE = /^# Changelog/; + + lines = normaliseBlanksBefore(lines, RELEASE_RE, 1, TITLE_RE); + lines = normaliseBlankAfter(lines, RELEASE_RE); + lines = normaliseBlanksBefore(lines, SECTION_RE, 1, RELEASE_RE); + lines = normaliseBlankAfter(lines, SECTION_RE); + + /* 7. Collapse multiple blank lines, trailing newline */ + lines = collapseBlankLines(lines); + while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop(); + lines.push(''); + + return { fixed: lines.join('\n'), errors }; +} + +/* ── entry point ─────────────────────────────────────────────────────── */ + +const root = resolve(__dirname, '../..'); +const args = process.argv.slice(2); +const files = args.length > 0 ? args : [resolve(root, 'CHANGELOG.md')]; +let anyErrors = false; +let anyProcessed = false; + +for (const f of files) { + const abs = resolve(f); + if (!abs.endsWith('CHANGELOG.md')) continue; + anyProcessed = true; + + if (!existsSync(abs)) { console.error(`lint-changelog: file not found – ${abs}`); anyErrors = true; continue; } + + const src = readFileSync(abs, 'utf8'); + const { fixed, errors } = lintChangelog(src); + + errors.forEach(e => console.error(` βœ— ${e}`)); + if (errors.length > 0) anyErrors = true; + + if (fixed !== src) { + writeFileSync(abs, fixed, 'utf8'); + console.log(` βœ” auto-fixed: ${abs}`); + } else { + console.log(` βœ” no changes: ${abs}`); + } +} + +if (!anyProcessed) process.exit(0); +process.exit(anyErrors ? 1 : 0); From 648c4ec4b6f881581a897b3fec8802f204a91006 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 20:51:31 +0200 Subject: [PATCH 07/27] chore: add linting scripts for readme.txt and CHANGELOG.md to package.json --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 596e4e8f..8106c761 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "lint:js:fix": "eslint --fix", "lint:php": "src/vendor/bin/phpcs -s --colors --standard=phpcs.xml src/php tests", "lint:php:fix": "src/vendor/bin/phpcbf --standard=phpcs.xml src/php tests", + "lint:readme": "ts-node scripts/linters/lint-readme.ts", + "lint:changelog": "ts-node scripts/linters/lint-changelog.ts", "version": "ts-node scripts/version.ts", "version-dev": "npm version --git-tag-version=false --preid=dev", "version-alpha": "npm version --git-tag-version=false --preid=alpha", @@ -127,7 +129,9 @@ "lint-staged": { "*.{js,ts,jsx,tsx}": "npm run lint:js:fix --", "*.{css,scss}": "npm run lint:styles:fix --", - "*.php": "npm run lint:php:fix --" + "*.php": "npm run lint:php:fix --", + "src/readme.txt": "ts-node scripts/linters/lint-readme.ts", + "CHANGELOG.md": "ts-node scripts/linters/lint-changelog.ts" }, "overrides": { "ajv": "8.18.0", From 8e78d272e7ce366ab908c6a26a16a9c9f813b668 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 20:51:37 +0200 Subject: [PATCH 08/27] chore: update readme.txt for consistency in section headings --- src/readme.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/readme.txt b/src/readme.txt index 13451bfd..d567616d 100644 --- a/src/readme.txt +++ b/src/readme.txt @@ -42,7 +42,7 @@ https://youtu.be/uzND-wdSCMQ == Installation == -= Automatic installation = += Automatic Installation = 1. Log into your WordPress admin 2. Click __Plugins__ @@ -54,7 +54,7 @@ https://youtu.be/uzND-wdSCMQ 5. Click __Install Now__ under "Code Snippets" 6. Activate the plugin -= Manual installation = += Manual Installation = 1. Download the plugin 2. Extract the contents of the zip file @@ -126,7 +126,7 @@ __Added__ __Changed__ -* Updated links to more recent documentation pages +* Updated links to more recent documentation pages __Fixed__ From 450c8dc9127c3168eda721f4a8a6dde6826eb368 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 21:29:06 +0200 Subject: [PATCH 09/27] feat: enhance linting rules for CHANGELOG.md formatting consistency --- scripts/linters/lint-changelog.ts | 90 ++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/scripts/linters/lint-changelog.ts b/scripts/linters/lint-changelog.ts index f341cc27..b02e525a 100644 --- a/scripts/linters/lint-changelog.ts +++ b/scripts/linters/lint-changelog.ts @@ -27,9 +27,9 @@ * * Spacing * - Exactly 1 blank line before every ## heading (not before the first one) - * - Exactly 1 blank line after every ## heading + * - Exactly 1 blank line after every # and ## headings + * - No blank lines after ### headings * - Exactly 1 blank line before every ### heading (not immediately after ##) - * - Exactly 1 blank line after every ### heading * - No consecutive blank lines (max 1) * - File ends with exactly one newline */ @@ -114,6 +114,24 @@ function normaliseBlankAfter(lines: string[], headingRe: RegExp): string[] { return out; } +/** Remove any blank lines immediately after lines matching `headingRe`. */ +function removeBlankAfter(lines: string[], headingRe: RegExp): string[] { + const out: string[] = []; + let i = 0; + while (i < lines.length) { + const line = lines[i]; + out.push(line); + if (headingRe.test(line)) { + i++; + // skip all blank lines following the heading + while (i < lines.length && lines[i].trim() === '') i++; + continue; + } + i++; + } + return out; +} + /* ── linter ─────────────────────────────────────────────────────────── */ export function lintChangelog(src: string): { fixed: string; errors: string[] } { @@ -147,6 +165,10 @@ export function lintChangelog(src: string): { fixed: string; errors: string[] } const bracketed = line.match(/^## \[([^\]]+)\]\s*\((\d{4}-\d{2}-\d{2})\)/); if (bracketed) return `## [${bracketed[1]}] (${bracketed[2]})`; + // Bracketed with date but missing closing paren (e.g. "## [1.2.3] (2021-01-01") + const bracketedMissingClose = line.match(/^## \[([^\]]+)\]\s*\((\d{4}-\d{2}-\d{2})$/); + if (bracketedMissingClose) return `## [${bracketedMissingClose[1]}] (${bracketedMissingClose[2]})`; + // Bracketed but missing / malformed date const bracketedNoDate = line.match(/^## \[([^\]]+)\]/); if (bracketedNoDate) { @@ -169,22 +191,76 @@ export function lintChangelog(src: string): { fixed: string; errors: string[] } lines = lines.map(line => { const m = line.match(/^###\s+(.+)$/); if (!m) return line; - const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === m[1].trim().toLowerCase()); - return n ? `### ${n}` : `### ${m[1].trim()}`; + let key = m[1].trim(); + let n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === key.toLowerCase()); + // tolerate accidental plural: Fixeds -> Fixed + if (!n && /s$/i.test(key)) { + const singular = key.replace(/s$/i, ''); + n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === singular.toLowerCase()); + if (n) key = singular; + } + return n ? `### ${n}` : `### ${key}`; }); - /* 5. List items: "- " β†’ "* " */ - lines = lines.map(line => (/^- /.test(line) ? '* ' + line.slice(2) : line)); + /* 5. Handle indented sub-list items (" * ..." or " - ...") BEFORE normalising + * top-level bullets, so we can still detect the indentation. + * - If the nearest preceding unindented `* ` line ends with `:`, convert to ` - ` + * - If that parent line does NOT end with `:`, append `:` to it, then convert + * - If no unindented `* ` parent found in the same block β†’ simple indent error, + * de-indent to `* ` + * A blank line breaks the parent–child relationship. + */ + { + const out: string[] = []; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const indented = line.match(/^ [*-] (.*)$/); + if (!indented) { + out.push(line); + continue; + } + const text = indented[1].trimEnd(); + // Scan backwards through out[] for nearest unindented `* ` parent (stop at blank line) + let parentIdx = -1; + for (let j = out.length - 1; j >= 0; j--) { + if (out[j].trim() === '') break; + if (/^\* /.test(out[j])) { parentIdx = j; break; } + } + if (parentIdx !== -1) { + // Ensure parent ends with ':' (replace trailing '.' or ',' if present) + const parentTrimmed = out[parentIdx].trimEnd(); + if (!parentTrimmed.endsWith(':')) { + out[parentIdx] = parentTrimmed.replace(/[.,;]$/, '') + ':'; + } + out.push(` - ${text}`); + } else { + // No valid parent – simple indentation error, promote to top-level + out.push(`* ${text}`); + } + } + lines = out; + } + + /* 5b. Normalise remaining top-level bullet markers to "* " */ + lines = lines.map(line => { + const m = line.match(/^([*-]) (.*)$/); + if (m) return `* ${m[2].trimEnd()}`; + return line; + }); /* 6. Spacing rules */ const RELEASE_RE = /^## /; const SECTION_RE = /^### /; const TITLE_RE = /^# Changelog/; + // Ensure one blank line after the main title and after each release header + lines = normaliseBlankAfter(lines, TITLE_RE); lines = normaliseBlanksBefore(lines, RELEASE_RE, 1, TITLE_RE); lines = normaliseBlankAfter(lines, RELEASE_RE); + // Ensure exactly one blank before each section (###) but remove any blank lines + // immediately after a section heading (we require no blank-after for ###). lines = normaliseBlanksBefore(lines, SECTION_RE, 1, RELEASE_RE); - lines = normaliseBlankAfter(lines, SECTION_RE); + lines = removeBlankAfter(lines, SECTION_RE); /* 7. Collapse multiple blank lines, trailing newline */ lines = collapseBlankLines(lines); From 8db8d715b6f7b71ec8d0eddaf0495d18284d2908 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 21:29:10 +0200 Subject: [PATCH 10/27] chore: fix formatting inconsistencies in CHANGELOG.md --- CHANGELOG.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b533db7..783d76c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ * Enhanced file based execution support with improved multisite mode compatibility ### Changed -* Updated links to more recent documentation pages +* Updated links to more recent documentation pages ### Fixed * Fixed multisite capability checks in Plugin class @@ -215,10 +215,10 @@ ### Changed * Updated CSS to use latest Sass features. -* Moved theme selector to just above editor preview on settings page (thanks to [brandonjp]). ([#206](https://github.com/codesnippetspro/code-snippets/issues/206)) +* Moved theme selector to just above editor preview on settings page (thanks to [brandonjp]). ([#206](https://github.com/codesnippetspro/code-snippets/issues/206)) * `[code_snippet]` shortcodes can now be nested within each other. ([#198](https://github.com/codesnippetspro/code-snippets/issues/198)) -### Fixed +### Fixed * Save buttons above editor did not follow usual validation process in Pro. (PRO) ([#197](https://github.com/codesnippetspro/code-snippets/issues/197)) * Minor inconsistencies in consistent UI elements between Core and Pro. * Tags input not allowing input. ([#211](https://github.com/codesnippetspro/code-snippets/issues/211)) @@ -242,13 +242,13 @@ * Action hook `code_snippets/admin/manage` now includes the currently viewed type. ### Fixed -* Memory issue from checking aggregate posts while loading front-end syntax highlighter. +* Memory issue from checking aggregate posts while loading front-end syntax highlighter. * Translation functions being called too early on upgrade, resulting in localisation loading errors. * Bug preventing the 'share on network' status of network snippets from correctly updating. * Incorrect logic controlling when to display 'Save Changes' or 'Save Changes and Activate' buttons. * Old notices persisting when switching between editing and creating snippets. -## 3.6.5.1 (2024-05-24) +## [3.6.5.1] (2024-05-24) * Redeployment of [v3.6.5](#365-2024-05-24) to overcome issue with initial build. @@ -376,11 +376,11 @@ ### Changed * Better compatibility with modern versions of PHP (7.0+). -* Converted Edit/Add New Snippet page to use React. - * Converted action buttons to asynchronously use REST API endpoints through AJAX. - * Load page components dynamically through React. - * Added action notice queue system. - * Replaced native alert dialog with proper React modal. +* Converted Edit/Add New Snippet page to use React: + - Converted action buttons to asynchronously use REST API endpoints through AJAX. + - Load page components dynamically through React. + - Added action notice queue system + - Replaced native alert dialog with proper React modal. * Catch snippet execution errors to prevent site from crashing. * Display recent snippet errors in admin dashboard instead. * Updated editor block to use new REST API endpoints. (PRO) @@ -564,9 +564,9 @@ ### Added * Added translations: - * Spanish by [Ibidem Group](https://www.ibidemgroup.com) - * Urdu by [Samuel Badree](https://mobilemall.pk/) - * Greek by [Toni Bishop from Jrop](https://www.jrop.com/) + - Spanish by [Ibidem Group](https://www.ibidemgroup.com) + - Urdu by [Samuel Badree](https://mobilemall.pk/) + - Greek by [Toni Bishop from Jrop](https://www.jrop.com/) * Support for `:class` syntax to the code validator. * PHP8 support to the code linter. * Color picker feature to the code editor. @@ -1307,12 +1307,12 @@ ### Changed * Updated CodeMirror to version 2.33. -* Updated the 'Manage Snippets' page to use the WP_List_Table class. - * Added 'Screen Options' tab to 'Manage Snippets' page. - * Added search capability to 'Manage Snippets' page. - * Added views to easily filter activated, deactivated and recently activated snippets. - * Added ID column to 'Manage Snippets' page. - * Added sortable name and ID column on 'Manage Snippets' page ([#](https://wordpress.org/support/topic/plugin-code-snippets-suggestion-sort-by-snippet-name)) +* Updated the 'Manage Snippets' page to use the WP_List_Table class: + - Added 'Screen Options' tab to 'Manage Snippets' page. + - Added search capability to 'Manage Snippets' page. + - Added views to easily filter activated, deactivated and recently activated snippets. + - Added ID column to 'Manage Snippets' page. + - Added sortable name and ID column on 'Manage Snippets' page ([#](https://wordpress.org/support/topic/plugin-code-snippets-suggestion-sort-by-snippet-name)) * Improved API. * Lengthened snippet name field to 64 characters. ([#](https://wordpress.org/support/topic/plugin-code-snippets-snippet-title-limited-to-36-characters)) From 443be817c206987f8b8ffd11907e8fb0603a2579 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:51:40 +0200 Subject: [PATCH 11/27] chore: add postcss-hsl-legacy and update webpack-css --- config/postcss-hsl-legacy.ts | 208 +++++++++++++++++++++++++++++++++++ config/webpack-css.ts | 2 +- 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 config/postcss-hsl-legacy.ts diff --git a/config/postcss-hsl-legacy.ts b/config/postcss-hsl-legacy.ts new file mode 100644 index 00000000..07dc87d1 --- /dev/null +++ b/config/postcss-hsl-legacy.ts @@ -0,0 +1,208 @@ +interface HslMatch { + fn: 'hsl' | 'hsla' + h: string + s: string + l: string + alpha?: string +} + +interface DeclarationLike { + value?: string +} + +const GRAD_TO_DEG = 0.9 +const DEG_PER_TURN = 360 +const DEG_PER_PI = 180 +const PERCENT_DIVISOR = 100 +const ROUNDING_MULTIPLIER = 1000 + +const hslArgsRegex = new RegExp( + [ + String.raw`(?hsl)a?\s*\(\s*`, + String.raw`(?\d*\.?\d+(?:deg|grad|rad|turn)?)`, + String.raw`(?:\s+|(?:\s*,\s*))`, + String.raw`(?\d*\.?\d+%)`, + String.raw`(?:\s+|(?:\s*,\s*))`, + String.raw`(?\d*\.?\d+%)`, + String.raw`(?:\s*(?:\/|,)\s*(?\d*\.?\d+%?))?`, + String.raw`\s*\)` + ].join(''), + 'g' +) + +const hueWithUnitRegex = /^(?\d*\.?\d+)(?deg|grad|rad|turn)$/ + +const convertHueToDeg = (hue: string): string => { + const match = hueWithUnitRegex.exec(hue) + if (!match?.groups) { + return hue + } + + const value = Number(match.groups.value) + const unit = match.groups.unit + + const degrees = + 'deg' === unit + ? value + : 'grad' === unit + ? value * GRAD_TO_DEG + : 'rad' === unit + ? value * DEG_PER_PI / Math.PI + : value * DEG_PER_TURN + + return String(Math.round(degrees * ROUNDING_MULTIPLIER) / ROUNDING_MULTIPLIER) +} + +const normalizeAlpha = (alpha: string): string => { + if (alpha.includes('%')) { + const value = Number(alpha.slice(0, -1)) / PERCENT_DIVISOR + alpha = String(value) + } + + return alpha.replace(/^0\./, '.') +} + +const toLegacyHsl = (colorFn: string): HslMatch | null => { + hslArgsRegex.lastIndex = 0 + const match = hslArgsRegex.exec(colorFn) + if (!match?.groups) { + return null + } + + const alpha = match.groups.alpha + + return { + fn: alpha ? 'hsla' : 'hsl', + h: convertHueToDeg(match.groups.hue), + s: match.groups.s, + l: match.groups.l, + alpha: alpha ? normalizeAlpha(alpha) : undefined + } +} + +const isIdentChar = (char: string | undefined): boolean => Boolean(char && /[a-zA-Z0-9_-]/.test(char)) + +const isUnescapedQuote = (value: string, index: number, quote: '"' | "'"): boolean => + quote === value[index] && '\\' !== value[index - 1] + +const findFunctionEnd = (value: string, openParenIndex: number): number | null => { + let depth = 0 + let index = openParenIndex + + while (index < value.length) { + const char = value[index] + + if ('(' === char) { + depth += 1 + } else if (')' === char) { + depth -= 1 + if (0 === depth) { + return index + } + } + + index += 1 + } + + return null +} + +const legacyHslString = (fnText: string): string | null => { + const legacy = toLegacyHsl(fnText) + if (!legacy) { + return null + } + + if ('hsl' === legacy.fn) { + return `hsl(${legacy.h}, ${legacy.s}, ${legacy.l})` + } + + return `hsla(${legacy.h}, ${legacy.s}, ${legacy.l}, ${legacy.alpha})` +} + +const replaceHslAtIndex = ( + value: string, + index: number +): { nextIndex: number; text: string } | null => { + const isStart = value.startsWith('hsl', index) || value.startsWith('hsla', index) + if (!isStart || isIdentChar(value[index - 1])) { + return null + } + + const name = value.startsWith('hsla', index) ? 'hsla' : 'hsl' + let afterNameIndex = index + name.length + + while (afterNameIndex < value.length && /\s/.test(value[afterNameIndex])) { + afterNameIndex += 1 + } + + if ('(' !== value[afterNameIndex]) { + return null + } + + const endIndex = findFunctionEnd(value, afterNameIndex) + if (null === endIndex) { + return { nextIndex: value.length, text: value.slice(index) } + } + + const fnText = value.slice(index, endIndex + 1) + return { nextIndex: endIndex + 1, text: legacyHslString(fnText) ?? fnText } +} + +const transformHslFunctions = (value: string): string => { + let result = '' + let index = 0 + + let inSingle = false + let inDouble = false + + while (index < value.length) { + const char = value[index] + + if (!inDouble && isUnescapedQuote(value, index, "'")) { + inSingle = !inSingle + result += char + index += 1 + continue + } + + if (!inSingle && isUnescapedQuote(value, index, '"')) { + inDouble = !inDouble + result += char + index += 1 + continue + } + + if (inSingle || inDouble) { + result += char + index += 1 + continue + } + + const replacement = replaceHslAtIndex(value, index) + if (!replacement) { + result += char + index += 1 + continue + } + + result += replacement.text + index = replacement.nextIndex + } + + return result +} + +const postcssHslLegacy = () => ({ + postcssPlugin: 'postcss-hsl-legacy', + Declaration(decl: DeclarationLike) { + if (!decl.value || !decl.value.includes('hsl(') && !decl.value.includes('hsla(')) { + return + } + decl.value = transformHslFunctions(decl.value) + } +}) + +postcssHslLegacy.postcss = true + +export default postcssHslLegacy diff --git a/config/webpack-css.ts b/config/webpack-css.ts index 828d7a02..1e4f94e5 100644 --- a/config/webpack-css.ts +++ b/config/webpack-css.ts @@ -3,10 +3,10 @@ import libsass from 'sass' import cssnano from 'cssnano' import autoprefixer from 'autoprefixer' import rgbaCompat from 'postcss-hexrgba' -import hslCompat from 'postcss-color-hsl' import MiniCssExtractPlugin from 'mini-css-extract-plugin' import RemoveEmptyScriptsPlugin from 'webpack-remove-empty-scripts' import { glob } from 'glob' +import hslCompat from './postcss-hsl-legacy' import type { Configuration, EntryObject } from 'webpack' import type { Config as PostCssConfig } from 'postcss-load-config' From e81a7a120c7f24192051f05518846cab109b2554 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:51:56 +0200 Subject: [PATCH 12/27] chore: update devDependencies and lockfile --- package-lock.json | 210 +++++++++++++++++----------------------------- package.json | 11 ++- 2 files changed, 87 insertions(+), 134 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4bcd81e..570d858b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "react-select": "^5.10.0" }, "devDependencies": { - "@eslint/eslintrc": "^3.2.0", + "@eslint/eslintrc": "^3.3.3", "@eslint/js": "^9.20.0", "@playwright/test": "^1.48.0", "@stylistic/eslint-plugin": "^3.1.0", @@ -62,7 +62,6 @@ "lint-staged": "^15.5.2", "mini-css-extract-plugin": "^2.9.2", "postcss": "^8.5.2", - "postcss-color-hsl": "^2.0.0", "postcss-hexrgba": "^2.1.0", "postcss-load-config": "^6.0.1", "postcss-loader": "^8.1.1", @@ -1700,11 +1699,10 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.7", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } @@ -2176,6 +2174,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "dev": true, @@ -2187,6 +2202,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/js": { "version": "9.39.2", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", @@ -7148,6 +7170,23 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -7176,6 +7215,13 @@ "node": ">=10.13.0" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -7409,6 +7455,13 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "dev": true, @@ -8809,13 +8862,6 @@ "dev": true, "license": "ISC" }, - "node_modules/isnumeric": { - "version": "0.2.0", - "dev": true, - "engines": { - "node": ">= 0.8.x" - } - }, "node_modules/isobject": { "version": "3.0.1", "dev": true, @@ -10311,106 +10357,6 @@ "postcss": "^8.4.38" } }, - "node_modules/postcss-color-hsl": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0", - "units-css": "^0.4.0" - } - }, - "node_modules/postcss-color-hsl/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-color-hsl/node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-color-hsl/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/postcss-color-hsl/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-color-hsl/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/postcss-color-hsl/node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-color-hsl/node_modules/postcss": { - "version": "6.0.23", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-color-hsl/node_modules/postcss-value-parser": { - "version": "3.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-color-hsl/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-color-hsl/node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-colormin": { "version": "7.0.2", "dev": true, @@ -11084,6 +11030,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "dev": true, @@ -11313,10 +11269,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "license": "MIT" - }, "node_modules/regenerator-transform": { "version": "0.15.2", "dev": true, @@ -13272,15 +13224,6 @@ "node": ">=4" } }, - "node_modules/units-css": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "isnumeric": "^0.2.0", - "viewport-dimensions": "^0.2.0" - } - }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", @@ -13361,6 +13304,16 @@ "tslib": "^2.0.3" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-isomorphic-layout-effect": { "version": "1.2.0", "license": "MIT", @@ -13410,11 +13363,6 @@ "dev": true, "license": "MIT" }, - "node_modules/viewport-dimensions": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, "node_modules/w3c-keyname": { "version": "2.2.8", "license": "MIT" diff --git a/package.json b/package.json index 8106c761..f253c651 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "react-select": "^5.10.0" }, "devDependencies": { - "@eslint/eslintrc": "^3.2.0", + "@eslint/eslintrc": "^3.3.3", "@eslint/js": "^9.20.0", "@stylistic/eslint-plugin": "^3.1.0", "@stylistic/stylelint-plugin": "^3.1.2", @@ -100,7 +100,6 @@ "globals": "^15.14.0", "mini-css-extract-plugin": "^2.9.2", "postcss": "^8.5.2", - "postcss-color-hsl": "^2.0.0", "postcss-hexrgba": "^2.1.0", "postcss-load-config": "^6.0.1", "postcss-loader": "^8.1.1", @@ -134,7 +133,13 @@ "CHANGELOG.md": "ts-node scripts/linters/lint-changelog.ts" }, "overrides": { - "ajv": "8.18.0", + "@eslint/eslintrc": { + "ajv": "6.12.6" + }, + "eslint": { + "ajv": "6.12.6" + }, + "@babel/runtime": "7.28.6", "js-yaml": "4.1.1", "lodash": "4.17.23", "brace-expansion": "1.1.12", From 1a91b7c71456535e03ae295f1409bfd77c633fdb Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:52:09 +0200 Subject: [PATCH 13/27] chore: refactor lint-changelog to satisfy ESLint --- scripts/linters/lint-changelog.ts | 382 +++++++++++++++--------------- 1 file changed, 191 insertions(+), 191 deletions(-) diff --git a/scripts/linters/lint-changelog.ts b/scripts/linters/lint-changelog.ts index b02e525a..23be6630 100644 --- a/scripts/linters/lint-changelog.ts +++ b/scripts/linters/lint-changelog.ts @@ -1,5 +1,5 @@ /** - * lint-changelog.ts + * Lint-changelog.ts * * Lints and auto-fixes CHANGELOG.md for formatting consistency. * @@ -34,27 +34,28 @@ * - File ends with exactly one newline */ -import { readFileSync, writeFileSync, existsSync } from 'fs'; -import { resolve } from 'path'; +import { existsSync, readFileSync, writeFileSync } from 'fs' +import { resolve } from 'path' /* ── helpers ─────────────────────────────────────────────────────────── */ -const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security']; +const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security'] -function trimTrailing(lines: string[]): string[] { - return lines.map(l => l.trimEnd()); -} +const CLI_ARGS_START_INDEX = 2 + +const trimTrailing = (lines: string[]): string[] => + lines.map(l => l.trimEnd()) -function collapseBlankLines(lines: string[]): string[] { - const out: string[] = []; - let prevBlank = false; +const collapseBlankLines = (lines: string[]): string[] => { + const out: string[] = [] + let prevBlank = false for (const l of lines) { - const blank = l.trim() === ''; - if (blank && prevBlank) continue; - out.push(l); - prevBlank = blank; + const blank = '' === l.trim() + if (blank && prevBlank) {continue} + out.push(l) + prevBlank = blank } - return out; + return out } /** @@ -62,242 +63,241 @@ function collapseBlankLines(lines: string[]): string[] { * `headingRe`. Lines matching `skipAfterRe` suppress spacing for the immediately * following heading (used to avoid a blank line between a ## and its first ###). */ -function normaliseBlanksBefore( +const normaliseBlanksBefore = ( lines: string[], headingRe: RegExp, n: number, skipAfterRe?: RegExp -): string[] { - const out: string[] = []; - let suppressNext = true; // suppress before very first heading - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - if (skipAfterRe && skipAfterRe.test(line)) { - suppressNext = true; - out.push(line); - continue; +): string[] => { + const out: string[] = [] + let suppressNext = true // Suppress before very first heading + + for (const line of lines) { + if (skipAfterRe?.test(line)) { + suppressNext = true + out.push(line) + continue } if (headingRe.test(line)) { if (!suppressNext) { - while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); - for (let b = 0; b < n; b++) out.push(''); + while (0 < out.length && '' === out[out.length - 1].trim()) {out.pop()} + for (let b = 0; b < n; b += 1) {out.push('')} } - out.push(line); - suppressNext = false; - continue; + out.push(line) + suppressNext = false + continue } - if (line.trim() !== '') suppressNext = false; - out.push(line); + if ('' !== line.trim()) {suppressNext = false} + out.push(line) } - return out; + return out } /** Ensure exactly 1 blank line immediately after every line matching `headingRe`. */ -function normaliseBlankAfter(lines: string[], headingRe: RegExp): string[] { - const out: string[] = []; - let i = 0; +const normaliseBlankAfter = (lines: string[], headingRe: RegExp): string[] => { + const out: string[] = [] + let i = 0 while (i < lines.length) { - const line = lines[i]; - out.push(line); + const line = lines[i] + out.push(line) if (headingRe.test(line)) { - i++; - while (i < lines.length && lines[i].trim() === '') i++; - if (i < lines.length) out.push(''); - continue; + i += 1 + while (i < lines.length && '' === lines[i].trim()) {i += 1} + if (i < lines.length) {out.push('')} + continue } - i++; + i += 1 } - return out; + return out } /** Remove any blank lines immediately after lines matching `headingRe`. */ -function removeBlankAfter(lines: string[], headingRe: RegExp): string[] { - const out: string[] = []; - let i = 0; +const removeBlankAfter = (lines: string[], headingRe: RegExp): string[] => { + const out: string[] = [] + let i = 0 while (i < lines.length) { - const line = lines[i]; - out.push(line); + const line = lines[i] + out.push(line) if (headingRe.test(line)) { - i++; - // skip all blank lines following the heading - while (i < lines.length && lines[i].trim() === '') i++; - continue; + i += 1 + // Skip all blank lines following the heading + while (i < lines.length && '' === lines[i].trim()) {i += 1} + continue } - i++; + i += 1 } - return out; + return out } /* ── linter ─────────────────────────────────────────────────────────── */ -export function lintChangelog(src: string): { fixed: string; errors: string[] } { - const errors: string[] = []; - let lines = src.split('\n'); - - /* 1. File title */ - if (lines[0] !== '# Changelog') { +const ensureTitle = (lines: string[], errors: string[]): string[] => { + if ('# Changelog' !== lines[0]) { if (/^#\s+changelog/i.test(lines[0])) { - lines[0] = '# Changelog'; + lines[0] = '# Changelog' } else { - errors.push('CHANGELOG.md: First line must be "# Changelog"'); + errors.push('CHANGELOG.md: First line must be "# Changelog"') } } - lines = trimTrailing(lines); + return lines +} - /* 2. Promote bold change-type labels to ### headings */ - lines = lines.map(line => { - const m = line.match(/^\s*(?:\*\*|__)(\w+)(?:\*\*|__)\s*$/); - if (m) { - const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === m[1].toLowerCase()); - if (n) return `### ${n}`; +const promoteBoldChangeTypeLabels = (lines: string[]): string[] => + lines.map(line => { + const match = /^\s*(?:\*\*|__)(?\w+)(?:\*\*|__)\s*$/.exec(line) + if (!match?.groups) {return line} + const { type } = match.groups + const canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === type.toLowerCase()) + return canonical ? `### ${canonical}` : line + }) + +const normaliseReleaseHeaders = (lines: string[], errors: string[]): string[] => + lines.map(line => { + const bracketed = /^## \[(?[^\]]+)\]\s*\((?\d{4}-\d{2}-\d{2})\)/.exec(line) + if (bracketed?.groups) {return `## [${bracketed.groups.ver}] (${bracketed.groups.date})`} + + const bracketedMissingClose = /^## \[(?[^\]]+)\]\s*\((?\d{4}-\d{2}-\d{2})$/.exec(line) + if (bracketedMissingClose?.groups) { + return `## [${bracketedMissingClose.groups.ver}] (${bracketedMissingClose.groups.date})` } - return line; - }); - /* 3. Normalise release headers to ## [X.Y.Z] (YYYY-MM-DD) */ - lines = lines.map(line => { - // Already bracketed: ## [X.Y.Z] (YYYY-MM-DD) - const bracketed = line.match(/^## \[([^\]]+)\]\s*\((\d{4}-\d{2}-\d{2})\)/); - if (bracketed) return `## [${bracketed[1]}] (${bracketed[2]})`; - - // Bracketed with date but missing closing paren (e.g. "## [1.2.3] (2021-01-01") - const bracketedMissingClose = line.match(/^## \[([^\]]+)\]\s*\((\d{4}-\d{2}-\d{2})$/); - if (bracketedMissingClose) return `## [${bracketedMissingClose[1]}] (${bracketedMissingClose[2]})`; - - // Bracketed but missing / malformed date - const bracketedNoDate = line.match(/^## \[([^\]]+)\]/); + const bracketedNoDate = /^## \[(?[^\]]+)\]/.exec(line) if (bracketedNoDate) { - errors.push(`CHANGELOG.md: Release header missing or malformed date: ${line}`); - return line; + errors.push(`CHANGELOG.md: Release header missing or malformed date: ${line}`) + return line } - // Non-bracketed: ## X.Y.Z (YYYY-MM-DD) - const plain = line.match(/^## (\d[^\s(]+)\s*(?:\((\d{4}-\d{2}-\d{2})\))?/); - if (plain) { - if (plain[2]) return `## [${plain[1]}] (${plain[2]})`; - errors.push(`CHANGELOG.md: Release header missing date: ${line}`); - return `## [${plain[1]}]`; + const plain = /^## (?\d[^\s(]+)\s*(?:\((?\d{4}-\d{2}-\d{2})\))?/.exec(line) + if (!plain?.groups) {return line} + if (plain.groups.date) {return `## [${plain.groups.ver}] (${plain.groups.date})`} + errors.push(`CHANGELOG.md: Release header missing date: ${line}`) + return `## [${plain.groups.ver}]` + }) + +const normaliseSectionNames = (lines: string[]): string[] => + lines.map(line => { + const match = /^###\s+(?.+)$/.exec(line) + if (!match?.groups) {return line} + let key = match.groups.name.trim() + let canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === key.toLowerCase()) + if (!canonical && /s$/i.test(key)) { + const singular = key.replace(/s$/i, '') + canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === singular.toLowerCase()) + if (canonical) {key = singular} } + return canonical ? `### ${canonical}` : `### ${key}` + }) - return line; - }); - - /* 4. Normalise ### section names */ - lines = lines.map(line => { - const m = line.match(/^###\s+(.+)$/); - if (!m) return line; - let key = m[1].trim(); - let n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === key.toLowerCase()); - // tolerate accidental plural: Fixeds -> Fixed - if (!n && /s$/i.test(key)) { - const singular = key.replace(/s$/i, ''); - n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === singular.toLowerCase()); - if (n) key = singular; - } - return n ? `### ${n}` : `### ${key}`; - }); - - /* 5. Handle indented sub-list items (" * ..." or " - ...") BEFORE normalising - * top-level bullets, so we can still detect the indentation. - * - If the nearest preceding unindented `* ` line ends with `:`, convert to ` - ` - * - If that parent line does NOT end with `:`, append `:` to it, then convert - * - If no unindented `* ` parent found in the same block β†’ simple indent error, - * de-indent to `* ` - * A blank line breaks the parent–child relationship. - */ - { - const out: string[] = []; - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const indented = line.match(/^ [*-] (.*)$/); - if (!indented) { - out.push(line); - continue; - } - const text = indented[1].trimEnd(); - // Scan backwards through out[] for nearest unindented `* ` parent (stop at blank line) - let parentIdx = -1; - for (let j = out.length - 1; j >= 0; j--) { - if (out[j].trim() === '') break; - if (/^\* /.test(out[j])) { parentIdx = j; break; } +const normaliseIndentedSubListItems = (lines: string[]): string[] => { + const out: string[] = [] + + for (const line of lines) { + const indented = /^ {2}[*-] (?.*)$/.exec(line) + if (!indented?.groups) { + out.push(line) + continue + } + + const text = indented.groups.text.trimEnd() + let parentIdx = -1 + for (let j = out.length - 1; 0 <= j; j -= 1) { + if ('' === out[j].trim()) {break} + if (out[j].startsWith('* ')) { + parentIdx = j + break } - if (parentIdx !== -1) { - // Ensure parent ends with ':' (replace trailing '.' or ',' if present) - const parentTrimmed = out[parentIdx].trimEnd(); - if (!parentTrimmed.endsWith(':')) { - out[parentIdx] = parentTrimmed.replace(/[.,;]$/, '') + ':'; - } - out.push(` - ${text}`); - } else { - // No valid parent – simple indentation error, promote to top-level - out.push(`* ${text}`); + } + + if (-1 !== parentIdx) { + const parentTrimmed = out[parentIdx].trimEnd() + if (!parentTrimmed.endsWith(':')) { + out[parentIdx] = `${parentTrimmed.replace(/[.,;]$/, '')}:` } + out.push(` - ${text}`) + } else { + out.push(`* ${text}`) } - lines = out; } - /* 5b. Normalise remaining top-level bullet markers to "* " */ - lines = lines.map(line => { - const m = line.match(/^([*-]) (.*)$/); - if (m) return `* ${m[2].trimEnd()}`; - return line; - }); - - /* 6. Spacing rules */ - const RELEASE_RE = /^## /; - const SECTION_RE = /^### /; - const TITLE_RE = /^# Changelog/; - - // Ensure one blank line after the main title and after each release header - lines = normaliseBlankAfter(lines, TITLE_RE); - lines = normaliseBlanksBefore(lines, RELEASE_RE, 1, TITLE_RE); - lines = normaliseBlankAfter(lines, RELEASE_RE); - // Ensure exactly one blank before each section (###) but remove any blank lines - // immediately after a section heading (we require no blank-after for ###). - lines = normaliseBlanksBefore(lines, SECTION_RE, 1, RELEASE_RE); - lines = removeBlankAfter(lines, SECTION_RE); - - /* 7. Collapse multiple blank lines, trailing newline */ - lines = collapseBlankLines(lines); - while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop(); - lines.push(''); - - return { fixed: lines.join('\n'), errors }; + return out +} + +const normaliseTopLevelBulletMarkers = (lines: string[]): string[] => + lines.map(line => { + const match = /^(?[*-]) (?.*)$/.exec(line) + if (match?.groups) {return `* ${match.groups.content.trimEnd()}`} + return line + }) + +const applySpacingRules = (lines: string[]): string[] => { + const RELEASE_RE = /^## / + const SECTION_RE = /^### / + const TITLE_RE = /^# Changelog/ + + let out = lines + out = normaliseBlankAfter(out, TITLE_RE) + out = normaliseBlanksBefore(out, RELEASE_RE, 1, TITLE_RE) + out = normaliseBlankAfter(out, RELEASE_RE) + out = normaliseBlanksBefore(out, SECTION_RE, 1, RELEASE_RE) + out = removeBlankAfter(out, SECTION_RE) + return out +} + +const finaliseLines = (lines: string[]): string[] => { + const out = collapseBlankLines(lines) + while (0 < out.length && '' === out[out.length - 1]) {out.pop()} + out.push('') + return out +} + +export const lintChangelog = (src: string): { fixed: string; errors: string[] } => { + const errors: string[] = [] + let lines = src.split('\n') + + lines = ensureTitle(lines, errors) + lines = trimTrailing(lines) + lines = promoteBoldChangeTypeLabels(lines) + lines = normaliseReleaseHeaders(lines, errors) + lines = normaliseSectionNames(lines) + lines = normaliseIndentedSubListItems(lines) + lines = normaliseTopLevelBulletMarkers(lines) + lines = applySpacingRules(lines) + lines = finaliseLines(lines) + + return { fixed: lines.join('\n'), errors } } /* ── entry point ─────────────────────────────────────────────────────── */ -const root = resolve(__dirname, '../..'); -const args = process.argv.slice(2); -const files = args.length > 0 ? args : [resolve(root, 'CHANGELOG.md')]; -let anyErrors = false; -let anyProcessed = false; +const root = resolve(__dirname, '../..') +const args = process.argv.slice(CLI_ARGS_START_INDEX) +const files = 0 < args.length ? args : [resolve(root, 'CHANGELOG.md')] +let anyErrors = false +let anyProcessed = false for (const f of files) { - const abs = resolve(f); - if (!abs.endsWith('CHANGELOG.md')) continue; - anyProcessed = true; + const abs = resolve(f) + if (!abs.endsWith('CHANGELOG.md')) {continue} + anyProcessed = true - if (!existsSync(abs)) { console.error(`lint-changelog: file not found – ${abs}`); anyErrors = true; continue; } + if (!existsSync(abs)) { console.error(`lint-changelog: file not found – ${abs}`); anyErrors = true; continue } - const src = readFileSync(abs, 'utf8'); - const { fixed, errors } = lintChangelog(src); + const src = readFileSync(abs, 'utf8') + const { fixed, errors } = lintChangelog(src) - errors.forEach(e => console.error(` βœ— ${e}`)); - if (errors.length > 0) anyErrors = true; + errors.forEach(e => console.error(` βœ— ${e}`)) + if (0 < errors.length) {anyErrors = true} if (fixed !== src) { - writeFileSync(abs, fixed, 'utf8'); - console.log(` βœ” auto-fixed: ${abs}`); + writeFileSync(abs, fixed, 'utf8') + console.log(` βœ” auto-fixed: ${abs}`) } else { - console.log(` βœ” no changes: ${abs}`); + console.log(` βœ” no changes: ${abs}`) } } -if (!anyProcessed) process.exit(0); -process.exit(anyErrors ? 1 : 0); +if (!anyProcessed) {process.exit(0)} +process.exit(anyErrors ? 1 : 0) From 5bb09aa52ad5a2a786dde9c47ca72dda85fffeb1 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:52:22 +0200 Subject: [PATCH 14/27] chore: refactor lint-readme to satisfy ESLint --- scripts/linters/lint-readme.ts | 404 +++++++++++++++++---------------- 1 file changed, 213 insertions(+), 191 deletions(-) diff --git a/scripts/linters/lint-readme.ts b/scripts/linters/lint-readme.ts index a2b1f797..f14f58ee 100644 --- a/scripts/linters/lint-readme.ts +++ b/scripts/linters/lint-readme.ts @@ -1,5 +1,5 @@ /** - * lint-readme.ts + * Lint-readme.ts * * Lints and auto-fixes src/readme.txt for WordPress.org formatting consistency. * @@ -40,15 +40,19 @@ * - File ends with exactly one newline */ -import { readFileSync, writeFileSync, existsSync } from 'fs'; -import { resolve } from 'path'; +import { existsSync, readFileSync, writeFileSync } from 'fs' +import { resolve } from 'path' /* ── helpers ─────────────────────────────────────────────────────────── */ -const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security']; +const KNOWN_CHANGE_TYPES = ['Added', 'Changed', 'Fixed', 'Removed', 'Deprecated', 'Security'] -const RE_DATE_SRC = '\\d{4}-\\d{2}-\\d{2}'; -const RE_VERSION_SRC = '\\d+\\.\\d+(?:\\.\\d+)*(?:-[a-zA-Z0-9.]+)?'; +const CLI_ARGS_START_INDEX = 2 +const SUBSECTION_TITLECASE_MAX_WORDS = 2 +const LIST_MARKER_LENGTH = 2 + +const RE_DATE_SRC = '\\d{4}-\\d{2}-\\d{2}' +const RE_VERSION_SRC = '\\d+\\.\\d+(?:\\.\\d+)*(?:-[a-zA-Z0-9.]+)?' /** Known == Section == names (canonical capitalisation). */ const KNOWN_SECTIONS: Record = { @@ -59,42 +63,37 @@ const KNOWN_SECTIONS: Record = { 'screenshots': 'Screenshots', 'changelog': 'Changelog', 'upgrade notice': 'Upgrade Notice', -}; - -function titleCase(s: string): string { - return s.replace(/\w\S*/g, t => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase()); } -/** Sentence-case: capitalise only the first word. */ -function sentenceCase(s: string): string { - return s.charAt(0).toUpperCase() + s.slice(1); -} +const titleCase = (s: string): string => + s.replace(/\w\S*/g, t => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase()) -/** Title-case for ≀ 2 words, sentence-case for 3+ words. */ -function subsectionCase(s: string): string { - const wordCount = s.trim().split(/\s+/).length; - return wordCount <= 2 ? titleCase(s) : sentenceCase(s); -} +const sentenceCase = (s: string): string => + s.charAt(0).toUpperCase() + s.slice(1) -function normaliseSectionName(raw: string): string { - const key = raw.trim().toLowerCase(); - return KNOWN_SECTIONS[key] ?? titleCase(raw.trim()); +const subsectionCase = (s: string): string => { + const wordCount = s.trim().split(/\s+/).length + return SUBSECTION_TITLECASE_MAX_WORDS >= wordCount ? titleCase(s) : sentenceCase(s) } -function trimTrailing(lines: string[]): string[] { - return lines.map(l => l.trimEnd()); +const normaliseSectionName = (raw: string): string => { + const key = raw.trim().toLowerCase() + return KNOWN_SECTIONS[key] ?? titleCase(raw.trim()) } -function collapseBlankLines(lines: string[]): string[] { - const out: string[] = []; - let prevBlank = false; +const trimTrailing = (lines: string[]): string[] => + lines.map(l => l.trimEnd()) + +const collapseBlankLines = (lines: string[]): string[] => { + const out: string[] = [] + let prevBlank = false for (const l of lines) { - const blank = l.trim() === ''; - if (blank && prevBlank) continue; - out.push(l); - prevBlank = blank; + const blank = '' === l.trim() + if (blank && prevBlank) {continue} + out.push(l) + prevBlank = blank } - return out; + return out } /** @@ -102,224 +101,247 @@ function collapseBlankLines(lines: string[]): string[] { * `headingRe`. Lines matching `skipAfterRe` reset the "just-saw-section-start" * flag, suppressing spacing for the immediately following heading. */ -function normaliseBlanksBefore( +const normaliseBlanksBefore = ( lines: string[], headingRe: RegExp, n: number, skipAfterRe?: RegExp -): string[] { - const out: string[] = []; - let suppressNext = true; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - if (skipAfterRe && skipAfterRe.test(line)) { - suppressNext = true; - out.push(line); - continue; +): string[] => { + const out: string[] = [] + let suppressNext = true + + for (const line of lines) { + if (skipAfterRe?.test(line)) { + suppressNext = true + out.push(line) + continue } if (headingRe.test(line)) { if (!suppressNext) { - while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); - for (let b = 0; b < n; b++) out.push(''); + while (0 < out.length && '' === out[out.length - 1].trim()) {out.pop()} + for (let b = 0; b < n; b += 1) {out.push('')} } - out.push(line); - suppressNext = false; - continue; + out.push(line) + suppressNext = false + continue } - if (line.trim() !== '') suppressNext = false; - out.push(line); + if ('' !== line.trim()) {suppressNext = false} + out.push(line) } - return out; + return out } /** Ensure exactly 1 blank line immediately after every line matching `headingRe`. */ -function normaliseBlankAfter(lines: string[], headingRe: RegExp): string[] { - const out: string[] = []; - let i = 0; +const normaliseBlankAfter = (lines: string[], headingRe: RegExp): string[] => { + const out: string[] = [] + let i = 0 while (i < lines.length) { - const line = lines[i]; - out.push(line); + const line = lines[i] + out.push(line) if (headingRe.test(line)) { - i++; - while (i < lines.length && lines[i].trim() === '') i++; - if (i < lines.length) out.push(''); - continue; + i += 1 + while (i < lines.length && '' === lines[i].trim()) {i += 1} + if (i < lines.length) {out.push('')} + continue } - i++; + i += 1 } - return out; + return out } /** * Like normaliseBlankAfter but only operates on lines that fall within a * specific section (between `sectionStartRe` and the next `== ... ==` heading). */ -function normaliseBlankAfterInSection( +const normaliseBlankAfterInSection = ( lines: string[], sectionStartRe: RegExp, headingRe: RegExp -): string[] { - const out: string[] = []; - let inSection = false; - let i = 0; +): string[] => { + const out: string[] = [] + let inSection = false + let i = 0 while (i < lines.length) { - const line = lines[i]; - if (sectionStartRe.test(line)) inSection = true; - else if (/^== .+ ==$/.test(line)) inSection = false; + const line = lines[i] + if (sectionStartRe.test(line)) {inSection = true} + else if (/^== .+ ==$/.test(line)) {inSection = false} - out.push(line); + out.push(line) if (inSection && headingRe.test(line)) { - i++; - while (i < lines.length && lines[i].trim() === '') i++; - if (i < lines.length) out.push(''); - continue; + i += 1 + while (i < lines.length && '' === lines[i].trim()) {i += 1} + if (i < lines.length) {out.push('')} + continue } - i++; + i += 1 } - return out; + return out } /* ── linter ─────────────────────────────────────────────────────────── */ -export function lintReadme(src: string): { fixed: string; errors: string[] } { - const errors: string[] = []; - let lines = src.split('\n'); - - /* 1. Plugin name header */ +const normalisePluginHeader = (lines: string[], errors: string[]): string[] => { if (!/^=== .+ ===$/.test(lines[0])) { - errors.push('readme.txt: First line must be "=== Plugin Name ==="'); + errors.push('readme.txt: First line must be "=== Plugin Name ==="') } + return lines +} - lines = trimTrailing(lines); - - /* 2. Normalise header field spacing: "Key: Value" */ - let inHeader = true; - lines = lines.map((line, i) => { - if (inHeader && i > 0 && line.trim() === '') { inHeader = false; return line; } - if (!inHeader) return line; - const m = line.match(/^([A-Za-z][A-Za-z ]+):\s*(.*)$/); - if (m) return `${m[1].trim()}: ${m[2].trim()}`; - return line; - }); - - /* 2a. Ensure exactly one blank line after the last header field (before short description). - * If the blank was removed the header parser above never terminates, so we fix it here - * by finding the last "Key: Value" line and inserting a blank after it when missing. */ - { - const FIELD_RE = /^[A-Za-z][A-Za-z ]+: /; - let lastFieldIdx = -1; - for (let i = 1; i < lines.length; i++) { - if (/^== /.test(lines[i])) break; // hit a section heading – header is long gone - if (FIELD_RE.test(lines[i])) lastFieldIdx = i; +const normaliseHeaderFieldSpacing = (lines: string[]): string[] => { + let inHeader = true + return lines.map((line, i) => { + if (inHeader && 0 < i && '' === line.trim()) { + inHeader = false + return line } - if (lastFieldIdx !== -1) { - const afterField = lines[lastFieldIdx + 1]; - if (afterField !== undefined && afterField.trim() !== '') { - // No blank line after last field – insert one - lines.splice(lastFieldIdx + 1, 0, ''); - } + if (!inHeader) {return line} + const match = /^(?[A-Za-z][A-Za-z ]+):\s*(?.*)$/.exec(line) + if (match?.groups) {return `${match.groups.key.trim()}: ${match.groups.value.trim()}`} + return line + }) +} + +const ensureBlankAfterLastHeaderField = (lines: string[]): string[] => { + const FIELD_RE = /^[A-Za-z][A-Za-z ]+: / + let lastFieldIdx = -1 + + for (const [i, line] of lines.entries()) { + if (0 === i) {continue} + if (line.startsWith('== ')) {break} + if (FIELD_RE.test(line)) {lastFieldIdx = i} + } + + if (-1 !== lastFieldIdx && lastFieldIdx + 1 < lines.length) { + if ('' !== lines[lastFieldIdx + 1].trim()) { + lines.splice(lastFieldIdx + 1, 0, '') } } - /* 3. Normalise == Section == headings */ - lines = lines.map(line => { - const m = line.match(/^==\s+(.+?)\s+==$/); - if (m) return `== ${normaliseSectionName(m[1])} ==`; - return line; - }); - - /* 4. Normalise = Sub Section = headings */ - lines = lines.map(line => { - const m = line.match(/^=\s+(.+?)\s+=$/); - if (!m) return line; - const inner = m[1].trim(); - // Version entry inside Changelog: "= X.Y.Z (YYYY-MM-DD) =" - const ver = inner.match(new RegExp(`^(${RE_VERSION_SRC})\\s+\\((${RE_DATE_SRC})\\)$`)); - if (ver) return `= ${ver[1]} (${ver[2]}) =`; - return `= ${subsectionCase(inner)} =`; - }); - - /* 5. Inside Changelog section: demote ### headings and **Bold** to __Type__ */ - let inChangelog = false; - lines = lines.map(line => { - if (/^== Changelog ==$/.test(line)) { inChangelog = true; return line; } - if (/^== /.test(line)) { inChangelog = false; return line; } - if (!inChangelog) return line; - - const hashM = line.match(/^###\s+(\w+)\s*$/); - if (hashM) { - const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === hashM[1].toLowerCase()); - if (n) return `__${n}__`; + return lines +} + +const normaliseSectionHeadings = (lines: string[]): string[] => + lines.map(line => { + const match = /^==\s+(?.+?)\s+==$/.exec(line) + if (match?.groups) {return `== ${normaliseSectionName(match.groups.name)} ==`} + return line + }) + +const normaliseSubSectionHeadings = (lines: string[]): string[] => + lines.map(line => { + const match = /^=\s+(?.+?)\s+=$/.exec(line) + if (!match?.groups) {return line} + const inner = match.groups.name.trim() + const ver = new RegExp(`^(?${RE_VERSION_SRC})\\s+\\((?${RE_DATE_SRC})\\)$`).exec(inner) + if (ver?.groups) {return `= ${ver.groups.ver} (${ver.groups.date}) =`} + return `= ${subsectionCase(inner)} =` + }) + +const normaliseChangelogChangeTypes = (lines: string[]): string[] => { + let inChangelog = false + return lines.map(line => { + if (/^== Changelog ==$/.test(line)) { + inChangelog = true + return line + } + if (line.startsWith('== ')) { + inChangelog = false + return line + } + if (!inChangelog) {return line} + + const hashM = /^###\s+(?\w+)\s*$/.exec(line) + if (hashM?.groups) { + const canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === hashM.groups.type.toLowerCase()) + if (canonical) {return `__${canonical}__`} } - const boldM = line.match(/^\*\*(\w+)\*\*\s*$/); - if (boldM) { - const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === boldM[1].toLowerCase()); - if (n) return `__${n}__`; + const boldM = /^\*\*(?\w+)\*\*\s*$/.exec(line) + if (boldM?.groups) { + const canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === boldM.groups.type.toLowerCase()) + if (canonical) {return `__${canonical}__`} } - // Normalise existing __type__ casing - const underM = line.match(/^__(\w+)__\s*$/); - if (underM) { - const n = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === underM[1].toLowerCase()); - if (n) return `__${n}__`; + const underM = /^__(?\w+)__\s*$/.exec(line) + if (underM?.groups) { + const canonical = KNOWN_CHANGE_TYPES.find(t => t.toLowerCase() === underM.groups.type.toLowerCase()) + if (canonical) {return `__${canonical}__`} } - return line; - }); - - /* 6. List items: "- " β†’ "* " */ - lines = lines.map(line => (/^- /.test(line) ? '* ' + line.slice(2) : line)); - - /* 7. Spacing rules */ - const SECTION_RE = /^== .+ ==$/; - const SUBSECTION_RE = /^= .+ =$/; - const CHANGETYPE_RE = /^__(?:Added|Changed|Fixed|Removed|Deprecated|Security)__$/; - - lines = normaliseBlanksBefore(lines, SECTION_RE, 1, /^=== .+ ===/); - lines = normaliseBlankAfter(lines, SECTION_RE); - lines = normaliseBlanksBefore(lines, SUBSECTION_RE, 1, SECTION_RE); - lines = normaliseBlankAfterInSection(lines, /^== Changelog ==$/, SUBSECTION_RE); - lines = normaliseBlanksBefore(lines, CHANGETYPE_RE, 1, SUBSECTION_RE); - lines = normaliseBlankAfterInSection(lines, /^== Changelog ==$/, CHANGETYPE_RE); - - /* 8. Collapse multiple blank lines, trailing newline */ - lines = collapseBlankLines(lines); - while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop(); - lines.push(''); - - return { fixed: lines.join('\n'), errors }; + return line + }) +} + +const normaliseListItems = (lines: string[]): string[] => + lines.map(line => line.startsWith('- ') ? `* ${line.slice(LIST_MARKER_LENGTH)}` : line) + +const applySpacingRules = (lines: string[]): string[] => { + const SECTION_RE = /^== .+ ==$/ + const SUBSECTION_RE = /^= .+ =$/ + const CHANGETYPE_RE = /^__(?:Added|Changed|Fixed|Removed|Deprecated|Security)__$/ + + let out = lines + out = normaliseBlanksBefore(out, SECTION_RE, 1, /^=== .+ ===/) + out = normaliseBlankAfter(out, SECTION_RE) + out = normaliseBlanksBefore(out, SUBSECTION_RE, 1, SECTION_RE) + out = normaliseBlankAfterInSection(out, /^== Changelog ==$/, SUBSECTION_RE) + out = normaliseBlanksBefore(out, CHANGETYPE_RE, 1, SUBSECTION_RE) + out = normaliseBlankAfterInSection(out, /^== Changelog ==$/, CHANGETYPE_RE) + return out +} + +const finaliseLines = (lines: string[]): string[] => { + const out = collapseBlankLines(lines) + while (0 < out.length && '' === out[out.length - 1]) {out.pop()} + out.push('') + return out +} + +export const lintReadme = (src: string): { fixed: string; errors: string[] } => { + const errors: string[] = [] + let lines = src.split('\n') + + lines = normalisePluginHeader(lines, errors) + lines = trimTrailing(lines) + lines = normaliseHeaderFieldSpacing(lines) + lines = ensureBlankAfterLastHeaderField(lines) + lines = normaliseSectionHeadings(lines) + lines = normaliseSubSectionHeadings(lines) + lines = normaliseChangelogChangeTypes(lines) + lines = normaliseListItems(lines) + lines = applySpacingRules(lines) + lines = finaliseLines(lines) + + return { fixed: lines.join('\n'), errors } } /* ── entry point ─────────────────────────────────────────────────────── */ -const root = resolve(__dirname, '../..'); -const args = process.argv.slice(2); -const files = args.length > 0 ? args : [resolve(root, 'src/readme.txt')]; -let anyErrors = false; -let anyProcessed = false; +const root = resolve(__dirname, '../..') +const args = process.argv.slice(CLI_ARGS_START_INDEX) +const files = 0 < args.length ? args : [resolve(root, 'src/readme.txt')] +let anyErrors = false +let anyProcessed = false for (const f of files) { - const abs = resolve(f); - if (!abs.endsWith('readme.txt')) continue; - anyProcessed = true; + const abs = resolve(f) + if (!abs.endsWith('readme.txt')) {continue} + anyProcessed = true - if (!existsSync(abs)) { console.error(`lint-readme: file not found – ${abs}`); anyErrors = true; continue; } + if (!existsSync(abs)) { console.error(`lint-readme: file not found – ${abs}`); anyErrors = true; continue } - const src = readFileSync(abs, 'utf8'); - const { fixed, errors } = lintReadme(src); + const src = readFileSync(abs, 'utf8') + const { fixed, errors } = lintReadme(src) - errors.forEach(e => console.error(` βœ— ${e}`)); - if (errors.length > 0) anyErrors = true; + errors.forEach(e => console.error(` βœ— ${e}`)) + if (0 < errors.length) {anyErrors = true} if (fixed !== src) { - writeFileSync(abs, fixed, 'utf8'); - console.log(` βœ” auto-fixed: ${abs}`); + writeFileSync(abs, fixed, 'utf8') + console.log(` βœ” auto-fixed: ${abs}`) } else { - console.log(` βœ” no changes: ${abs}`); + console.log(` βœ” no changes: ${abs}`) } } -if (!anyProcessed) process.exit(0); -process.exit(anyErrors ? 1 : 0); +if (!anyProcessed) {process.exit(0)} +process.exit(anyErrors ? 1 : 0) From 664aadd8ade3f2b69dca91c3363f94f2988181d6 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:52:35 +0200 Subject: [PATCH 15/27] fix: remove unnecessary toString() and fix indentation in SnippetForm.tsx --- src/js/components/EditMenu/SnippetForm/SnippetForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/components/EditMenu/SnippetForm/SnippetForm.tsx b/src/js/components/EditMenu/SnippetForm/SnippetForm.tsx index 0fe4ae2f..4dbf71bd 100644 --- a/src/js/components/EditMenu/SnippetForm/SnippetForm.tsx +++ b/src/js/components/EditMenu/SnippetForm/SnippetForm.tsx @@ -89,7 +89,7 @@ const EditForm: React.FC = ({ children, className }) => { submitSnippet(snippet, action) .then(response => { if (response && 0 !== response.id && window.CODE_SNIPPETS) { - if (window.location.href.toString().includes(window.CODE_SNIPPETS.urls.addNew)) { + if (window.location.href.includes(window.CODE_SNIPPETS.urls.addNew)) { document.title = document.title .replace(__('Create New Snippet', 'code-snippets'), __('Edit Snippet', 'code-snippets')) .replace(__('Create New Condition', 'code-snippets'), __('Edit Condition', 'code-snippets')) From f7b117430e50a6ef924c2c36e3f317a98fbf164d Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:52:48 +0200 Subject: [PATCH 16/27] fix: guard against undefined searchResults in CloudSearch --- src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx b/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx index c1c22017..a24651ca 100644 --- a/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx +++ b/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx @@ -106,7 +106,7 @@ export const CloudSearch = () => { {error && } - {0 < page && searchResults && 0 === searchResults.length + {0 < page && 0 === searchResults?.length ? : From bcc77916b957ca5ef4edf634364fd4d7ed84a97d Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:53:02 +0200 Subject: [PATCH 17/27] fix: use optional chaining in admin-bar pagination update --- src/js/entries/admin-bar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/entries/admin-bar.ts b/src/js/entries/admin-bar.ts index 444efec0..c7b42789 100644 --- a/src/js/entries/admin-bar.ts +++ b/src/js/entries/admin-bar.ts @@ -238,7 +238,7 @@ const replaceSnippetItems = (status: PaginationStatus, snippets: SnippetResponse fragment.appendChild(li) } - if (insertAfter && insertAfter.parentNode === subMenu) { + if (insertAfter?.parentNode === subMenu) { subMenu.insertBefore(fragment, insertAfter.nextSibling) } else { subMenu.appendChild(fragment) From 9e496e2532a37c49b61fa97e547688d0ec87bd49 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:53:19 +0200 Subject: [PATCH 18/27] fix: stylelint fixes in admin-bar.scss --- src/css/admin-bar.scss | 102 ++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/css/admin-bar.scss b/src/css/admin-bar.scss index de7b2a8e..8da2b46f 100644 --- a/src/css/admin-bar.scss +++ b/src/css/admin-bar.scss @@ -1,80 +1,45 @@ #wpadminbar { #wp-admin-bar-code-snippets > .ab-item { .code-snippets-admin-bar-icon { - width: 16px; - height: 16px; - top: 5px; + inline-size: 16px; + block-size: 16px; + inset-block-start: 5px; &::before { content: ''; display: block; - width: 16px; - height: 16px; + inline-size: 16px; + block-size: 16px; mask-image: url('../assets/menu-icon.svg'); mask-repeat: no-repeat; mask-position: center; mask-size: contain; - background-color: rgba(240, 245, 250, 0.6); + background-color: rgb(240 245 250 / 60%); } } } + .code-snippets-pagination-node > .ab-item { + padding: 0; + margin-block-end: 6px; + } + .code-snippets-safe-mode-active { > .ab-item, &.ab-item { background: #b32d2e; color: #fff; } - - &:hover > .ab-item, - &.hover > .ab-item { - background: #d63638; - color: #fff; - } - } - - .code-snippets-safe-mode.code-snippets-safe-mode-active > .ab-item, - .code-snippets-safe-mode.code-snippets-safe-mode-active.ab-item { - font-weight: 600; - } - - .code-snippets-safe-mode .code-snippets-external-icon { - font-family: dashicons; - display: inline-block; - position: relative; - line-height: 1; - opacity: .8; - top: 6px; - } - - .code-snippets-safe-mode:hover .code-snippets-external-icon, - .code-snippets-safe-mode.hover .code-snippets-external-icon { - opacity: 1; - } - - #wp-admin-bar-code-snippets-active-snippets > .ab-sub-wrapper > .ab-submenu, - #wp-admin-bar-code-snippets-inactive-snippets > .ab-sub-wrapper > .ab-submenu { - padding-top: 0; } .code-snippets-disabled > .ab-item { opacity: 0.6; } - .code-snippets-disabled:hover > .ab-item, - .code-snippets-disabled.hover > .ab-item { - opacity: 1; - } - - .code-snippets-pagination-node > .ab-item { - padding: 0; - margin-bottom: 6px; - } - .code-snippets-pagination-controls { display: flex; align-items: stretch; - width: 100%; + inline-size: 100%; white-space: nowrap; .code-snippets-pagination-button { @@ -82,16 +47,16 @@ align-items: center; justify-content: center; flex: 1 1 0; - min-height: 32px; + min-block-size: 32px; padding: 0 10px; - background: rgba(240, 245, 250, 0.08); + background: rgb(240 245 250 / 8%); color: inherit; text-decoration: none; line-height: 1.2; box-sizing: border-box; & + .code-snippets-pagination-button { - border-left: 1px solid rgba(240, 245, 250, 0.15); + border-inline-start: 1px solid rgb(240 245 250 / 15%); } &[aria-disabled='true'] { @@ -101,7 +66,7 @@ } a.code-snippets-pagination-button:hover { - background: rgba(240, 245, 250, 0.16); + background: rgb(240 245 250 / 16%); } a[data-action='first'], @@ -116,4 +81,39 @@ opacity: 0.85; } } + + .code-snippets-safe-mode-active:hover > .ab-item, + .code-snippets-safe-mode-active.hover > .ab-item { + background: #d63638; + color: #fff; + } + + .code-snippets-disabled:hover > .ab-item, + .code-snippets-disabled.hover > .ab-item { + opacity: 1; + } + + .code-snippets-safe-mode.code-snippets-safe-mode-active > .ab-item, + .code-snippets-safe-mode.code-snippets-safe-mode-active.ab-item { + font-weight: 600; + } + + .code-snippets-safe-mode .code-snippets-external-icon { + font-family: dashicons; + display: inline-block; + position: relative; + line-height: 1; + opacity: .8; + inset-block-start: 6px; + } + + .code-snippets-safe-mode:hover .code-snippets-external-icon, + .code-snippets-safe-mode.hover .code-snippets-external-icon { + opacity: 1; + } + + #wp-admin-bar-code-snippets-active-snippets > .ab-sub-wrapper > .ab-submenu, + #wp-admin-bar-code-snippets-inactive-snippets > .ab-sub-wrapper > .ab-submenu { + padding-block-start: 0; + } } From 3106c2af1f17d6c62f6fc350b5467803fb8b6628 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:53:33 +0200 Subject: [PATCH 19/27] fix: stylelint fixes in _badges.scss --- src/css/common/_badges.scss | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/css/common/_badges.scss b/src/css/common/_badges.scss index 9d842b45..0f87454e 100644 --- a/src/css/common/_badges.scss +++ b/src/css/common/_badges.scss @@ -62,6 +62,11 @@ gap: 2px; } +.nav-tab-button .dashicons-external { + font-size: 15px; + color: #666; +} + @each $name, $colors in theme.$badges { $text-color: #fff; $background-color: list.nth($colors, 1); @@ -99,6 +104,8 @@ $text-color: list.nth($colors, 2); $background-color: list.nth($colors, 1); + background: transparent; + .badge.pro-badge { color: $text-color; background-color: $background-color; @@ -115,12 +122,3 @@ } } } - -.nav-tab-inactive { - background: transparent; -} - -.nav-tab-button .dashicons-external { - font-size: 15px; - color: #666; -} From 91947c4da1e8c89b3fc4df5b9a0fce8b48c97749 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:53:46 +0200 Subject: [PATCH 20/27] fix: stylelint fixes in _toolbar.scss --- src/css/common/_toolbar.scss | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/css/common/_toolbar.scss b/src/css/common/_toolbar.scss index b260d7a3..12faf84e 100644 --- a/src/css/common/_toolbar.scss +++ b/src/css/common/_toolbar.scss @@ -58,10 +58,6 @@ $wpbody-block-indent: 20px; a { color: inherit; text-decoration: none; - - &.active-link, &:hover, &:focus, &:active { - color: #2271b1; - } } } @@ -99,6 +95,13 @@ $wpbody-block-indent: 20px; } } +.code-snippets-toolbar-upper li a.active-link, +.code-snippets-toolbar-upper li a:hover, +.code-snippets-toolbar-upper li a:focus, +.code-snippets-toolbar-upper li a:active { + color: #2271b1; +} + .code-snippets-toolbar-lower .pro-chip, .nav-tab .pro-chip { color: #d46f4d; From 3da7f1ee221e4664d0eebd0ce0e794b8005c40b6 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:54:01 +0200 Subject: [PATCH 21/27] fix: stylelint fixes in _sidebar.scss --- src/css/edit/_sidebar.scss | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/css/edit/_sidebar.scss b/src/css/edit/_sidebar.scss index bec3bff1..b7805c5d 100644 --- a/src/css/edit/_sidebar.scss +++ b/src/css/edit/_sidebar.scss @@ -1,5 +1,20 @@ @use '../common/theme'; +.snippet-priority input { + inline-size: 4em; +} + +.activation-switch-container, +.lock-control-container { + label { + display: flex; + flex-flow: row; + gap: 5px; + justify-content: center; + align-items: center; + } +} + .code-snippets-modal { p h4 { margin-block-start: 0; @@ -23,6 +38,11 @@ .delete-button { color: #cc1818; + &:disabled { + color: #a7aaad; + cursor: not-allowed; + } + &:hover:not(:disabled) { color: #9e1313; } @@ -31,11 +51,6 @@ color: #710d0d; border-color: #710d0d; } - - &:disabled { - color: #a7aaad; - cursor: not-allowed; - } } .help-tooltip { @@ -114,10 +129,6 @@ } } -.snippet-priority input { - inline-size: 4em; -} - p.submit { display: flex; flex-flow: column; @@ -126,17 +137,6 @@ p.submit { padding-block-start: 0; } -.activation-switch-container, -.lock-control-container { - label { - display: flex; - flex-flow: row; - gap: 5px; - justify-content: center; - align-items: center; - } -} - .shortcode-tag-wrapper { background: #fff; min-block-size: 54px; From 7de4636a76e76cf13234fc78729816fb592ae7a8 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:54:13 +0200 Subject: [PATCH 22/27] fix: stylelint fixes in import SCSS files --- src/css/import/_card.scss | 10 +- src/css/import/_migrate.scss | 85 +++++------ src/css/import/_page.scss | 6 +- src/css/import/_upload.scss | 276 +++++++++++++++++------------------ 4 files changed, 189 insertions(+), 188 deletions(-) diff --git a/src/css/import/_card.scss b/src/css/import/_card.scss index 29d6ae68..aceb91dc 100644 --- a/src/css/import/_card.scss +++ b/src/css/import/_card.scss @@ -11,13 +11,13 @@ .tablenav { display: flex; gap: 10px; - height: auto; + block-size: auto; padding: 0; } .tablenav.bottom { justify-content: flex-end; - margin-top: 1em; + margin-block-start: 1em; } } @@ -26,13 +26,13 @@ padding: 25px; border-radius: 5px; border: 1px solid #e0e0e0; - margin-bottom: 10px; - width: 100%; + margin-block-end: 10px; + inline-size: 100%; &.status-display { display: flex; align-items: flex-start; gap: 12px; - margin-bottom: 20px; + margin-block-end: 20px; } } diff --git a/src/css/import/_migrate.scss b/src/css/import/_migrate.scss index c47ec98d..9dc092ba 100644 --- a/src/css/import/_migrate.scss +++ b/src/css/import/_migrate.scss @@ -1,18 +1,18 @@ .importer-selector-card { h2 { - margin: 0 0 1em 0; + margin: 0 0 1em; } select { display: block; - margin-top: 5px; - width: 100%; - max-width: 300px; + margin-block-start: 5px; + inline-size: 100%; + max-inline-size: 300px; } p { - margin: 10px 0 0 0; + margin: 10px 0 0; color: #666; font-size: 14px; } @@ -20,7 +20,7 @@ .import-options-card { h2 { - margin: 0 0 1em 0; + margin: 0 0 1em; } label { @@ -36,7 +36,7 @@ } input { - margin-top: 2px; + margin-block-start: 2px; } > div { @@ -44,11 +44,11 @@ } .import-tag-entry { - margin-top: 12px; + margin-block-start: 12px; input { - width: 100%; - max-width: 300px; + inline-size: 100%; + max-inline-size: 300px; } } } @@ -57,13 +57,13 @@ .import-section-status { .error, .success { border-radius: 50%; - width: 24px; - height: 24px; + inline-size: 24px; + block-size: 24px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; - margin-top: 2px; + margin-block-start: 2px; span { color: white; @@ -81,7 +81,7 @@ } h3 { - margin: 0 0 8px 0; + margin: 0 0 8px; font-size: 16px; font-weight: 600; } @@ -97,52 +97,53 @@ } } +.no-snippets-card { + .card-inner { + text-align: center; + padding: 40px 20px; + color: #666; + + p { + margin: 0; + font-size: 14px; + } + } + + .card-icon { + font-size: 48px; + margin-block-end: 16px; + } + + h3 { + margin: 0 0 8px; + font-size: 18px; + color: #333; + } + +} + .migrate-snippets-table-card { > div:first-child { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 10px; + margin-block-end: 10px; h2 { margin: 0; } p { - margin: 0.5em 0 1em 0; + margin: 0.5em 0 1em; } } .column-id { text-align: end; - width: 50px; + inline-size: 50px; } } .migrate-form-container { - max-width: 800px; -} - -.no-snippets-card { - .card-inner { - text-align: center; - padding: 40px 20px; - color: #666; - } - - .card-icon { - font-size: 48px; - margin-bottom: 16px; - } - - h3 { - margin: 0 0 8px 0; - font-size: 18px; - color: #333; - } - - p { - margin: 0; - font-size: 14px; - } + max-inline-size: 800px; } diff --git a/src/css/import/_page.scss b/src/css/import/_page.scss index 69330bc1..d0b694e5 100644 --- a/src/css/import/_page.scss +++ b/src/css/import/_page.scss @@ -1,15 +1,15 @@ .import-snippets-menu { .narrow { - max-width: 800px; + max-inline-size: 800px; } h2.nav-tab-wrapper { - margin-bottom: 20px; + margin-block-end: 20px; } } .import-snippets-section { - padding-top: 0; + padding-block-start: 0; display: none; &.active-section { diff --git a/src/css/import/_upload.scss b/src/css/import/_upload.scss index 9e4449d3..e8f67a9f 100644 --- a/src/css/import/_upload.scss +++ b/src/css/import/_upload.scss @@ -5,102 +5,27 @@ $type-colors: ( ); .upload-form-container { - max-width: 800px; + max-inline-size: 800px; } .import-upload-card { h2 { - margin: 0 0 1em 0; + margin: 0 0 1em; } p.description { - margin-bottom: 1em; + margin-block-end: 1em; } footer { text-align: center; .button { - min-width: 200px; + min-inline-size: 200px; } } } -.import-select-card { - .return-link { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 20px; - } - - .tablenav.top { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 10px; - - h3 { - margin: 0; - } - - p { - margin: 0.5em 0 1em 0; - color: #666; - } - } - - .table-actions .button { - margin-right: 10px; - } - - .wp-list-table { - table-layout: fixed; - } - - th.check-column { - width: 40px; - } - - th.column-name { - width: 200px; - } - - td.column-name div { - font-size: 12px; - color: #666; - margin-top: 2px; - } - - .column-type { - width: 90px; - text-align: center; - - span { - background-color: #1d97c6; - color: white; - padding: 3px 6px; - font-size: 10px; - text-transform: uppercase; - border-radius: 3px; - - @each $type, $color in $type-colors { - @at-root .import-select-card .#{$type}-snippet & { - background-color: $color; - } - } - } - } - - th.column-desc { - width: auto; - } - - th.column-tags { - width: 120px; - } -} - .upload-drop-zone { border: 2px dashed #ccd0d4; border-radius: 4px; @@ -108,7 +33,7 @@ $type-colors: ( text-align: center; cursor: pointer; background-color: #fafafa; - margin-bottom: 20px; + margin-block-end: 20px; transition: all 0.3s ease; opacity: 1; @@ -125,12 +50,12 @@ $type-colors: ( .drop-zone-icon { font-size: 48px; - margin-bottom: 10px; + margin-block-end: 10px; color: #666; } p:first-of-type { - margin: 0 0 8px 0; + margin: 0 0 8px; font-size: 16px; font-weight: 500; } @@ -146,13 +71,75 @@ $type-colors: ( } } +.import-result-display-card { + > div { + display: flex; + align-items: flex-start; + gap: 12px; + } +} + +.selected-files { + margin-block-end: 20px; + + h3 { + margin: 0 0 12px; + font-size: 14px; + font-weight: 600; + } +} + +.selected-files-list { + display: flex; + flex-direction: column; + gap: 8px; + + > div { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + background-color: #f9f9f9; + } + + button { + background: none; + border: none; + color: #d63638; + cursor: pointer; + font-size: 16px; + padding: 4px; + } + + .selected-file-details { + display: flex; + align-items: center; + gap: 8px; + + strong { + font-weight: 500; + } + + .file-icon { + font-size: 16px; + } + + .file-size { + font-size: 12px; + color: #666; + } + } +} + .duplicate-action-selector-card { h2 { - margin: 0 0 1em 0; + margin: 0 0 1em; } p.description { - margin-bottom: 1em; + margin-block-end: 1em; } fieldset { @@ -170,19 +157,11 @@ $type-colors: ( } input { - margin-top: 2px + margin-block-start: 2px; } } } -.import-result-display-card { - > div { - display: flex; - align-items: flex-start; - gap: 12px; - } -} - .import-result { display: flex; align-items: flex-start; @@ -193,13 +172,13 @@ $type-colors: ( } h3 { - margin: 0 0 8px 0; + margin: 0 0 8px; font-size: 16px; font-weight: 600 } p.import-result-message { - margin: 0 0 8px 0; + margin: 0 0 8px; color: #666; } @@ -214,17 +193,17 @@ $type-colors: ( } p.import-result-warnings { - margin-top: 12px; + margin-block-start: 12px; h4 { - margin: 0 0 8px 0; + margin: 0 0 8px; font-size: 14px; color: #d63638; } ul { margin: 0; - padding-left: 20px; + padding-inline-start: 20px; } li { @@ -236,8 +215,8 @@ $type-colors: ( .import-result-icon { border-radius: 50%; - width: 24px; - height: 24px; + inline-size: 24px; + block-size: 24px; display: flex; align-items: center; justify-content: center; @@ -259,56 +238,77 @@ $type-colors: ( } } -.selected-files { - margin-bottom: 20px; - - h3 { - margin: 0 0 12px 0; - font-size: 14px; - font-weight: 600; - } -} - -.selected-files-list { - display: flex; - flex-direction: column; - gap: 8px; - - > div { +.import-select-card { + .return-link { display: flex; align-items: center; justify-content: space-between; - padding: 8px 12px; - border: 1px solid #ddd; - border-radius: 4px; - background-color: #f9f9f9; + margin-block-end: 20px; } - button { - background: none; - border: none; - color: #d63638; - cursor: pointer; - font-size: 16px; - padding: 4px; - } - - .selected-file-details { + .tablenav.top { display: flex; + justify-content: space-between; align-items: center; - gap: 8px; + margin-block-end: 10px; - strong { - font-weight: 500; + h3 { + margin: 0; } - .file-icon { - font-size: 16px; + p { + margin: 0.5em 0 1em; + color: #666; } + } - .file-size { - font-size: 12px; - color: #666; + .table-actions .button { + margin-inline-end: 10px; + } + + .wp-list-table { + table-layout: fixed; + } + + th.check-column { + inline-size: 40px; + } + + th.column-name { + inline-size: 200px; + } + + td.column-name div { + font-size: 12px; + color: #666; + margin-block-start: 2px; + } + + .column-type { + inline-size: 90px; + text-align: center; + + span { + background-color: #1d97c6; + color: white; + padding: 3px 6px; + font-size: 10px; + text-transform: uppercase; + border-radius: 3px; + + @each $type, $color in $type-colors { + @at-root .import-select-card .#{$type}-snippet & { + background-color: $color; + } + } } } + + th.column-desc { + inline-size: auto; + } + + th.column-tags { + inline-size: 120px; + } } From 5c878244050c5ec3f25465ad0f99916b7553312c Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:54:25 +0200 Subject: [PATCH 23/27] fix: stylelint fixes in manage.scss and welcome.scss --- src/css/manage.scss | 38 ++++++++++++++++---------------------- src/css/welcome.scss | 24 ++++++++++++------------ 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/css/manage.scss b/src/css/manage.scss index f73a529d..fad988ed 100644 --- a/src/css/manage.scss +++ b/src/css/manage.scss @@ -10,19 +10,6 @@ @use 'manage/snippets-table'; @use 'manage/cloud-community'; -.wrap h1:first-of-type { - font-size: 1.6rem; - padding: 0; - margin-block: 50px 1.4rem; - - .subtitle { - vertical-align: middle; - display: inline-flex; - align-items: center; - gap: 1em; - } -} - .create-snippet-button { margin-inline-start: auto; float: inline-end; @@ -61,7 +48,7 @@ } .column-name .tooltip { - float: right; + float: inline-end; .dashicons-lock { color: #646970; @@ -128,6 +115,19 @@ } } +.wrap > h1:first-of-type { + font-size: 1.6rem; + padding: 0; + margin-block: 50px 1.4rem; + + .subtitle { + vertical-align: middle; + display: inline-flex; + align-items: center; + gap: 1em; + } +} + .wp-list-table { td.column-id { text-align: center; @@ -229,9 +229,8 @@ inline-size: 130px; /* fixed column width */ min-inline-size: 130px; max-inline-size: 130px; - text-align: right; - padding-inline-start: 8px; - padding-inline-end: 8px; + text-align: end; + padding-inline: 8px; overflow: hidden; text-overflow: ellipsis; } @@ -268,11 +267,6 @@ display: table-cell !important; } -.nav-tab-wrapper + .subsubsub, p.search-box { - margin-block: 10px 0; - margin-inline: 0; -} - .snippet-type-description { border-block-end: 1px solid #ccc; margin: 0; diff --git a/src/css/welcome.scss b/src/css/welcome.scss index fdd34ca3..7b83f3c7 100644 --- a/src/css/welcome.scss +++ b/src/css/welcome.scss @@ -41,18 +41,6 @@ $breakpoint: 1060px; } } -.csp-welcome-header nav { - column-gap: 15px; - - ul { - display: flex; - flex-flow: row wrap; - justify-content: space-evenly; - gap: 5px; - margin: 0; - } -} - .code-snippets-hero { display: flex; flex-flow: column; @@ -248,6 +236,18 @@ $breakpoint: 1060px; inset-block-start: 45%; } +.csp-welcome-header nav { + column-gap: 15px; + + ul { + display: flex; + flex-flow: row wrap; + justify-content: space-evenly; + gap: 5px; + margin: 0; + } +} + @keyframes loading-rotate { 100% { transform: rotate(calc(360deg * var(--cs-direction-multiplier))); From d6086c89e03ebb751ba9581ec14e6bec149884a7 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:54:37 +0200 Subject: [PATCH 24/27] fix: remove trailing blank line from test-flat-files-hooks.php --- tests/phpunit/test-flat-files-hooks.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/phpunit/test-flat-files-hooks.php b/tests/phpunit/test-flat-files-hooks.php index 7876ac74..abc35b09 100644 --- a/tests/phpunit/test-flat-files-hooks.php +++ b/tests/phpunit/test-flat-files-hooks.php @@ -42,4 +42,3 @@ public function test_update_snippet_fields_triggers_update_action_with_snippet_o $this->assertSame( $saved->id, $observed->id ); } } - From 598cade0736f0d38a5d63b424699d880446a9470 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:55:01 +0200 Subject: [PATCH 25/27] fix: remove unused postcss-color-hsl type declaration --- config/modules/postcss-color-hsl.d.ts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 config/modules/postcss-color-hsl.d.ts diff --git a/config/modules/postcss-color-hsl.d.ts b/config/modules/postcss-color-hsl.d.ts deleted file mode 100644 index fc76708c..00000000 --- a/config/modules/postcss-color-hsl.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'postcss-color-hsl' { - import type { Plugin } from 'postcss' - export default function (): Plugin -} From c4b2223755cd60236812616d43ecb1f83fb739e3 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:55:36 +0200 Subject: [PATCH 26/27] fix: make .husky/pre-commit executable --- .husky/pre-commit | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 From bef5b8b00c6f14c73313bbb64139678429c38750 Mon Sep 17 00:00:00 2001 From: Imants Date: Wed, 18 Feb 2026 23:58:16 +0200 Subject: [PATCH 27/27] chore: remove duplicate eslint override --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index f253c651..86128036 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,6 @@ "tmp": "0.2.5", "eslint-visitor-keys": "4.2.1", "@typescript-eslint/visitor-keys": "8.55.0", - "eslint": "^9.20.1", "react": "^18.3.1", "react-dom": "^18.3.1" }