diff --git a/.cspell.json b/.cspell.json index badfa4d..6593556 100644 --- a/.cspell.json +++ b/.cspell.json @@ -16,7 +16,8 @@ "notcss", "stylelintcache", "eslintcache", - "autocrlf" + "autocrlf", + "nodenext" ], "ignorePaths": [ diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 777d65f..665d648 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -62,8 +62,11 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node-version: [18.x, 20.x, 22.x, 24.x] - stylelint-version: [13.x, 14.x, 15.x, 16.x] + stylelint-version: [13.x, 14.x, 15.x, 16.x, 17.x] webpack-version: [latest] + exclude: + - node-version: 18.x + stylelint-version: 17.x runs-on: ${{ matrix.os }} diff --git a/package-lock.json b/package-lock.json index d6fe161..f200ca6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,20 +53,20 @@ "postcss-scss": "^4.0.9", "prettier": "^3.3.2", "standard-version": "^9.5.0", - "stylelint": "^16.6.1", + "stylelint": "^17.1.0", "typescript": "^5.5.3", "typescript-eslint": "^8.38.0", "webpack": "^5.92.1" }, "engines": { - "node": ">= 18.12.0" + "node": ">= 20.19.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "webpack": "^5.0.0" } }, @@ -1848,6 +1848,67 @@ "dev": true, "license": "MIT" }, + "node_modules/@cacheable/memory": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.7.tgz", + "integrity": "sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.3.3", + "@keyv/bigmap": "^1.3.0", + "hookified": "^1.14.0", + "keyv": "^5.5.5" + } + }, + "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.3.3.tgz", + "integrity": "sha512-JsXDL70gQ+1Vc2W/KUFfkAJzgb4puKwwKehNLuB+HrNKWf91O736kGfxn4KujXCCSuh6mRRL4XEB0PkAFjWS0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.3.0", + "keyv": "^5.5.5" + } + }, + "node_modules/@cacheable/utils/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/@commitlint/cli": { "version": "19.8.1", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.1.tgz", @@ -2707,9 +2768,9 @@ } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -2723,16 +2784,33 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" } }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.26.tgz", + "integrity": "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0" + }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -2746,13 +2824,13 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", - "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-5.0.0.tgz", + "integrity": "sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==", "dev": true, "funding": [ { @@ -2766,17 +2844,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, - "node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/@csstools/selector-resolve-nested": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-4.0.0.tgz", + "integrity": "sha512-9vAPxmp+Dx3wQBIUwc1v7Mdisw1kbbaGqXUM8QLTgWg7SoPGYtXBsMXvsFs/0Bn5yoFhcktzxNZGNaUt0VjgjA==", "dev": true, "funding": [ { @@ -2790,21 +2868,33 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "postcss-selector-parser": "^7.0.0" + "postcss-selector-parser": "^7.1.1" } }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "node_modules/@csstools/selector-specificity": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-6.0.0.tgz", + "integrity": "sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA==", "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.1.1" } }, "node_modules/@emnapi/core": { @@ -3000,9 +3090,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -3761,9 +3851,9 @@ "license": "MIT" }, "node_modules/@jest/reporters/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -4206,14 +4296,11 @@ } }, "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - } + "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.11", @@ -4309,6 +4396,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -5943,27 +6043,6 @@ "dev": true, "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -6053,31 +6132,6 @@ "node-int64": "^0.4.0" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -6099,24 +6153,27 @@ } }, "node_modules/cacheable": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.0.tgz", - "integrity": "sha512-SSgQTAnhd7WlJXnGlIi4jJJOiHzgnM5wRMEPaXAU4kECTAMpBoYKoZ9i5zHmclIEZbxcu3j7yY/CF8DTmwIsHg==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.2.tgz", + "integrity": "sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.8.2", - "keyv": "^5.3.3" + "@cacheable/memory": "^2.0.7", + "@cacheable/utils": "^2.3.3", + "hookified": "^1.15.0", + "keyv": "^5.5.5", + "qified": "^0.6.0" } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", - "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.0.3" + "@keyv/serialize": "^1.1.1" } }, "node_modules/call-bind": { @@ -8002,9 +8059,9 @@ "license": "Python-2.0" }, "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -8380,9 +8437,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -11734,6 +11791,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hashery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.4.0.tgz", + "integrity": "sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.14.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -11748,9 +11818,9 @@ } }, "node_modules/hookified": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.9.1.tgz", - "integrity": "sha512-u3pxtGhKjcSXnGm1CX6aXS9xew535j3lkOCegbA6jdyh0BaAjTbXI4aslKstCr6zUNtoCxFGFKwjbSHdGrMB8g==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.0.tgz", + "integrity": "sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw==", "dev": true, "license": "MIT" }, @@ -11769,13 +11839,13 @@ "license": "MIT" }, "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-5.1.0.tgz", + "integrity": "sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11807,27 +11877,6 @@ "url": "https://github.com/sponsors/typicode" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -11898,9 +11947,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, "license": "MIT", "funding": { @@ -12986,9 +13035,9 @@ "license": "MIT" }, "node_modules/jest-config/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -13786,9 +13835,9 @@ "license": "MIT" }, "node_modules/jest-runtime/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -14347,9 +14396,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -14561,9 +14610,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.36.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", - "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", "dev": true, "license": "MIT" }, @@ -14903,9 +14952,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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" }, @@ -15194,9 +15243,9 @@ } }, "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-4.0.0.tgz", + "integrity": "sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==", "dev": true, "license": "MIT", "funding": { @@ -17047,9 +17096,9 @@ } }, "node_modules/postcss": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", - "integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -17075,13 +17124,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true, - "license": "MIT" - }, "node_modules/postcss-safe-parser": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", @@ -17137,9 +17179,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -17270,6 +17312,19 @@ "teleport": ">=0.2.0" } }, + "node_modules/qified": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.6.0.tgz", + "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.14.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -18918,9 +18973,9 @@ } }, "node_modules/stylelint": { - "version": "16.20.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.20.0.tgz", - "integrity": "sha512-B5Myu9WRxrgKuLs3YyUXLP2H0mrbejwNxPmyADlACWwFsrL8Bmor/nTSh4OMae5sHjOz6gkSeccQH34gM4/nAw==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.1.0.tgz", + "integrity": "sha512-+cUX1FxkkbLX5qJRAPapUv/+v+YU3pGbWu+pHVqTXpiY0mYh3Dxfxa0bLBtVtYgOC8hIWIyX2H/3Y3LWlAevDg==", "dev": true, "funding": [ { @@ -18934,86 +18989,116 @@ ], "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", - "balanced-match": "^2.0.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-syntax-patches-for-csstree": "^1.0.25", + "@csstools/css-tokenizer": "^4.0.0", + "@csstools/media-query-list-parser": "^5.0.0", + "@csstools/selector-resolve-nested": "^4.0.0", + "@csstools/selector-specificity": "^6.0.0", + "balanced-match": "^3.0.1", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", "css-tree": "^3.1.0", - "debug": "^4.4.1", + "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.1.0", + "file-entry-cache": "^11.1.2", "global-modules": "^2.0.0", - "globby": "^11.1.0", + "globby": "^16.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^7.0.4", + "html-tags": "^5.1.0", + "ignore": "^7.0.5", + "import-meta-resolve": "^4.2.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.36.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", + "known-css-properties": "^0.37.0", + "mathml-tag-names": "^4.0.0", + "meow": "^14.0.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.5.3", - "postcss-resolve-nested-selector": "^0.1.6", + "postcss": "^8.5.6", "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.1.0", + "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.2.0", + "string-width": "^8.1.0", + "supports-hyperlinks": "^4.4.0", "svg-tags": "^1.0.0", "table": "^6.9.0", - "write-file-atomic": "^5.0.1" + "write-file-atomic": "^7.0.0" }, "bin": { "stylelint": "bin/stylelint.mjs" }, "engines": { - "node": ">=18.12.0" + "node": ">=20.19.0" } }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "node_modules/stylelint/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" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } }, - "node_modules/stylelint/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/stylelint/node_modules/balanced-match": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", + "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 16" + } }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", - "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.2.tgz", + "integrity": "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.10" + "flat-cache": "^6.1.20" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.10.tgz", - "integrity": "sha512-B6/v1f0NwjxzmeOhzfXPGWpKBVA207LS7lehaVKQnFrVktcFRfkzjZZ2gwj2i1TkEUMQht7ZMJbABUT5N+V1Nw==", + "version": "6.1.20", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.20.tgz", + "integrity": "sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.10.0", + "cacheable": "^2.3.2", "flatted": "^3.3.3", - "hookified": "^1.9.1" + "hookified": "^1.15.0" + } + }, + "node_modules/stylelint/node_modules/globby": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.0.tgz", + "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/stylelint/node_modules/ignore": { @@ -19026,42 +19111,103 @@ "node": ">= 4" } }, - "node_modules/stylelint/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/stylelint/node_modules/meow": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", + "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "node_modules/stylelint/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/stylelint/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/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/stylelint/node_modules/unicorn-magic": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/node_modules/write-file-atomic": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.0.tgz", + "integrity": "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/supports-color": { @@ -19078,22 +19224,48 @@ } }, "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-4.4.0.tgz", + "integrity": "sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "has-flag": "^5.0.1", + "supports-color": "^10.2.2" }, "engines": { - "node": ">=14.18" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz", + "integrity": "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", diff --git a/package.json b/package.json index 0bab272..9735fed 100644 --- a/package.json +++ b/package.json @@ -94,16 +94,16 @@ "postcss-scss": "^4.0.9", "prettier": "^3.3.2", "standard-version": "^9.5.0", - "stylelint": "^16.6.1", + "stylelint": "^17.1.0", "typescript": "^5.5.3", "typescript-eslint": "^8.38.0", "webpack": "^5.92.1" }, "peerDependencies": { - "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "webpack": "^5.0.0" }, "engines": { - "node": ">= 18.12.0" + "node": ">= 20.19.0" } } diff --git a/src/getStylelint.js b/src/getStylelint.js index 5e2a2fc..f14ff47 100644 --- a/src/getStylelint.js +++ b/src/getStylelint.js @@ -4,7 +4,11 @@ const { Worker: JestWorker } = require("jest-worker"); const { getStylelintOptions } = require("./options"); const { jsonStringifyReplacerSortKeys } = require("./utils"); -const { lintFiles, setup } = require("./worker"); +const { + getStylelint: getStylelintInstance, + lintFiles, + setup, +} = require("./worker"); /** @type {{ [key: string]: Linter }} */ const cache = {}; @@ -19,7 +23,7 @@ const cache = {}; /** @typedef {import('./options').Options} Options */ /** @typedef {() => Promise} AsyncTask */ /** @typedef {(files: string|string[]) => Promise} LintTask */ -/** @typedef {{stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number }} Linter */ +/** @typedef {{getStylelint: () => Promise, lintFiles: LintTask, cleanup: AsyncTask, threads: number }} Linter */ /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */ /** @@ -28,10 +32,10 @@ const cache = {}; */ function loadStylelint(options) { const stylelintOptions = getStylelintOptions(options); - const stylelint = setup(options, stylelintOptions); + setup(options, stylelintOptions); return { - stylelint, + getStylelint: getStylelintInstance, lintFiles, cleanup: async () => {}, threads: 1, diff --git a/src/index.js b/src/index.js index fa5334d..3f96822 100644 --- a/src/index.js +++ b/src/index.js @@ -89,21 +89,7 @@ class StylelintWebpackPlugin { if (isCompilerHooked) return; compiler.hooks.thisCompilation.tap(this.key, (compilation) => { - /** @type {import('./linter').Linter} */ - let lint; - - /** @type {import('./linter').Reporter} */ - let report; - - /** @type number */ - let threads; - - try { - ({ lint, report, threads } = linter(this.key, options, compilation)); - } catch (err) { - compilation.errors.push(err); - return; - } + const { lint, report, threads } = linter(this.key, options, compilation); compilation.hooks.finishModules.tapPromise(this.key, async () => { /** @type {string[]} */ diff --git a/src/linter.js b/src/linter.js index 7b58215..db9c412 100644 --- a/src/linter.js +++ b/src/linter.js @@ -1,7 +1,7 @@ const { dirname, isAbsolute, join } = require("node:path"); const StylelintError = require("./StylelintError"); -const getStylelint = require("./getStylelint"); +const getStylelintModule = require("./getStylelint"); const { arrify } = require("./utils"); /** @typedef {import('webpack').Compiler} Compiler */ @@ -57,24 +57,30 @@ async function flatten(results) { } /** - * @param {Stylelint} stylelint stylelint + * @param {() => Promise} getStylelint stylelint getter * @param {FormatterType=} formatter formatter - * @returns {Promise | Formatter} resolved formatter + * @returns {Promise} resolved formatter */ -function loadFormatter(stylelint, formatter) { +async function loadFormatter(getStylelint, formatter) { if (typeof formatter === "function") { return formatter; } + const stylelint = await getStylelint(); + if (typeof formatter === "string") { try { - return stylelint.formatters[formatter]; + const fmt = stylelint.formatters[formatter]; + // Handle both sync (v13-v15) and promise-based (v16+) formatters + return fmt instanceof Promise ? await fmt : fmt; } catch { // Load the default formatter. } } - return stylelint.formatters.string; + const defaultFmt = stylelint.formatters.string; + // Handle both sync (v13-v15) and promise-based (v16+) formatters + return defaultFmt instanceof Promise ? await defaultFmt : defaultFmt; } /* istanbul ignore next */ @@ -164,28 +170,15 @@ function parseResults(options, results) { * @returns {{ lint: Linter, report: Reporter, threads: number }} the linter with additional functions */ function linter(key, options, compilation) { - /** @type {Stylelint} */ - let stylelint; - - /** @type {(files: string | string[]) => Promise} */ - let lintFiles; - - /** @type {() => Promise} */ - let cleanup; - - /** @type number */ - let threads; - /** @type {Promise[]} */ const rawResults = []; const crossRunResultStorage = getResultStorage(compilation); - try { - ({ stylelint, lintFiles, cleanup, threads } = getStylelint(key, options)); - } catch (err) { - throw new StylelintError(err.message); - } + const { getStylelint, lintFiles, cleanup, threads } = getStylelintModule( + key, + options, + ); /** * @param {string | string[]} files files @@ -225,15 +218,14 @@ function linter(key, options, compilation) { return {}; } - const formatter = await loadFormatter(stylelint, options.formatter); + const formatter = await loadFormatter(getStylelint, options.formatter); /** @type {LinterResult} */ - // @ts-expect-error need better types const returnValue = { cwd: /** @type {string} */ (options.cwd), errored: false, results: [], - output: "", + report: "", reportedDisables: [], ruleMetadata: getRuleMetadata(results), }; @@ -282,7 +274,7 @@ function linter(key, options, compilation) { } const content = outputReport.formatter - ? (await loadFormatter(stylelint, outputReport.formatter))( + ? (await loadFormatter(getStylelint, outputReport.formatter))( results, returnValue, ) diff --git a/src/worker.js b/src/worker.js index 8480d08..8d2c41f 100644 --- a/src/worker.js +++ b/src/worker.js @@ -3,22 +3,39 @@ /** @typedef {import('./getStylelint').LintResult} LintResult */ /** @typedef {import('./options').Options} Options */ -/** @type {Stylelint} */ -let stylelint; +/** @type {string} */ +let stylelintPath = "stylelint"; /** @type {Partial} */ let linterOptions; +/** @type {Promise | null} */ +let stylelintPromise = null; + +/** + * Lazily load stylelint on first use + * @returns {Promise} stylelint instance + */ +async function getStylelint() { + if (!stylelintPromise) { + stylelintPromise = (async () => { + const mod = await import(stylelintPath); + // Handle both CJS (v13-v16) and ESM (v17) exports + return mod.default || mod; + })(); + } + return stylelintPromise; +} + /** * @param {Options} options the worker options * @param {Partial} stylelintOptions the stylelint options - * @returns {Stylelint} stylelint instance */ function setup(options, stylelintOptions) { - stylelint = require(options.stylelintPath || "stylelint"); + stylelintPath = options.stylelintPath || "stylelint"; linterOptions = stylelintOptions; - - return stylelint; + // Reset cached stylelint in case path changed + stylelintPromise = null; } /** @@ -26,6 +43,7 @@ function setup(options, stylelintOptions) { * @returns {Promise} results */ async function lintFiles(files) { + const stylelint = await getStylelint(); const { results } = await stylelint.lint({ ...linterOptions, files, @@ -44,5 +62,6 @@ async function lintFiles(files) { })); } +module.exports.getStylelint = getStylelint; module.exports.lintFiles = lintFiles; module.exports.setup = setup; diff --git a/test/error.test.js b/test/error.test.js index 6c01fbe..531420c 100644 --- a/test/error.test.js +++ b/test/error.test.js @@ -1,3 +1,5 @@ +import { join } from "node:path"; + import pack from "./utils/pack"; describe("error", () => { @@ -12,12 +14,21 @@ describe("error", () => { expect(stats.hasErrors()).toBe(true); }); - it("should propagate stylelint exceptions as errors", async () => { - jest.mock("stylelint", () => { - throw new Error("Oh no!"); - }); + it("should propagate stylelint lint exceptions as errors", async () => { + // Mock that throws when lint() is called + const mockStylelintPath = join(__dirname, "mock/stylelint-error"); + + const compiler = pack("good", { stylelintPath: mockStylelintPath }); + const stats = await compiler.runAsync(); + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(true); + }); + + it("should propagate stylelint load exceptions as errors", async () => { + // Mock that throws when the module is loaded + const mockStylelintPath = join(__dirname, "mock/stylelint-load-error"); - const compiler = pack("good"); + const compiler = pack("good", { stylelintPath: mockStylelintPath }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); diff --git a/test/formatter.test.js b/test/formatter.test.js index 7088d79..54ed47d 100644 --- a/test/formatter.test.js +++ b/test/formatter.test.js @@ -1,5 +1,3 @@ -import { formatters } from "stylelint"; - import pack from "./utils/pack"; describe("formatter", () => { @@ -28,7 +26,13 @@ describe("formatter", () => { }); it("should use function formatter", async () => { - const compiler = pack("error", { formatter: await formatters.verbose }); + // Use dynamic import for ESM-only stylelint v17 + // eslint-disable-next-line import/no-unresolved + const stylelintModule = await import("stylelint"); + const stylelint = stylelintModule.default || stylelintModule; + const verboseFormatter = await stylelint.formatters.verbose; + + const compiler = pack("error", { formatter: verboseFormatter }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); diff --git a/test/mock/stylelint-error/index.js b/test/mock/stylelint-error/index.js new file mode 100644 index 0000000..242f1a1 --- /dev/null +++ b/test/mock/stylelint-error/index.js @@ -0,0 +1,16 @@ +// Mock stylelint that throws an error on lint +const stylelint = { + formatters: { + string() { + return ""; + }, + }, + + lint() { + throw new Error("Oh no!"); + }, +}; + +module.exports = stylelint; +// Also export as default for ESM compatibility with dynamic import() +module.exports.default = stylelint; diff --git a/test/mock/stylelint-load-error/index.js b/test/mock/stylelint-load-error/index.js new file mode 100644 index 0000000..76d78c1 --- /dev/null +++ b/test/mock/stylelint-load-error/index.js @@ -0,0 +1,2 @@ +// Mock that throws on load (simulates corrupted/missing module) +throw new Error("Oh no! Failed to load stylelint"); diff --git a/test/mock/stylelint-recorder/index.js b/test/mock/stylelint-recorder/index.js new file mode 100644 index 0000000..d59cf64 --- /dev/null +++ b/test/mock/stylelint-recorder/index.js @@ -0,0 +1,27 @@ +// Mock stylelint that records lint calls for testing +const calls = []; + +const stylelint = { + formatters: { + string(results) { + return JSON.stringify(results); + }, + }, + + lint(options) { + calls.push(options); + return { + results: [], + }; + }, +}; + +// Export the calls array so tests can access it +stylelint._calls = calls; +stylelint._reset = () => { + calls.length = 0; +}; + +module.exports = stylelint; +// Also export as default for ESM compatibility with dynamic import() +module.exports.default = stylelint; diff --git a/test/mock/stylelint/index.js b/test/mock/stylelint/index.js index 041f3b5..2eb2539 100644 --- a/test/mock/stylelint/index.js +++ b/test/mock/stylelint/index.js @@ -1,4 +1,4 @@ -module.exports = { +const stylelint = { formatters: { string(results) { return JSON.stringify(results); @@ -25,3 +25,7 @@ module.exports = { }; }, }; + +module.exports = stylelint; +// Also export as default for ESM compatibility with dynamic import() +module.exports.default = stylelint; diff --git a/test/stylelint-lint.test.js b/test/stylelint-lint.test.js index 043e095..37b593e 100644 --- a/test/stylelint-lint.test.js +++ b/test/stylelint-lint.test.js @@ -1,26 +1,29 @@ +import { join } from "node:path"; + import pack from "./utils/pack"; describe("stylelint lint", () => { - const mockLintFiles = jest.fn().mockReturnValue({ - results: [], - }); - - beforeAll(() => { - jest.mock("stylelint", () => ({ - lint: mockLintFiles, - })); - }); + const mockStylelintPath = join(__dirname, "mock/stylelint-recorder"); beforeEach(() => { - mockLintFiles.mockClear(); + // Clear recorded calls before each test + const mock = require(mockStylelintPath); + + mock._reset(); }); it("should lint one file", async () => { - const compiler = pack("lint-one", { configFile: null }); + const compiler = pack("lint-one", { + configFile: null, + stylelintPath: mockStylelintPath, + }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(false); + + const mock = require(mockStylelintPath); + const files = [expect.stringMatching("test.scss")]; - expect(mockLintFiles).toHaveBeenCalledWith({ + expect(mock._calls[0]).toMatchObject({ cache: false, cacheLocation: "node_modules/.cache/stylelint-webpack-plugin/.stylelintcache", @@ -31,14 +34,20 @@ describe("stylelint lint", () => { }); it("should lint two files", async () => { - const compiler = pack("lint-two", { configFile: null }); + const compiler = pack("lint-two", { + configFile: null, + stylelintPath: mockStylelintPath, + }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(false); + + const mock = require(mockStylelintPath); + const files = [ expect.stringMatching(/test[12]\.scss$/), expect.stringMatching(/test[12]\.scss$/), ]; - expect(mockLintFiles).toHaveBeenCalledWith({ + expect(mock._calls[0]).toMatchObject({ cache: false, cacheLocation: "node_modules/.cache/stylelint-webpack-plugin/.stylelintcache", diff --git a/test/threads.test.js b/test/threads.test.js index d553ffb..cd4d7ee 100644 --- a/test/threads.test.js +++ b/test/threads.test.js @@ -53,21 +53,21 @@ describe("Threading", () => { }); it("worker can start", async () => { - const { lintFiles, setup } = require("../src/worker"); + const mockStylelintPath = join(__dirname, "mock/stylelint-recorder"); - const mockThread = { parentPort: { on: jest.fn() }, workerData: {} }; - const mockLintFiles = jest.fn().mockReturnValue({ - results: [], - }); + // Clear any previous calls + const mock = require(mockStylelintPath); - jest.mock("worker_threads", () => mockThread); - jest.mock("stylelint", () => ({ lint: mockLintFiles })); + mock._reset(); + + // Now require the worker (fresh copy due to resetModules) + const { lintFiles, setup } = require("../src/worker"); - setup({}); + setup({ stylelintPath: mockStylelintPath }); await lintFiles("foo"); - expect(mockLintFiles).toHaveBeenCalledWith({ + expect(mock._calls[0]).toMatchObject({ files: "foo", quietDeprecationWarnings: true, }); diff --git a/tsconfig.json b/tsconfig.json index 1c3bf10..1172e40 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,8 @@ { "compilerOptions": { "target": "esnext", - "moduleResolution": "node", + "module": "nodenext", + "moduleResolution": "nodenext", "allowJs": true, "checkJs": true, "strict": true, diff --git a/types/getStylelint.d.ts b/types/getStylelint.d.ts index 4eb02cc..c8fbe1e 100644 --- a/types/getStylelint.d.ts +++ b/types/getStylelint.d.ts @@ -40,7 +40,7 @@ type Options = import("./options").Options; type AsyncTask = () => Promise; type LintTask = (files: string | string[]) => Promise; type Linter = { - stylelint: Stylelint; + getStylelint: () => Promise; lintFiles: LintTask; cleanup: AsyncTask; threads: number; diff --git a/types/worker.d.ts b/types/worker.d.ts index 970fe8a..9fc73e3 100644 --- a/types/worker.d.ts +++ b/types/worker.d.ts @@ -2,6 +2,11 @@ export type Stylelint = import("./getStylelint").Stylelint; export type StylelintOptions = import("./getStylelint").LinterOptions; export type LintResult = import("./getStylelint").LintResult; export type Options = import("./options").Options; +/** + * Lazily load stylelint on first use + * @returns {Promise} stylelint instance + */ +export function getStylelint(): Promise; /** * @param {string | string[]} files files * @returns {Promise} results @@ -10,9 +15,8 @@ export function lintFiles(files: string | string[]): Promise; /** * @param {Options} options the worker options * @param {Partial} stylelintOptions the stylelint options - * @returns {Stylelint} stylelint instance */ export function setup( options: Options, stylelintOptions: Partial, -): Stylelint; +): void;