From da4d2d63731bd8364b852af70b1c4874e34608dd Mon Sep 17 00:00:00 2001 From: Ante Budimir Date: Sun, 9 Mar 2025 18:12:00 +0200 Subject: [PATCH] =?UTF-8?q?feat=20=E2=9C=85:=20add=20comprehensive=20test?= =?UTF-8?q?=20suite=20for=20CSS=20ordering=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tests for all three CSS property ordering rules: alphabetical-order, concentric-order, custom-order, Tests cover all implemented vanilla-extract APIs, fontFace, globalFontFace, globalKeyframes, globalStyle, keyframes, style, and styleVariants.. Each test verifies both valid and invalid cases, along with proper auto-fixing functionality. --- CHANGELOG.md | 50 + README.md | 4 +- package.json | 11 +- pnpm-lock.yaml | 1330 ++++++++++++++++- .../__tests__/animation.test.ts | 111 ++ .../__tests__/font-face.test.ts | 143 ++ .../__tests__/global.test.ts | 52 + .../__tests__/recipe.test.ts | 92 ++ .../__tests__/style.test.ts | 111 ++ .../__tests__/variants.test.ts | 64 + .../__tests__/animation.test.ts | 70 + .../__tests__/font-face.test.ts | 97 ++ .../concentric-order/__tests__/global.test.ts | 58 + .../concentric-order/__tests__/recipe.test.ts | 101 ++ .../concentric-order/__tests__/style.test.ts | 129 ++ .../__tests__/variants.test.ts | 135 ++ .../custom-order/__tests__/animation.test.ts | 151 ++ .../custom-order/__tests__/font-face.test.ts | 127 ++ .../custom-order/__tests__/global.test.ts | 127 ++ .../custom-order/__tests__/recipe.test.ts | 211 +++ .../custom-order/__tests__/style.test.ts | 252 ++++ .../custom-order/__tests__/variants.test.ts | 187 +++ .../order-strategy-visitor-creator.ts | 13 +- src/index.ts | 2 +- vitest.config.mjs | 31 + 25 files changed, 3635 insertions(+), 24 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 src/css-rules/alphabetical-order/__tests__/animation.test.ts create mode 100644 src/css-rules/alphabetical-order/__tests__/font-face.test.ts create mode 100644 src/css-rules/alphabetical-order/__tests__/global.test.ts create mode 100644 src/css-rules/alphabetical-order/__tests__/recipe.test.ts create mode 100644 src/css-rules/alphabetical-order/__tests__/style.test.ts create mode 100644 src/css-rules/alphabetical-order/__tests__/variants.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/animation.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/font-face.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/global.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/recipe.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/style.test.ts create mode 100644 src/css-rules/concentric-order/__tests__/variants.test.ts create mode 100644 src/css-rules/custom-order/__tests__/animation.test.ts create mode 100644 src/css-rules/custom-order/__tests__/font-face.test.ts create mode 100644 src/css-rules/custom-order/__tests__/global.test.ts create mode 100644 src/css-rules/custom-order/__tests__/recipe.test.ts create mode 100644 src/css-rules/custom-order/__tests__/style.test.ts create mode 100644 src/css-rules/custom-order/__tests__/variants.test.ts create mode 100644 vitest.config.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..271fd8c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,50 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.4.1] - 2025-03-09 + +- Add comprehensive test suite for CSS ordering rules () + +## [1.4.0] - 2025-03-08 + +- Implement special ordering for fontFace APIs (3e9bad1) + +## [1.3.1] - 2025-03-07 + +- Update milestones (8916be7) + +## [1.3.0] - 2025-03-06 + +- Add script for versioning updates (f2ad87c) + +## [1.2.0] - 2025-03-05 + +- Add support for linting keyframes and globalKeyframes (dea0a32) + +## [1.1.2] - 2025-03-05 + +- add .npmignore to exclude development files from npm package (223a81d) + +## [1.1.1] - 2025-03-05 + +- Improve packaging and TypeScript configuration (c616fb0) + +## [1.1.0] - 2025-03-04 + +- Lower minimum Node.js version to 18.18.0 (44aba94) + +## [1.0.2] - 2025-03-04 + +- Add npm version badge and link to vanilla-extract (87acd61) + +## [1.0.1] - 2025-03-04 + +- Add sample CSS file for linting demo during development (88a9d43) + +## [1.0.0] - 2025-03-04 + +- Initialize project with complete codebase (d569dea) diff --git a/README.md b/README.md index cd873f4..641dfc6 100644 --- a/README.md +++ b/README.md @@ -253,14 +253,14 @@ The roadmap outlines the project's current status and future plans: - Initial release with support for alphabetical, concentric, and custom group CSS ordering. - Auto-fix capability integrated into ESLint. - Support for multiple vanilla-extract APIs (e.g., `style`, `styleVariants`, `recipe`, `globalStyle`, `fontFace`, etc.). +- Rules tested. ### Current Work -- Test coverage. +- `no-empty-blocks` rule to disallow empty blocks. ### Upcoming Features -- `no-empty-blocks` rule to disallow empty blocks. - `no-unknown-units` rule to disallow unknown units. - `no-number-trailing-zeros` rule to disallow trailing zeros in numbers. - `no-zero-unit` rule to disallow units when the value is zero. diff --git a/package.json b/package.json index a46b6ef..0ba6e09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@antebudimir/eslint-plugin-vanilla-extract", - "version": "1.4.0", + "version": "1.4.1", "description": "ESLint plugin for enforcing CSS ordering in vanilla-extract styles", "author": "Ante Budimir", "license": "MIT", @@ -46,6 +46,9 @@ "lint": "eslint src --ext .ts --fix --max-warnings 0", "prepublishOnly": "pnpm run lint && pnpm run build", "publish": "pnpm publish --access public", + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", "typecheck": "tsc --noEmit", "version:update": "node scripts/update-version.mjs" }, @@ -61,16 +64,20 @@ "@types/node": "^20.17.19", "@typescript-eslint/eslint-plugin": "^8.25.0", "@typescript-eslint/parser": "^8.25.0", + "@typescript-eslint/rule-tester": "^8.26.0", "@typescript-eslint/utils": "^8.25.0", "@vanilla-extract/css": "^1.17.1", "@vanilla-extract/recipes": "^0.5.5", + "@vitest/coverage-v8": "3.0.8", "eslint": "^9.21.0", "eslint-config-prettier": "^10.0.2", "eslint-import-resolver-typescript": "^3.8.3", "eslint-plugin-eslint-plugin": "^6.4.0", "eslint-plugin-import": "^2.31.0", + "eslint-vitest-rule-tester": "^1.1.0", "prettier": "^3.5.2", "typescript": "^5.7.3", - "typescript-eslint": "^8.25.0" + "typescript-eslint": "^8.25.0", + "vitest": "^3.0.8" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 87e5bbb..3a9afab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,6 @@ importers: .: devDependencies: - '@antebudimir/eslint-plugin-vanilla-extract': - specifier: ./antebudimir-eslint-plugin-vanilla-extract-2.10.83.tgz - version: file:antebudimir-eslint-plugin-vanilla-extract-2.10.83.tgz(eslint@9.21.0) '@eslint/eslintrc': specifier: ^3.3.0 version: 3.3.0 @@ -23,6 +20,9 @@ importers: '@typescript-eslint/parser': specifier: ^8.25.0 version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/rule-tester': + specifier: ^8.26.0 + version: 8.26.0(eslint@9.21.0)(typescript@5.7.3) '@typescript-eslint/utils': specifier: ^8.25.0 version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) @@ -32,6 +32,9 @@ importers: '@vanilla-extract/recipes': specifier: ^0.5.5 version: 0.5.5(@vanilla-extract/css@1.17.1) + '@vitest/coverage-v8': + specifier: 3.0.8 + version: 3.0.8(vitest@3.0.8(@types/node@20.17.19)(tsx@4.19.3)) eslint: specifier: ^9.21.0 version: 9.21.0 @@ -47,6 +50,9 @@ importers: eslint-plugin-import: specifier: ^2.31.0 version: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) + eslint-vitest-rule-tester: + specifier: ^1.1.0 + version: 1.1.0(eslint@9.21.0)(typescript@5.7.3)(vitest@3.0.8(@types/node@20.17.19)(tsx@4.19.3)) prettier: specifier: ^3.5.2 version: 3.5.2 @@ -56,23 +62,197 @@ importers: typescript-eslint: specifier: ^8.25.0 version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) + vitest: + specifier: ^3.0.8 + version: 3.0.8(@types/node@20.17.19)(tsx@4.19.3) packages: - '@antebudimir/eslint-plugin-vanilla-extract@file:antebudimir-eslint-plugin-vanilla-extract-2.10.83.tgz': - resolution: {integrity: sha512-4wbgC0r7Has3eZiN2P1RdvUhuC4zoGQmn85WUKy5OBDaW6FgT2NAuLNiYWU44oyK0WQmfVhMi6E8qhrFgpkVTA==, tarball: file:antebudimir-eslint-plugin-vanilla-extract-2.10.83.tgz} - version: 1.0.0 - engines: {node: '>=20.18.3'} - peerDependencies: - eslint: '>=9.0.0' + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@antfu/utils@8.1.1': + resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + engines: {node: '>=6.0.0'} + hasBin: true '@babel/runtime@7.26.9': resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@emotion/hash@0.9.2': resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -127,6 +307,32 @@ packages: resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} engines: {node: '>=18.18'} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -143,9 +349,111 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/rollup-android-arm-eabi@4.35.0': + resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.35.0': + resolution: {integrity: sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.35.0': + resolution: {integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.35.0': + resolution: {integrity: sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.35.0': + resolution: {integrity: sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.35.0': + resolution: {integrity: sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + resolution: {integrity: sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + resolution: {integrity: sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.35.0': + resolution: {integrity: sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.35.0': + resolution: {integrity: sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + resolution: {integrity: sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + resolution: {integrity: sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + resolution: {integrity: sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.35.0': + resolution: {integrity: sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.35.0': + resolution: {integrity: sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.35.0': + resolution: {integrity: sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.35.0': + resolution: {integrity: sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.35.0': + resolution: {integrity: sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.35.0': + resolution: {integrity: sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==} + cpu: [x64] + os: [win32] + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -173,10 +481,27 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/parser@8.26.0': + resolution: {integrity: sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/rule-tester@8.26.0': + resolution: {integrity: sha512-o6UDdOWGpkdXpfG+iVC/caucZptQfbcXLoWWRyKVXYW5PDTqN9HDXlDXS0jKtqT0gIHdNuYKflo+ELv7oW7cvw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/scope-manager@8.25.0': resolution: {integrity: sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.26.0': + resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.25.0': resolution: {integrity: sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -188,12 +513,22 @@ packages: resolution: {integrity: sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.26.0': + resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.25.0': resolution: {integrity: sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/typescript-estree@8.26.0': + resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.25.0': resolution: {integrity: sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -201,10 +536,21 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/utils@8.26.0': + resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/visitor-keys@8.25.0': resolution: {integrity: sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.26.0': + resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vanilla-extract/css@1.17.1': resolution: {integrity: sha512-tOHQXHm10FrJeXKFeWE09JfDGN/tvV6mbjwoNB9k03u930Vg021vTnbrCwVLkECj9Zvh/SHLBHJ4r2flGqfovw==} @@ -216,6 +562,44 @@ packages: peerDependencies: '@vanilla-extract/css': ^1.0.0 + '@vitest/coverage-v8@3.0.8': + resolution: {integrity: sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==} + peerDependencies: + '@vitest/browser': 3.0.8 + vitest: 3.0.8 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@3.0.8': + resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} + + '@vitest/mocker@3.0.8': + resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.0.8': + resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} + + '@vitest/runner@3.0.8': + resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} + + '@vitest/snapshot@3.0.8': + resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} + + '@vitest/spy@3.0.8': + resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} + + '@vitest/utils@3.0.8': + resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -229,10 +613,22 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -260,6 +656,10 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -281,6 +681,10 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -297,10 +701,18 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -364,6 +776,10 @@ packages: babel-plugin-macros: optional: true + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -390,6 +806,15 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enhanced-resolve@5.18.1: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} @@ -406,6 +831,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -422,6 +850,11 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -497,6 +930,12 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-vitest-rule-tester@1.1.0: + resolution: {integrity: sha512-rilURDIBbHZKUDXdnlDnewJ3A5NdiK9HpYgdaeKY7rPpn+nI1KfvB/DyYMc0R8KgL9ziu5lbXVmWukgX0JPbAQ==} + peerDependencies: + eslint: ^9.0.0 + vitest: ^1.0.0 || ^2.0.0 || ^3.0.0 + eslint@9.21.0: resolution: {integrity: sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -523,10 +962,17 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + expect-type@1.2.0: + resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + engines: {node: '>=12.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -574,6 +1020,15 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -607,6 +1062,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -652,6 +1111,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -711,6 +1173,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -773,6 +1239,25 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -804,9 +1289,22 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -832,12 +1330,21 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + modern-ahocorasick@1.1.0: resolution: {integrity: sha512-sEKPVl2rM+MNVkGQt3ChdmD8YsigmXdn5NifZn6jiwn9LRJpWm8F3guhaqrJT/JOat6pwpbXEk6kv+b9DMIjsQ==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.9: + resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -881,6 +1388,9 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -896,6 +1406,17 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -911,6 +1432,10 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -954,6 +1479,11 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rollup@4.35.0: + resolution: {integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1014,9 +1544,34 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.8.1: + resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -1029,6 +1584,14 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -1049,10 +1612,32 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyglobby@0.2.12: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1066,6 +1651,11 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1108,6 +1698,79 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + vite-node@3.0.8: + resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.2.1: + resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.0.8: + resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.8 + '@vitest/ui': 3.0.8 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -1129,26 +1792,132 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} snapshots: - '@antebudimir/eslint-plugin-vanilla-extract@file:antebudimir-eslint-plugin-vanilla-extract-2.10.83.tgz(eslint@9.21.0)': + '@ampproject/remapping@2.3.0': dependencies: - eslint: 9.21.0 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@antfu/utils@8.1.1': {} + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 '@babel/runtime@7.26.9': dependencies: regenerator-runtime: 0.14.1 + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@1.0.2': {} + '@emotion/hash@0.9.2': {} + '@esbuild/aix-ppc64@0.25.0': + optional: true + + '@esbuild/android-arm64@0.25.0': + optional: true + + '@esbuild/android-arm@0.25.0': + optional: true + + '@esbuild/android-x64@0.25.0': + optional: true + + '@esbuild/darwin-arm64@0.25.0': + optional: true + + '@esbuild/darwin-x64@0.25.0': + optional: true + + '@esbuild/freebsd-arm64@0.25.0': + optional: true + + '@esbuild/freebsd-x64@0.25.0': + optional: true + + '@esbuild/linux-arm64@0.25.0': + optional: true + + '@esbuild/linux-arm@0.25.0': + optional: true + + '@esbuild/linux-ia32@0.25.0': + optional: true + + '@esbuild/linux-loong64@0.25.0': + optional: true + + '@esbuild/linux-mips64el@0.25.0': + optional: true + + '@esbuild/linux-ppc64@0.25.0': + optional: true + + '@esbuild/linux-riscv64@0.25.0': + optional: true + + '@esbuild/linux-s390x@0.25.0': + optional: true + + '@esbuild/linux-x64@0.25.0': + optional: true + + '@esbuild/netbsd-arm64@0.25.0': + optional: true + + '@esbuild/netbsd-x64@0.25.0': + optional: true + + '@esbuild/openbsd-arm64@0.25.0': + optional: true + + '@esbuild/openbsd-x64@0.25.0': + optional: true + + '@esbuild/sunos-x64@0.25.0': + optional: true + + '@esbuild/win32-arm64@0.25.0': + optional: true + + '@esbuild/win32-ia32@0.25.0': + optional: true + + '@esbuild/win32-x64@0.25.0': + optional: true + '@eslint-community/eslint-utils@4.4.1(eslint@9.21.0)': dependencies: eslint: 9.21.0 @@ -1204,6 +1973,34 @@ snapshots: '@humanwhocodes/retry@0.4.2': {} + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1218,8 +2015,73 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.35.0': + optional: true + + '@rollup/rollup-android-arm64@4.35.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.35.0': + optional: true + + '@rollup/rollup-darwin-x64@4.35.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.35.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.35.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.35.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.35.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.35.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.35.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.35.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.35.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.35.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.35.0': + optional: true + '@rtsao/scc@1.1.0': {} + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} @@ -1259,11 +2121,42 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.26.0 + debug: 4.4.0 + eslint: 9.21.0 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/rule-tester@8.26.0(eslint@9.21.0)(typescript@5.7.3)': + dependencies: + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.7.3) + ajv: 6.12.6 + eslint: 9.21.0 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/scope-manager@8.25.0': dependencies: '@typescript-eslint/types': 8.25.0 '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/scope-manager@8.26.0': + dependencies: + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 + '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': dependencies: '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) @@ -1277,6 +2170,8 @@ snapshots: '@typescript-eslint/types@8.25.0': {} + '@typescript-eslint/types@8.26.0': {} + '@typescript-eslint/typescript-estree@8.25.0(typescript@5.7.3)': dependencies: '@typescript-eslint/types': 8.25.0 @@ -1291,6 +2186,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.26.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) @@ -1302,11 +2211,27 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.26.0(eslint@9.21.0)(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.7.3) + eslint: 9.21.0 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@8.25.0': dependencies: '@typescript-eslint/types': 8.25.0 eslint-visitor-keys: 4.2.0 + '@typescript-eslint/visitor-keys@8.26.0': + dependencies: + '@typescript-eslint/types': 8.26.0 + eslint-visitor-keys: 4.2.0 + '@vanilla-extract/css@1.17.1': dependencies: '@emotion/hash': 0.9.2 @@ -1330,6 +2255,64 @@ snapshots: dependencies: '@vanilla-extract/css': 1.17.1 + '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@20.17.19)(tsx@4.19.3))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.1 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.8(@types/node@20.17.19)(tsx@4.19.3) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.0.8': + dependencies: + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.0.8(vite@6.2.1(@types/node@20.17.19)(tsx@4.19.3))': + dependencies: + '@vitest/spy': 3.0.8 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.1(@types/node@20.17.19)(tsx@4.19.3) + + '@vitest/pretty-format@3.0.8': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.0.8': + dependencies: + '@vitest/utils': 3.0.8 + pathe: 2.0.3 + + '@vitest/snapshot@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.0.8': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -1343,10 +2326,16 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.1: {} + argparse@2.0.1: {} array-buffer-byte-length@1.0.2: @@ -1396,6 +2385,8 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + assertion-error@2.0.1: {} + async-function@1.0.0: {} available-typed-arrays@1.0.7: @@ -1417,6 +2408,8 @@ snapshots: dependencies: fill-range: 7.1.1 + cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -1436,11 +2429,21 @@ snapshots: callsites@3.1.0: {} + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + check-error@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -1489,6 +2492,8 @@ snapshots: dedent@1.5.3: {} + deep-eql@5.0.2: {} + deep-is@0.1.4: {} deep-object-diff@1.1.9: {} @@ -1517,6 +2522,12 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + enhanced-resolve@5.18.1: dependencies: graceful-fs: 4.2.11 @@ -1580,6 +2591,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.6.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -1601,6 +2614,34 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + escape-string-regexp@4.0.0: {} eslint-config-prettier@10.0.2(eslint@9.21.0): @@ -1685,6 +2726,17 @@ snapshots: eslint-visitor-keys@4.2.0: {} + eslint-vitest-rule-tester@1.1.0(eslint@9.21.0)(typescript@5.7.3)(vitest@3.0.8(@types/node@20.17.19)(tsx@4.19.3)): + dependencies: + '@antfu/utils': 8.1.1 + '@types/eslint': 9.6.1 + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.7.3) + eslint: 9.21.0 + vitest: 3.0.8(@types/node@20.17.19)(tsx@4.19.3) + transitivePeerDependencies: + - supports-color + - typescript + eslint@9.21.0: dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) @@ -1740,8 +2792,14 @@ snapshots: estraverse@5.3.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + esutils@2.0.3: {} + expect-type@1.2.0: {} + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -1788,6 +2846,14 @@ snapshots: dependencies: is-callable: 1.2.7 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} function.prototype.name@1.1.8: @@ -1837,6 +2903,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + globals@14.0.0: {} globalthis@1.0.4: @@ -1872,6 +2947,8 @@ snapshots: dependencies: function-bind: 1.1.2 + html-escaper@2.0.2: {} + ignore@5.3.2: {} import-fresh@3.3.1: @@ -1937,6 +3014,8 @@ snapshots: dependencies: call-bound: 1.0.3 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.0: dependencies: call-bound: 1.0.3 @@ -2000,6 +3079,33 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -2029,8 +3135,24 @@ snapshots: lodash.merge@4.6.2: {} + loupe@3.1.3: {} + lru-cache@10.4.3: {} + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.1 + math-intrinsics@1.1.0: {} media-query-parser@2.0.2: @@ -2054,10 +3176,14 @@ snapshots: minimist@1.2.8: {} + minipass@7.1.2: {} + modern-ahocorasick@1.1.0: {} ms@2.1.3: {} + nanoid@3.3.9: {} + natural-compare@1.4.0: {} object-inspect@1.13.4: {} @@ -2116,6 +3242,8 @@ snapshots: dependencies: p-limit: 3.1.0 + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -2126,6 +3254,15 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + pathe@2.0.3: {} + + pathval@2.0.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -2134,6 +3271,12 @@ snapshots: possible-typed-array-names@1.1.0: {} + postcss@8.5.3: + dependencies: + nanoid: 3.3.9 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prelude-ls@1.2.1: {} prettier@3.5.2: {} @@ -2176,6 +3319,31 @@ snapshots: reusify@1.1.0: {} + rollup@4.35.0: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.35.0 + '@rollup/rollup-android-arm64': 4.35.0 + '@rollup/rollup-darwin-arm64': 4.35.0 + '@rollup/rollup-darwin-x64': 4.35.0 + '@rollup/rollup-freebsd-arm64': 4.35.0 + '@rollup/rollup-freebsd-x64': 4.35.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.35.0 + '@rollup/rollup-linux-arm-musleabihf': 4.35.0 + '@rollup/rollup-linux-arm64-gnu': 4.35.0 + '@rollup/rollup-linux-arm64-musl': 4.35.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.35.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.35.0 + '@rollup/rollup-linux-riscv64-gnu': 4.35.0 + '@rollup/rollup-linux-s390x-gnu': 4.35.0 + '@rollup/rollup-linux-x64-gnu': 4.35.0 + '@rollup/rollup-linux-x64-musl': 4.35.0 + '@rollup/rollup-win32-arm64-msvc': 4.35.0 + '@rollup/rollup-win32-ia32-msvc': 4.35.0 + '@rollup/rollup-win32-x64-msvc': 4.35.0 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -2259,8 +3427,30 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + source-map-js@1.2.1: {} + stable-hash@0.0.4: {} + stackback@0.0.2: {} + + std-env@3.8.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -2284,6 +3474,14 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} @@ -2296,11 +3494,27 @@ snapshots: tapable@2.2.1: {} + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2316,6 +3530,14 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tsx@4.19.3: + dependencies: + esbuild: 0.25.0 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + optional: true + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -2378,6 +3600,75 @@ snapshots: dependencies: punycode: 2.3.1 + vite-node@3.0.8(@types/node@20.17.19)(tsx@4.19.3): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.1(@types/node@20.17.19)(tsx@4.19.3) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.2.1(@types/node@20.17.19)(tsx@4.19.3): + dependencies: + esbuild: 0.25.0 + postcss: 8.5.3 + rollup: 4.35.0 + optionalDependencies: + '@types/node': 20.17.19 + fsevents: 2.3.3 + tsx: 4.19.3 + + vitest@3.0.8(@types/node@20.17.19)(tsx@4.19.3): + dependencies: + '@vitest/expect': 3.0.8 + '@vitest/mocker': 3.0.8(vite@6.2.1(@types/node@20.17.19)(tsx@4.19.3)) + '@vitest/pretty-format': 3.0.8 + '@vitest/runner': 3.0.8 + '@vitest/snapshot': 3.0.8 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.1 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.1(@types/node@20.17.19)(tsx@4.19.3) + vite-node: 3.0.8(@types/node@20.17.19)(tsx@4.19.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.17.19 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -2422,6 +3713,23 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + yocto-queue@0.1.0: {} diff --git a/src/css-rules/alphabetical-order/__tests__/animation.test.ts b/src/css-rules/alphabetical-order/__tests__/animation.test.ts new file mode 100644 index 0000000..bd1a1e6 --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/animation.test.ts @@ -0,0 +1,111 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/animation', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // keyframes with alphabetical ordering + ` + import { keyframes } from '@vanilla-extract/css'; + + const fadeIn = keyframes({ + '0%': { + opacity: 0, + transform: 'translateY(10px)' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)' + } + }); + `, + + // globalKeyframes with alphabetical ordering + ` + import { globalKeyframes } from '@vanilla-extract/css'; + + globalKeyframes('fadeIn', { + '0%': { + opacity: 0, + transform: 'translateY(10px)' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)' + } + }); + `, + ], + invalid: [ + // keyframes with incorrect ordering + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + transform: 'translateY(10px)', + opacity: 0 + }, + '100%': { + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }, { messageId: 'alphabeticalOrder' }], + output: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + opacity: 0, + transform: 'translateY(10px)' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)' + } + }); + `, + }, + + // globalKeyframes with incorrect ordering + { + code: ` + import { globalKeyframes } from '@vanilla-extract/css'; + globalKeyframes('fadeIn', { + '0%': { + transform: 'translateY(10px)', + opacity: 0 + }, + '100%': { + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }, { messageId: 'alphabeticalOrder' }], + output: ` + import { globalKeyframes } from '@vanilla-extract/css'; + globalKeyframes('fadeIn', { + '0%': { + opacity: 0, + transform: 'translateY(10px)' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)' + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/alphabetical-order/__tests__/font-face.test.ts b/src/css-rules/alphabetical-order/__tests__/font-face.test.ts new file mode 100644 index 0000000..700d1b2 --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/font-face.test.ts @@ -0,0 +1,143 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/font-face', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // fontFace with src first and other properties alphabetically ordered + ` + import { fontFace } from '@vanilla-extract/css'; + + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + + // globalFontFace with src first and other properties alphabetically ordered + ` + import { globalFontFace } from '@vanilla-extract/css'; + + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + ], + invalid: [ + // fontFace with src not first + { + code: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + fontWeight: '400', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + + // fontFace with src first but other properties not in alphabetical order + { + code: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + fontWeight: '400', + ascentOverride: '90%', + fontStyle: 'normal' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + + // globalFontFace with src not first + { + code: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + fontWeight: '400', + fontStyle: 'normal', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + + // globalFontFace with src first but other properties not in alphabetical order + { + code: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + fontWeight: '400', + fontStyle: 'normal', + ascentOverride: '90%' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + ], +}); diff --git a/src/css-rules/alphabetical-order/__tests__/global.test.ts b/src/css-rules/alphabetical-order/__tests__/global.test.ts new file mode 100644 index 0000000..73a7225 --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/global.test.ts @@ -0,0 +1,52 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/global', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // globalStyle with alphabetical ordering + ` + import { globalStyle } from '@vanilla-extract/css'; + + globalStyle('body', { + backgroundColor: 'white', + color: 'black', + margin: 0, + padding: 0 + }); + `, + ], + invalid: [ + // globalStyle with incorrect ordering + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + color: 'black', + backgroundColor: 'white', + padding: 0, + margin: 0 + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }], + output: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + backgroundColor: 'white', + color: 'black', + margin: 0, + padding: 0 + }); + `, + }, + ], +}); diff --git a/src/css-rules/alphabetical-order/__tests__/recipe.test.ts b/src/css-rules/alphabetical-order/__tests__/recipe.test.ts new file mode 100644 index 0000000..82ba7ed --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/recipe.test.ts @@ -0,0 +1,92 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/recipe', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Recipe with alphabetical ordering + ` + import { recipe } from '@vanilla-extract/recipes'; + + const myRecipe = recipe({ + base: { + alignItems: 'center', + display: 'flex' + }, + variants: { + color: { + blue: { + backgroundColor: 'blue', + color: 'white' + }, + red: { + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + ], + invalid: [ + // Recipe with incorrect ordering + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + display: 'flex', + alignItems: 'center' + }, + variants: { + color: { + blue: { + color: 'white', + backgroundColor: 'blue' + }, + red: { + color: 'black', + backgroundColor: 'red' + } + } + } + }); + `, + errors: [ + { messageId: 'alphabeticalOrder' }, + { messageId: 'alphabeticalOrder' }, + { messageId: 'alphabeticalOrder' }, + ], + output: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + alignItems: 'center', + display: 'flex' + }, + variants: { + color: { + blue: { + backgroundColor: 'blue', + color: 'white' + }, + red: { + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/alphabetical-order/__tests__/style.test.ts b/src/css-rules/alphabetical-order/__tests__/style.test.ts new file mode 100644 index 0000000..9b0587a --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/style.test.ts @@ -0,0 +1,111 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/style', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Basic style object with alphabetical ordering + ` + import { style } from '@vanilla-extract/css'; + + const myStyle = style({ + alignItems: 'center', + backgroundColor: 'red', + color: 'blue', + display: 'flex', + margin: '10px', + padding: '20px', + zIndex: 1 + }); + `, + + // Style with nested selectors + ` + import { style } from '@vanilla-extract/css'; + + const myStyle = style({ + alignItems: 'center', + backgroundColor: 'red', + color: 'blue', + selectors: { + '&:hover': { + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + ], + invalid: [ + // Basic style object with incorrect ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + backgroundColor: 'red', + alignItems: 'center', + padding: '20px', + color: 'blue', + margin: '10px', + display: 'flex', + zIndex: 1 + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + alignItems: 'center', + backgroundColor: 'red', + color: 'blue', + display: 'flex', + margin: '10px', + padding: '20px', + zIndex: 1 + }); + `, + }, + + // Style with nested selectors having incorrect ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + backgroundColor: 'red', + alignItems: 'center', + color: 'blue', + selectors: { + '&:hover': { + color: 'white', + backgroundColor: 'blue' + } + } + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }, { messageId: 'alphabeticalOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + alignItems: 'center', + backgroundColor: 'red', + color: 'blue', + selectors: { + '&:hover': { + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/alphabetical-order/__tests__/variants.test.ts b/src/css-rules/alphabetical-order/__tests__/variants.test.ts new file mode 100644 index 0000000..d30b572 --- /dev/null +++ b/src/css-rules/alphabetical-order/__tests__/variants.test.ts @@ -0,0 +1,64 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import alphabeticalOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/alphabetical-order/variants', + rule: alphabeticalOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // styleVariants with alphabetical ordering + ` + import { styleVariants } from '@vanilla-extract/css'; + + const variants = styleVariants({ + primary: { + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + backgroundColor: 'gray', + color: 'black' + } + }); + `, + ], + invalid: [ + // styleVariants with incorrect ordering + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + color: 'white', + backgroundColor: 'blue' + }, + secondary: { + color: 'black', + backgroundColor: 'gray' + } + }); + `, + errors: [{ messageId: 'alphabeticalOrder' }, { messageId: 'alphabeticalOrder' }], + output: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + backgroundColor: 'gray', + color: 'black' + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/animation.test.ts b/src/css-rules/concentric-order/__tests__/animation.test.ts new file mode 100644 index 0000000..820b186 --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/animation.test.ts @@ -0,0 +1,70 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/animation', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // keyframes with concentric ordering + ` + import { keyframes } from '@vanilla-extract/css'; + + const fadeIn = keyframes({ + '0%': { + position: 'relative', + transform: 'translateY(1rem)', + opacity: 0 + }, + '100%': { + position: 'relative', + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + ], + invalid: [ + // keyframes with incorrect ordering + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + opacity: 0, + transform: 'translateY(1rem)', + position: 'relative' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)', + position: 'relative' + } + }); + `, + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + position: 'relative', + transform: 'translateY(1rem)', + opacity: 0 + }, + '100%': { + position: 'relative', + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/font-face.test.ts b/src/css-rules/concentric-order/__tests__/font-face.test.ts new file mode 100644 index 0000000..077b322 --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/font-face.test.ts @@ -0,0 +1,97 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/font-face', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // fontFace with src first and other properties alphabetically ordered + ` + import { fontFace } from '@vanilla-extract/css'; + + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + + // globalFontFace with src first and other properties alphabetically ordered + ` + import { globalFontFace } from '@vanilla-extract/css'; + + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + ], + invalid: [ + // fontFace with src not first + { + code: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + fontWeight: '400', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + + // globalFontFace with src not first + { + code: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + fontWeight: '400', + fontStyle: 'normal', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%' + }); + `, + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/global.test.ts b/src/css-rules/concentric-order/__tests__/global.test.ts new file mode 100644 index 0000000..b2d91f2 --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/global.test.ts @@ -0,0 +1,58 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/global', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // globalStyle with concentric ordering + ` + import { globalStyle } from '@vanilla-extract/css'; + + globalStyle('body', { + position: 'relative', + display: 'block', + margin: 0, + backgroundColor: 'white', + padding: 0, + color: 'black' + }); + `, + ], + invalid: [ + // globalStyle with incorrect ordering + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + color: 'black', + margin: 0, + backgroundColor: 'white', + padding: 0, + display: 'block', + position: 'relative' + }); + `, + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + position: 'relative', + display: 'block', + margin: 0, + backgroundColor: 'white', + padding: 0, + color: 'black' + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/recipe.test.ts b/src/css-rules/concentric-order/__tests__/recipe.test.ts new file mode 100644 index 0000000..0eff340 --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/recipe.test.ts @@ -0,0 +1,101 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/recipe', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Recipe with concentric ordering + ` + import { recipe } from '@vanilla-extract/recipes'; + + const myRecipe = recipe({ + base: { + position: 'relative', + display: 'flex', + alignItems: 'center', + backgroundColor: 'white', + width: '100%' + }, + variants: { + color: { + blue: { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + }, + red: { + position: 'relative', + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + ], + invalid: [ + // Recipe with incorrect ordering + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + backgroundColor: 'white', + width: '100%', + display: 'flex', + alignItems: 'center' + }, + variants: { + color: { + blue: { + color: 'white', + backgroundColor: 'blue', + position: 'relative' + }, + red: { + color: 'black', + backgroundColor: 'red', + position: 'relative' + } + } + } + }); + `, + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + display: 'flex', + alignItems: 'center', + backgroundColor: 'white', + width: '100%' + }, + variants: { + color: { + blue: { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + }, + red: { + position: 'relative', + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/style.test.ts b/src/css-rules/concentric-order/__tests__/style.test.ts new file mode 100644 index 0000000..5f8ea0b --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/style.test.ts @@ -0,0 +1,129 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/style', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Basic style object with concentric ordering + ` + import { style } from '@vanilla-extract/css'; + + const myStyle = style({ + boxSizing: 'border-box', + position: 'relative', + zIndex: 1, + display: 'flex', + alignItems: 'center', + transform: 'none', + opacity: 1, + margin: '1rem', + border: '1px solid black', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + backgroundColor: 'red', + padding: '2rem', + width: '10rem', + height: '10rem', + color: 'blue', + fontSize: '16rem' + }); + `, + + // Style with nested selectors + ` + import { style } from '@vanilla-extract/css'; + + const myStyle = style({ + position: 'relative', + display: 'flex', + alignItems: 'center', + backgroundColor: 'red', + color: 'blue', + + selectors: { + '&:hover': { + position: 'relative', + opacity: 0.8, + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + ], + invalid: [ + // Basic style object with incorrect ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + color: 'blue', + width: '10rem', + display: 'flex', + backgroundColor: 'red', + margin: '1rem', + position: 'relative' + }); + `, + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + position: 'relative', + display: 'flex', + margin: '1rem', + backgroundColor: 'red', + width: '10rem', + color: 'blue' + }); + `, + }, + + // Style with nested selectors having incorrect ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + color: 'blue', + display: 'flex', + backgroundColor: 'red', + position: 'relative', + + selectors: { + '&:hover': { + color: 'white', + position: 'relative', + backgroundColor: 'blue' + } + } + }); + `, + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + position: 'relative', + display: 'flex', + backgroundColor: 'red', + color: 'blue', + + selectors: { + '&:hover': { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/concentric-order/__tests__/variants.test.ts b/src/css-rules/concentric-order/__tests__/variants.test.ts new file mode 100644 index 0000000..c5a43c1 --- /dev/null +++ b/src/css-rules/concentric-order/__tests__/variants.test.ts @@ -0,0 +1,135 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import concentricOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/concentric-order/variants', + rule: concentricOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // styleVariants with concentric ordering + ` + import { styleVariants } from '@vanilla-extract/css'; + + const variants = styleVariants({ + primary: { + position: 'relative', + display: 'flex', + margin: '1rem', + backgroundColor: 'blue', + padding: '0.5rem', + color: 'white' + }, + secondary: { + position: 'relative', + display: 'flex', + margin: '0.8rem', + backgroundColor: 'gray', + padding: '0.4rem', + color: 'black' + } + }); + `, + ], + invalid: [ + // styleVariants with incorrect ordering + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + color: 'white', + backgroundColor: 'blue', + padding: '0.5rem', + margin: '1rem', + display: 'flex', + position: 'relative' + }, + secondary: { + color: 'black', + backgroundColor: 'gray', + padding: '0.4rem', + margin: '0.8rem', + display: 'flex', + position: 'relative' + } + }); + `, + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + position: 'relative', + display: 'flex', + margin: '1rem', + backgroundColor: 'blue', + padding: '0.5rem', + color: 'white' + }, + secondary: { + position: 'relative', + display: 'flex', + margin: '0.8rem', + backgroundColor: 'gray', + padding: '0.4rem', + color: 'black' + } + }); + `, + }, + + // styleVariants with some variants having incorrect ordering + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + position: 'relative', + display: 'flex', + margin: '1rem', + padding: '0.5rem', + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + color: 'black', + backgroundColor: 'gray', + padding: '0.4rem', + margin: '0.8rem', + display: 'flex', + position: 'relative' + } + }); + `, + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + position: 'relative', + display: 'flex', + margin: '1rem', + backgroundColor: 'blue', + padding: '0.5rem', + color: 'white' + }, + secondary: { + position: 'relative', + display: 'flex', + margin: '0.8rem', + backgroundColor: 'gray', + padding: '0.4rem', + color: 'black' + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/animation.test.ts b/src/css-rules/custom-order/__tests__/animation.test.ts new file mode 100644 index 0000000..b31f165 --- /dev/null +++ b/src/css-rules/custom-order/__tests__/animation.test.ts @@ -0,0 +1,151 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/animation', + rule: customGroupOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // keyframes with custom group ordering (concentric for remaining) + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + + const fadeIn = keyframes({ + '0%': { + position: 'relative', + transform: 'translateY(1rem)', + opacity: 0 + }, + '100%': { + position: 'relative', + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // keyframes with custom group ordering (alphabetical for remaining) + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + + const fadeIn = keyframes({ + '0%': { + opacity: 0, + position: 'relative', + transform: 'translateY(1rem)' + }, + '100%': { + opacity: 1, + position: 'relative', + transform: 'translateY(0)' + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + }, + ], + invalid: [ + // keyframes with incorrect ordering (concentric for remaining) + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + opacity: 0, + transform: 'translateY(1rem)', + position: 'relative' + }, + '100%': { + opacity: 1, + transform: 'translateY(0)', + position: 'relative' + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + position: 'relative', + transform: 'translateY(1rem)', + opacity: 0 + }, + '100%': { + position: 'relative', + transform: 'translateY(0)', + opacity: 1 + } + }); + `, + }, + + // keyframes with incorrect ordering (alphabetical for remaining) + { + code: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + transform: 'translateY(1rem)', + position: 'relative', + opacity: 0 + }, + '100%': { + transform: 'translateY(0)', + position: 'relative', + opacity: 1 + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { keyframes } from '@vanilla-extract/css'; + const fadeIn = keyframes({ + '0%': { + opacity: 0, + position: 'relative', + transform: 'translateY(1rem)' + }, + '100%': { + opacity: 1, + position: 'relative', + transform: 'translateY(0)' + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/font-face.test.ts b/src/css-rules/custom-order/__tests__/font-face.test.ts new file mode 100644 index 0000000..7d2866b --- /dev/null +++ b/src/css-rules/custom-order/__tests__/font-face.test.ts @@ -0,0 +1,127 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/font-face', + rule: customGroupOrderRule, + configs: { + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + }, + valid: [ + // fontFace + { + code: ` + import { fontFace } from '@vanilla-extract/css'; + + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // globalFontFace + { + code: ` + import { globalFontFace } from '@vanilla-extract/css'; + + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + descentOverride: '10%', + fontDisplay: 'swap', + fontFeatureSettings: '"liga" 1', + fontStretch: 'normal', + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: '400' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font'], + sortRemainingProperties: 'concentric', + }, + ], + }, + ], + invalid: [ + // fontFace with src not first + { + code: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + fontWeight: '400', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { fontFace } from '@vanilla-extract/css'; + const myFont = fontFace({ + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + + // globalFontFace with src not first + { + code: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + fontWeight: '400', + fontStyle: 'normal', + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'fontFaceOrder' }], + output: ` + import { globalFontFace } from '@vanilla-extract/css'; + globalFontFace('GlobalFont', { + src: ['url("/fonts/MyFont.woff2") format("woff2")'], + ascentOverride: '90%', + fontStyle: 'normal', + fontWeight: '400' + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/global.test.ts b/src/css-rules/custom-order/__tests__/global.test.ts new file mode 100644 index 0000000..99f45a9 --- /dev/null +++ b/src/css-rules/custom-order/__tests__/global.test.ts @@ -0,0 +1,127 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/global', + rule: customGroupOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // globalStyle with custom group ordering (concentric for remaining) + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + + globalStyle('body', { + margin: 0, + position: 'relative', + display: 'block', + backgroundColor: 'white', + padding: 0, + color: 'black' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // globalStyle with custom group ordering (alphabetical for remaining) + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + + globalStyle('body', { + margin: 0, + backgroundColor: 'white', + color: 'black', + display: 'block', + padding: 0, + position: 'relative' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + }, + ], + invalid: [ + // globalStyle with incorrect ordering (concentric for remaining) + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + color: 'black', + margin: 0, + backgroundColor: 'white', + padding: 0, + display: 'block', + position: 'relative' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + margin: 0, + position: 'relative', + display: 'block', + backgroundColor: 'white', + padding: 0, + color: 'black' + }); + `, + }, + + // globalStyle with incorrect ordering (alphabetical for remaining) + { + code: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + position: 'relative', + display: 'block', + margin: 0, + backgroundColor: 'white', + padding: 0, + color: 'black' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { globalStyle } from '@vanilla-extract/css'; + globalStyle('body', { + margin: 0, + backgroundColor: 'white', + color: 'black', + display: 'block', + padding: 0, + position: 'relative' + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/recipe.test.ts b/src/css-rules/custom-order/__tests__/recipe.test.ts new file mode 100644 index 0000000..16e66e7 --- /dev/null +++ b/src/css-rules/custom-order/__tests__/recipe.test.ts @@ -0,0 +1,211 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/recipe', + rule: customGroupOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Recipe with custom group ordering (concentric for remaining) + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + + const myRecipe = recipe({ + base: { + width: '100%', + margin: 0, + position: 'relative', + display: 'flex', + alignItems: 'center', + backgroundColor: 'white' + }, + variants: { + color: { + blue: { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + }, + red: { + position: 'relative', + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // Recipe with custom group ordering (alphabetical for remaining) + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + + const myRecipe = recipe({ + base: { + width: '100%', + margin: 0, + alignItems: 'center', + backgroundColor: 'white', + display: 'flex', + position: 'relative' + }, + variants: { + color: { + blue: { + backgroundColor: 'blue', + color: 'white', + position: 'relative' + }, + red: { + backgroundColor: 'red', + color: 'black', + position: 'relative' + } + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + }, + ], + invalid: [ + // Recipe with incorrect ordering (concentric for remaining) + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + backgroundColor: 'white', + width: '100%', + display: 'flex', + alignItems: 'center', + margin: 0 + }, + variants: { + color: { + blue: { + color: 'white', + backgroundColor: 'blue', + position: 'relative' + }, + red: { + color: 'black', + backgroundColor: 'red', + position: 'relative' + } + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + width: '100%', + margin: 0, + display: 'flex', + alignItems: 'center', + backgroundColor: 'white' + }, + variants: { + color: { + blue: { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + }, + red: { + position: 'relative', + backgroundColor: 'red', + color: 'black' + } + } + } + }); + `, + }, + + // Recipe with incorrect ordering (alphabetical for remaining) + { + code: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + position: 'relative', + display: 'flex', + alignItems: 'center', + backgroundColor: 'white', + width: '100%', + margin: 0 + }, + variants: { + color: { + blue: { + position: 'relative', + backgroundColor: 'blue', + color: 'white' + } + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { recipe } from '@vanilla-extract/recipes'; + const myRecipe = recipe({ + base: { + width: '100%', + margin: 0, + alignItems: 'center', + backgroundColor: 'white', + display: 'flex', + position: 'relative' + }, + variants: { + color: { + blue: { + backgroundColor: 'blue', + color: 'white', + position: 'relative' + } + } + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/style.test.ts b/src/css-rules/custom-order/__tests__/style.test.ts new file mode 100644 index 0000000..f770123 --- /dev/null +++ b/src/css-rules/custom-order/__tests__/style.test.ts @@ -0,0 +1,252 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/style', + rule: customGroupOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // Style with custom group ordering (dimensions, margin, font, border, boxShadow) + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + // dimensions group first + width: '10rem', + minWidth: '5rem', + height: '10rem', + maxHeight: '20rem', + + // margin group second + margin: '1rem', + marginTop: '0.5rem', + + // font group third + fontFamily: 'sans-serif', + fontSize: '1rem', + fontWeight: 'bold', + + // border group fourth + border: '1px solid black', + borderRadius: '4px', + + // boxShadow group fifth + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + + // remaining properties in concentric order + position: 'relative', + display: 'flex', + backgroundColor: 'red', + padding: '2rem', + color: 'blue' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // Style with nested selectors following custom group ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + width: '10rem', + margin: '1rem', + fontFamily: 'sans-serif', + border: '1px solid black', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + position: 'relative', + backgroundColor: 'red', + selectors: { + '&:hover': { + width: '12rem', + margin: '12px', + fontSize: '1rem', + borderColor: 'blue', + boxShadow: '0 4px 8px rgba(0,0,0,0.2)', + position: 'relative', + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + // dimensions group first + width: '10rem', + height: '10rem', + + // margin group second + margin: '1rem', + + // font group third + fontFamily: 'sans-serif', + + // border group fourth + border: '1px solid black', + + // boxShadow group fifth + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + + // remaining properties in alphabetical order + backgroundColor: 'red', + color: 'blue', + display: 'flex', + padding: '2rem', + position: 'relative' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + }, + ], + invalid: [ + // Style with incorrect custom group ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + position: 'relative', + border: '1px solid black', + width: '10rem', + color: 'blue', + margin: '1rem', + fontFamily: 'sans-serif', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + backgroundColor: 'red' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + width: '10rem', + margin: '1rem', + fontFamily: 'sans-serif', + border: '1px solid black', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + position: 'relative', + backgroundColor: 'red', + color: 'blue' + }); + `, + }, + + // Style with nested selectors having incorrect ordering + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + border: '1px solid black', + width: '10rem', + position: 'relative', + margin: '1rem', + selectors: { + '&:hover': { + color: 'white', + width: '12rem', + border: '2px solid blue', + margin: '1.2rem', + backgroundColor: 'blue' + } + } + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + width: '10rem', + margin: '1rem', + border: '1px solid black', + position: 'relative', + selectors: { + '&:hover': { + width: '12rem', + margin: '1.2rem', + border: '2px solid blue', + backgroundColor: 'blue', + color: 'white' + } + } + }); + `, + }, + { + code: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + position: 'relative', + border: '1px solid black', + width: '10rem', + padding: '2rem', + color: 'blue', + margin: '1rem', + display: 'flex', + fontFamily: 'sans-serif', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + backgroundColor: 'red' + }); + `, + options: [ + { + groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + errors: [{ messageId: 'incorrectOrder' }], + output: ` + import { style } from '@vanilla-extract/css'; + const myStyle = style({ + width: '10rem', + margin: '1rem', + fontFamily: 'sans-serif', + border: '1px solid black', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + backgroundColor: 'red', + color: 'blue', + display: 'flex', + padding: '2rem', + position: 'relative' + }); + `, + }, + ], +}); diff --git a/src/css-rules/custom-order/__tests__/variants.test.ts b/src/css-rules/custom-order/__tests__/variants.test.ts new file mode 100644 index 0000000..18187e5 --- /dev/null +++ b/src/css-rules/custom-order/__tests__/variants.test.ts @@ -0,0 +1,187 @@ +import tsParser from '@typescript-eslint/parser'; +import { run } from 'eslint-vitest-rule-tester'; +import customGroupOrderRule from '../rule-definition.js'; + +run({ + name: 'vanilla-extract/custom-order/variants', + rule: customGroupOrderRule, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + valid: [ + // styleVariants with custom group ordering (concentric for remaining) + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + + const variants = styleVariants({ + primary: { + margin: '1rem', + padding: '0.5rem', + position: 'relative', + display: 'flex', + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + margin: '0.8rem', + padding: '0.4rem', + position: 'relative', + display: 'flex', + backgroundColor: 'gray', + color: 'black' + } + }); + `, + options: [ + { + groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + }, + + // styleVariants with custom group ordering (alphabetical for remaining) + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + + const variants = styleVariants({ + primary: { + margin: '1rem', + padding: '0.5rem', + backgroundColor: 'blue', + color: 'white', + display: 'flex', + position: 'relative' + }, + secondary: { + margin: '0.8rem', + padding: '0.4rem', + backgroundColor: 'gray', + color: 'black', + display: 'flex', + position: 'relative' + } + }); + `, + options: [ + { + groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + }, + ], + invalid: [ + // styleVariants with incorrect ordering (concentric for remaining) + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + color: 'white', + backgroundColor: 'blue', + padding: '0.5rem', + margin: '1rem', + display: 'flex', + position: 'relative' + }, + secondary: { + color: 'black', + backgroundColor: 'gray', + padding: '0.4rem', + margin: '0.8rem', + display: 'flex', + position: 'relative' + } + }); + `, + options: [ + { + groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'concentric', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + margin: '1rem', + padding: '0.5rem', + position: 'relative', + display: 'flex', + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + margin: '0.8rem', + padding: '0.4rem', + position: 'relative', + display: 'flex', + backgroundColor: 'gray', + color: 'black' + } + }); + `, + }, + + // styleVariants with incorrect ordering (alphabetical for remaining) + { + code: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + position: 'relative', + display: 'flex', + margin: '1rem', + padding: '0.5rem', + backgroundColor: 'blue', + color: 'white' + }, + secondary: { + color: 'black', + backgroundColor: 'gray', + padding: '0.4rem', + margin: '0.8rem', + display: 'flex', + position: 'relative' + } + }); + `, + options: [ + { + groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'], + sortRemainingProperties: 'alphabetical', + }, + ], + errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }], + output: ` + import { styleVariants } from '@vanilla-extract/css'; + const variants = styleVariants({ + primary: { + margin: '1rem', + padding: '0.5rem', + backgroundColor: 'blue', + color: 'white', + display: 'flex', + position: 'relative' + }, + secondary: { + margin: '0.8rem', + padding: '0.4rem', + backgroundColor: 'gray', + color: 'black', + display: 'flex', + position: 'relative' + } + }); + `, + }, + ], +}); diff --git a/src/css-rules/shared-utils/order-strategy-visitor-creator.ts b/src/css-rules/shared-utils/order-strategy-visitor-creator.ts index 19d8bae..dc36d28 100644 --- a/src/css-rules/shared-utils/order-strategy-visitor-creator.ts +++ b/src/css-rules/shared-utils/order-strategy-visitor-creator.ts @@ -18,9 +18,10 @@ import { processStyleNode } from './style-node-processor.js'; * @returns An object with visitor functions for the ESLint rule. * * This function sets up visitors for the following cases: - * 1. Style-related functions: 'style', 'styleVariants', 'createVar', 'createTheme', 'createThemeContract' - * 2. The 'globalStyle' function - * 3. The 'recipe' function + * 1. The fontFace and globalFontFace functions. + * 2. Style-related functions: 'keyframes', 'style', 'styleVariants'. + * 3. The 'globalStyle' and 'globalKeyframes' function + * 4. The 'recipe' function * * Each visitor applies the appropriate ordering strategy to the style objects in these function calls. */ @@ -80,11 +81,7 @@ export const createNodeVisitors = ( } // Handle style-related functions - if ( - ['createThemeContract', 'createVar', 'createTheme', 'keyframes', 'style', 'styleVariants'].includes( - node.callee.name, - ) - ) { + if (['keyframes', 'style', 'styleVariants'].includes(node.callee.name)) { if (node.arguments.length > 0) { const styleArguments = node.arguments[0]; processStyleNode(ruleContext, styleArguments as TSESTree.Node, processProperty); diff --git a/src/index.ts b/src/index.ts index 1982048..4eb2c03 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import customOrderRule from './css-rules/custom-order/rule-definition.js'; export const vanillaExtract = { meta: { name: '@antebudimir/eslint-plugin-vanilla-extract', - version: '1.4.0', + version: '1.4.1', }, rules: { 'alphabetical-order': alphabeticalOrderRule, diff --git a/vitest.config.mjs b/vitest.config.mjs new file mode 100644 index 0000000..90151e4 --- /dev/null +++ b/vitest.config.mjs @@ -0,0 +1,31 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + coverage: { + provider: 'v8', + reporter: ['html', 'json', 'text'], + reportsDirectory: './coverage/vitest-reports', + // include: ['src/**/rule-definition.ts'], + include: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/__tests__/**'], + // exclude: [ + // 'src/**/*.css.ts', + // 'src/**/*.test.ts', + // 'src/**/*constants.ts', + // 'src/**/*index.ts', + // // Exclude all icon directories and their contents + // 'src/components/common/icons/**', + // // But include the CheckboxIcon component + // '!src/components/common/icons/checkbox-icon/CheckboxIcon.tsx', + // ], + }, + reporters: [ + 'default', + ['json', { outputFile: './coverage/vitest-results/vitest-results.json' }], + ['junit', { outputFile: './coverage/vitest-results/vitest-results.xml' }], + ], + environment: 'node', + include: ['src/**/*.test.ts'], + globals: true, + }, +});