mirror of
https://github.com/BradNut/personal-website-sveltekit
synced 2025-09-08 23:20:18 +00:00
Adding playwright tests for home and about page. Adding github actions.
This commit is contained in:
parent
8a66b190b7
commit
2714d05917
12 changed files with 807 additions and 221 deletions
4
.github/workflows/svelte_check.yml
vendored
4
.github/workflows/svelte_check.yml
vendored
|
|
@ -2,6 +2,10 @@ name: Run_Svelte_Check_on_PRs
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- development
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
|
|
|
|||
48
.github/workflows/svelte_integration.yml
vendored
Normal file
48
.github/workflows/svelte_integration.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: Run_Svelte_Integration_on_PRs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- development
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
WALLABAG_MAX_ARTICLES: ${{ secrets.WALLABAG_MAX_ARTICLES }}
|
||||
WALLABAG_MAX_PAGES: ${{ secrets.WALLABAG_MAX_PAGES }}
|
||||
WALLABAG_CLIENT_ID: ${{ secrets.WALLABAG_CLIENT_ID }}
|
||||
WALLABAG_CLIENT_SECRET: ${{ secrets.WALLABAG_CLIENT_SECRET }}
|
||||
WALLABAG_USERNAME: ${{ secrets.WALLABAG_USERNAME }}
|
||||
WALLABAG_PASSWORD: ${{ secrets.WALLABAG_PASSWORD }}
|
||||
WALLABAG_URL: ${{ secrets.WALLABAG_URL }}
|
||||
BANDCAMP_USERNAME: ${{ secrets.BANDCAMP_USERNAME }}
|
||||
PUBLIC_SITE_URL: ${{ secrets.PUBLIC_SITE_URL }}
|
||||
PUBLIC_URL: ${{ secrets.PUBLIC_URL }}
|
||||
PUBLIC_UMAMI_DO_NOT_TRACK: ${{ secrets.PUBLIC_UMAMI_DO_NOT_TRACK }}
|
||||
PUBLIC_UMAMI_URL: ${{ secrets.PUBLIC_UMAMI_URL }}
|
||||
PUBLIC_UMAMI_ID: ${{ secrets.PUBLIC_UMAMI_ID }}
|
||||
PAGE_SIZE: ${{ secrets.PAGE_SIZE }}
|
||||
USE_REDIS_CACHE: ${{ secrets.USE_REDIS_CACHE }}
|
||||
REDIS_URI: ${{ secrets.REDIS_URI }}
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ubuntu-latest # or macos-latest, windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
|
||||
- uses: microsoft/playwright-github-action@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies and run tests
|
||||
run: pnpm install && pnpm test:integration
|
||||
58
.github/workflows/svelte_unit.yml
vendored
Normal file
58
.github/workflows/svelte_unit.yml
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
name: Run_Svelte_Unit_on_PRs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- development
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- development
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
WALLABAG_MAX_ARTICLES: ${{ secrets.WALLABAG_MAX_ARTICLES }}
|
||||
WALLABAG_MAX_PAGES: ${{ secrets.WALLABAG_MAX_PAGES }}
|
||||
WALLABAG_CLIENT_ID: ${{ secrets.WALLABAG_CLIENT_ID }}
|
||||
WALLABAG_CLIENT_SECRET: ${{ secrets.WALLABAG_CLIENT_SECRET }}
|
||||
WALLABAG_USERNAME: ${{ secrets.WALLABAG_USERNAME }}
|
||||
WALLABAG_PASSWORD: ${{ secrets.WALLABAG_PASSWORD }}
|
||||
WALLABAG_URL: ${{ secrets.WALLABAG_URL }}
|
||||
BANDCAMP_USERNAME: ${{ secrets.BANDCAMP_USERNAME }}
|
||||
PUBLIC_SITE_URL: ${{ secrets.PUBLIC_SITE_URL }}
|
||||
PUBLIC_URL: ${{ secrets.PUBLIC_URL }}
|
||||
PUBLIC_UMAMI_DO_NOT_TRACK: ${{ secrets.PUBLIC_UMAMI_DO_NOT_TRACK }}
|
||||
PUBLIC_UMAMI_URL: ${{ secrets.PUBLIC_UMAMI_URL }}
|
||||
PUBLIC_UMAMI_ID: ${{ secrets.PUBLIC_UMAMI_ID }}
|
||||
PAGE_SIZE: ${{ secrets.PAGE_SIZE }}
|
||||
USE_REDIS_CACHE: ${{ secrets.USE_REDIS_CACHE }}
|
||||
REDIS_URI: ${{ secrets.REDIS_URI }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: pnpm-setup
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Execute unit tests
|
||||
run: pnpm test:unit
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"workbench.colorTheme": "Dark+ (default dark)",
|
||||
}
|
||||
10
package.json
10
package.json
|
|
@ -18,7 +18,7 @@
|
|||
"test:unit": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.2.0",
|
||||
"@biomejs/biome": "^2.2.2",
|
||||
"@chromatic-com/storybook": "^4.1.1",
|
||||
"@internationalized/date": "^3.8.2",
|
||||
"@playwright/test": "^1.55.0",
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
"@storybook/addon-svelte-csf": "^5.0.8",
|
||||
"@storybook/sveltekit": "^9.1.3",
|
||||
"@sveltejs/enhanced-img": "^0.5.1",
|
||||
"@sveltejs/kit": "^2.36.1",
|
||||
"@sveltejs/kit": "^2.36.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.1.1",
|
||||
"@unpic/svelte": "^1.0.0",
|
||||
"@zerodevx/svelte-img": "^2.1.2",
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
"postcss-custom-media": "^11.0.6",
|
||||
"postcss-import": "^16.1.1",
|
||||
"postcss-load-config": "^6.0.1",
|
||||
"postcss-preset-env": "^10.2.4",
|
||||
"postcss-preset-env": "^10.3.0",
|
||||
"satori": "^0.12.2",
|
||||
"satori-html": "^0.3.2",
|
||||
"storybook": "^9.1.3",
|
||||
|
|
@ -57,10 +57,10 @@
|
|||
"@resvg/resvg-js": "^2.6.2",
|
||||
"@sveltejs/adapter-node": "^5.3.1",
|
||||
"@vercel/og": "^0.6.8",
|
||||
"bits-ui": "2.9.2",
|
||||
"bits-ui": "2.9.4",
|
||||
"flexsearch": "^0.8.205",
|
||||
"ioredis": "^5.7.0",
|
||||
"lucide-svelte": "^0.539.0",
|
||||
"lucide-svelte": "^0.541.0",
|
||||
"scrape-it": "^6.1.11",
|
||||
"sharp": "^0.34.3",
|
||||
"svelte-local-storage-store": "^0.6.4"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ import type { PlaywrightTestConfig } from '@playwright/test';
|
|||
const config: PlaywrightTestConfig = {
|
||||
webServer: {
|
||||
command: 'pnpm run build && pnpm run preview',
|
||||
port: 4173
|
||||
port: 4173,
|
||||
timeout: 180_000,
|
||||
reuseExistingServer: true
|
||||
},
|
||||
testDir: 'tests',
|
||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/,
|
||||
|
|
|
|||
368
pnpm-lock.yaml
368
pnpm-lock.yaml
|
|
@ -13,13 +13,13 @@ importers:
|
|||
version: 2.6.2
|
||||
'@sveltejs/adapter-node':
|
||||
specifier: ^5.3.1
|
||||
version: 5.3.1(@sveltejs/kit@2.36.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))
|
||||
version: 5.3.1(@sveltejs/kit@2.36.2(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))
|
||||
'@vercel/og':
|
||||
specifier: ^0.6.8
|
||||
version: 0.6.8
|
||||
bits-ui:
|
||||
specifier: 2.9.2
|
||||
version: 2.9.2(@internationalized/date@3.8.2)(svelte@5.38.2)
|
||||
specifier: 2.9.4
|
||||
version: 2.9.4(@internationalized/date@3.8.2)(svelte@5.38.2)
|
||||
flexsearch:
|
||||
specifier: ^0.8.205
|
||||
version: 0.8.205
|
||||
|
|
@ -27,8 +27,8 @@ importers:
|
|||
specifier: ^5.7.0
|
||||
version: 5.7.0
|
||||
lucide-svelte:
|
||||
specifier: ^0.539.0
|
||||
version: 0.539.0(svelte@5.38.2)
|
||||
specifier: ^0.541.0
|
||||
version: 0.541.0(svelte@5.38.2)
|
||||
scrape-it:
|
||||
specifier: ^6.1.11
|
||||
version: 6.1.11
|
||||
|
|
@ -40,8 +40,8 @@ importers:
|
|||
version: 0.6.4(svelte@5.38.2)
|
||||
devDependencies:
|
||||
'@biomejs/biome':
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@chromatic-com/storybook':
|
||||
specifier: ^4.1.1
|
||||
version: 4.1.1(storybook@9.1.3(@testing-library/dom@10.4.1)(vite@6.3.5(yaml@2.7.0)))
|
||||
|
|
@ -67,8 +67,8 @@ importers:
|
|||
specifier: ^0.5.1
|
||||
version: 0.5.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(rollup@4.34.8)(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
'@sveltejs/kit':
|
||||
specifier: ^2.36.1
|
||||
version: 2.36.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
specifier: ^2.36.2
|
||||
version: 2.36.2(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
|
|
@ -97,8 +97,8 @@ importers:
|
|||
specifier: ^6.0.1
|
||||
version: 6.0.1(postcss@8.5.6)(yaml@2.7.0)
|
||||
postcss-preset-env:
|
||||
specifier: ^10.2.4
|
||||
version: 10.2.4(postcss@8.5.6)
|
||||
specifier: ^10.3.0
|
||||
version: 10.3.0(postcss@8.5.6)
|
||||
satori:
|
||||
specifier: ^0.12.2
|
||||
version: 0.12.2
|
||||
|
|
@ -113,7 +113,7 @@ importers:
|
|||
version: 5.38.2
|
||||
svelte-check:
|
||||
specifier: ^4.3.1
|
||||
version: 4.3.1(picomatch@4.0.3)(svelte@5.38.2)(typescript@5.9.2)
|
||||
version: 4.3.1(picomatch@4.0.2)(svelte@5.38.2)(typescript@5.9.2)
|
||||
svelte-meta-tags:
|
||||
specifier: ^4.4.0
|
||||
version: 4.4.0(svelte@5.38.2)
|
||||
|
|
@ -163,55 +163,55 @@ packages:
|
|||
resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@biomejs/biome@2.2.0':
|
||||
resolution: {integrity: sha512-3On3RSYLsX+n9KnoSgfoYlckYBoU6VRM22cw1gB4Y0OuUVSYd/O/2saOJMrA4HFfA1Ff0eacOvMN1yAAvHtzIw==}
|
||||
'@biomejs/biome@2.2.2':
|
||||
resolution: {integrity: sha512-j1omAiQWCkhuLgwpMKisNKnsM6W8Xtt1l0WZmqY/dFj8QPNkIoTvk4tSsi40FaAAkBE1PU0AFG2RWFBWenAn+w==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
hasBin: true
|
||||
|
||||
'@biomejs/cli-darwin-arm64@2.2.0':
|
||||
resolution: {integrity: sha512-zKbwUUh+9uFmWfS8IFxmVD6XwqFcENjZvEyfOxHs1epjdH3wyyMQG80FGDsmauPwS2r5kXdEM0v/+dTIA9FXAg==}
|
||||
'@biomejs/cli-darwin-arm64@2.2.2':
|
||||
resolution: {integrity: sha512-6ePfbCeCPryWu0CXlzsWNZgVz/kBEvHiPyNpmViSt6A2eoDf4kXs3YnwQPzGjy8oBgQulrHcLnJL0nkCh80mlQ==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@biomejs/cli-darwin-x64@2.2.0':
|
||||
resolution: {integrity: sha512-+OmT4dsX2eTfhD5crUOPw3RPhaR+SKVspvGVmSdZ9y9O/AgL8pla6T4hOn1q+VAFBHuHhsdxDRJgFCSC7RaMOw==}
|
||||
'@biomejs/cli-darwin-x64@2.2.2':
|
||||
resolution: {integrity: sha512-Tn4JmVO+rXsbRslml7FvKaNrlgUeJot++FkvYIhl1OkslVCofAtS35MPlBMhXgKWF9RNr9cwHanrPTUUXcYGag==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@biomejs/cli-linux-arm64-musl@2.2.0':
|
||||
resolution: {integrity: sha512-egKpOa+4FL9YO+SMUMLUvf543cprjevNc3CAgDNFLcjknuNMcZ0GLJYa3EGTCR2xIkIUJDVneBV3O9OcIlCEZQ==}
|
||||
'@biomejs/cli-linux-arm64-musl@2.2.2':
|
||||
resolution: {integrity: sha512-/MhYg+Bd6renn6i1ylGFL5snYUn/Ct7zoGVKhxnro3bwekiZYE8Kl39BSb0MeuqM+72sThkQv4TnNubU9njQRw==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-arm64@2.2.0':
|
||||
resolution: {integrity: sha512-6eoRdF2yW5FnW9Lpeivh7Mayhq0KDdaDMYOJnH9aT02KuSIX5V1HmWJCQQPwIQbhDh68Zrcpl8inRlTEan0SXw==}
|
||||
'@biomejs/cli-linux-arm64@2.2.2':
|
||||
resolution: {integrity: sha512-JfrK3gdmWWTh2J5tq/rcWCOsImVyzUnOS2fkjhiYKCQ+v8PqM+du5cfB7G1kXas+7KQeKSWALv18iQqdtIMvzw==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-x64-musl@2.2.0':
|
||||
resolution: {integrity: sha512-I5J85yWwUWpgJyC1CcytNSGusu2p9HjDnOPAFG4Y515hwRD0jpR9sT9/T1cKHtuCvEQ/sBvx+6zhz9l9wEJGAg==}
|
||||
'@biomejs/cli-linux-x64-musl@2.2.2':
|
||||
resolution: {integrity: sha512-ZCLXcZvjZKSiRY/cFANKg+z6Fhsf9MHOzj+NrDQcM+LbqYRT97LyCLWy2AS+W2vP+i89RyRM+kbGpUzbRTYWig==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-x64@2.2.0':
|
||||
resolution: {integrity: sha512-5UmQx/OZAfJfi25zAnAGHUMuOd+LOsliIt119x2soA2gLggQYrVPA+2kMUxR6Mw5M1deUF/AWWP2qpxgH7Nyfw==}
|
||||
'@biomejs/cli-linux-x64@2.2.2':
|
||||
resolution: {integrity: sha512-Ogb+77edO5LEP/xbNicACOWVLt8mgC+E1wmpUakr+O4nKwLt9vXe74YNuT3T1dUBxC/SnrVmlzZFC7kQJEfquQ==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-win32-arm64@2.2.0':
|
||||
resolution: {integrity: sha512-n9a1/f2CwIDmNMNkFs+JI0ZjFnMO0jdOyGNtihgUNFnlmd84yIYY2KMTBmMV58ZlVHjgmY5Y6E1hVTnSRieggA==}
|
||||
'@biomejs/cli-win32-arm64@2.2.2':
|
||||
resolution: {integrity: sha512-wBe2wItayw1zvtXysmHJQoQqXlTzHSpQRyPpJKiNIR21HzH/CrZRDFic1C1jDdp+zAPtqhNExa0owKMbNwW9cQ==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@biomejs/cli-win32-x64@2.2.0':
|
||||
resolution: {integrity: sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww==}
|
||||
'@biomejs/cli-win32-x64@2.2.2':
|
||||
resolution: {integrity: sha512-DAuHhHekGfiGb6lCcsT4UyxQmVwQiBCBUMwVra/dcOSs9q8OhfaZgey51MlekT3p8UwRqtXQfFuEJBhJNdLZwg==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -229,8 +229,8 @@ packages:
|
|||
'@csstools/css-parser-algorithms': ^3.0.5
|
||||
'@csstools/css-tokenizer': ^3.0.4
|
||||
|
||||
'@csstools/color-helpers@5.0.2':
|
||||
resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==}
|
||||
'@csstools/color-helpers@5.1.0':
|
||||
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@csstools/css-calc@2.1.4':
|
||||
|
|
@ -240,8 +240,8 @@ packages:
|
|||
'@csstools/css-parser-algorithms': ^3.0.5
|
||||
'@csstools/css-tokenizer': ^3.0.4
|
||||
|
||||
'@csstools/css-color-parser@3.0.10':
|
||||
resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==}
|
||||
'@csstools/css-color-parser@3.1.0':
|
||||
resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@csstools/css-parser-algorithms': ^3.0.5
|
||||
|
|
@ -264,32 +264,44 @@ packages:
|
|||
'@csstools/css-parser-algorithms': ^3.0.5
|
||||
'@csstools/css-tokenizer': ^3.0.4
|
||||
|
||||
'@csstools/postcss-alpha-function@1.0.0':
|
||||
resolution: {integrity: sha512-r2L8KNg5Wriq5n8IUQcjzy2Rh37J5YjzP9iOyHZL5fxdWYHB08vqykHQa4wAzN/tXwDuCHnhQDGCtxfS76xn7g==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-cascade-layers@5.0.2':
|
||||
resolution: {integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-color-function@4.0.10':
|
||||
resolution: {integrity: sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ==}
|
||||
'@csstools/postcss-color-function-display-p3-linear@1.0.0':
|
||||
resolution: {integrity: sha512-7q+OuUqfowRrP84m/Jl0wv3pfCQyUTCW5MxDIux+/yty5IkUUHOTigCjrC0Fjy3OT0ncGLudHbfLWmP7E1arNA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-color-mix-function@3.0.10':
|
||||
resolution: {integrity: sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q==}
|
||||
'@csstools/postcss-color-function@4.0.11':
|
||||
resolution: {integrity: sha512-AtH22zLHTLm64HLdpv5EedT/zmYTm1MtdQbQhRZXxEB6iYtS6SrS1jLX3TcmUWMFzpumK/OVylCm3HcLms4slw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments@1.0.0':
|
||||
resolution: {integrity: sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ==}
|
||||
'@csstools/postcss-color-mix-function@3.0.11':
|
||||
resolution: {integrity: sha512-cQpXBelpTx0YhScZM5Ve0jDCA4RzwFc7oNafzZOGgCHt/GQVYiU8Vevz9QJcwy/W0Pyi/BneY+KMjz23lI9r+Q==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-content-alt-text@2.0.6':
|
||||
resolution: {integrity: sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ==}
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments@1.0.1':
|
||||
resolution: {integrity: sha512-c7hyBtbF+jlHIcUGVdWY06bHICgguV9ypfcELU3eU3W/9fiz2dxM8PqxQk2ndXYTzLnwPvNNqu1yCmQ++N6Dcg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-content-alt-text@2.0.7':
|
||||
resolution: {integrity: sha512-cq/zWaEkpcg3RttJ5+GdNwk26NwxY5KgqgtNL777Fdd28AVGHxuBvqmK4Jq4oKhW1NX4M2LbgYAVVN0NZ+/XYQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -306,26 +318,26 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-gamut-mapping@2.0.10':
|
||||
resolution: {integrity: sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg==}
|
||||
'@csstools/postcss-gamut-mapping@2.0.11':
|
||||
resolution: {integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-gradients-interpolation-method@5.0.10':
|
||||
resolution: {integrity: sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw==}
|
||||
'@csstools/postcss-gradients-interpolation-method@5.0.11':
|
||||
resolution: {integrity: sha512-8M3mcNTL3cGIJXDnvrJ2oWEcKi3zyw7NeYheFKePUlBmLYm1gkw9Rr/BA7lFONrOPeQA3yeMPldrrws6lqHrug==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-hwb-function@4.0.10':
|
||||
resolution: {integrity: sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ==}
|
||||
'@csstools/postcss-hwb-function@4.0.11':
|
||||
resolution: {integrity: sha512-9meZbsVWTZkWsSBazQips3cHUOT29a/UAwFz0AMEXukvpIGGDR9+GMl3nIckWO5sPImsadu4F5Zy+zjt8QgCdA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-ic-unit@4.0.2':
|
||||
resolution: {integrity: sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA==}
|
||||
'@csstools/postcss-ic-unit@4.0.3':
|
||||
resolution: {integrity: sha512-RtYYm2qUIu9vAaHB0cC8rQGlOCQAUgEc2tMr7ewlGXYipBQKjoWmyVArqsk7SEr8N3tErq6P6UOJT3amaVof5Q==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -342,8 +354,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-light-dark-function@2.0.9':
|
||||
resolution: {integrity: sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ==}
|
||||
'@csstools/postcss-light-dark-function@2.0.10':
|
||||
resolution: {integrity: sha512-g7Lwb294lSoNnyrwcqoooh9fTAp47rRNo+ILg7SLRSMU3K9ePIwRt566sNx+pehiCelv4E1ICaU1EwLQuyF2qw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -402,14 +414,14 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-oklab-function@4.0.10':
|
||||
resolution: {integrity: sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg==}
|
||||
'@csstools/postcss-oklab-function@4.0.11':
|
||||
resolution: {integrity: sha512-9f03ZGxZ2VmSCrM4SDXlAYP+Xpu4VFzemfQUQFL9OYxAbpvDy0FjDipZ0i8So1pgs8VIbQI0bNjFWgfdpGw8ig==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-progressive-custom-properties@4.1.0':
|
||||
resolution: {integrity: sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA==}
|
||||
'@csstools/postcss-progressive-custom-properties@4.2.0':
|
||||
resolution: {integrity: sha512-fWCXRasX17N1NCPTCuwC3FJDV+Wc031f16cFuuMEfIsYJ1q5ABCa59W0C6VeMGqjNv6ldf37vvwXXAeaZjD9PA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -420,8 +432,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-relative-color-syntax@3.0.10':
|
||||
resolution: {integrity: sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g==}
|
||||
'@csstools/postcss-relative-color-syntax@3.0.11':
|
||||
resolution: {integrity: sha512-oQ5fZvkcBrWR+k6arHXk0F8FlkmD4IxM+rcGDLWrF2f31tWyEM3lSraeWAV0f7BGH6LIrqmyU3+Qo/1acfoJng==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -444,8 +456,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@csstools/postcss-text-decoration-shorthand@4.0.2':
|
||||
resolution: {integrity: sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA==}
|
||||
'@csstools/postcss-text-decoration-shorthand@4.0.3':
|
||||
resolution: {integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -639,8 +651,8 @@ packages:
|
|||
'@floating-ui/core@1.7.3':
|
||||
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
|
||||
|
||||
'@floating-ui/dom@1.7.3':
|
||||
resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==}
|
||||
'@floating-ui/dom@1.7.4':
|
||||
resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
|
||||
|
||||
'@floating-ui/utils@0.2.10':
|
||||
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
||||
|
|
@ -1332,8 +1344,8 @@ packages:
|
|||
svelte: ^5.0.0
|
||||
vite: '>= 5.0.0'
|
||||
|
||||
'@sveltejs/kit@2.36.1':
|
||||
resolution: {integrity: sha512-dldNCtSIpaGxQMEfHaUxSPH/k3uU28pTZwtKzfkn8fqpOjWufKlMBeIL7FJ/s93dOrhEq41zaQYkXh+XTgEgVw==}
|
||||
'@sveltejs/kit@2.36.2':
|
||||
resolution: {integrity: sha512-WlBGY060nHe4UE5QrDAJAbls5hOsG6mljtrDGkM8jJCDQ4JEcAEH04XrTVmQ0Ex1CU8nzoZto0EE75aiLA3G8Q==}
|
||||
engines: {node: '>=18.13'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -1522,8 +1534,8 @@ packages:
|
|||
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
bits-ui@2.9.2:
|
||||
resolution: {integrity: sha512-GGbyr4oVKtHin//Q0AhlygkasmfWt328VjsnmB3sP+h8Sh+Eyghm+1AQ8o+xQMDCYbdL35JZ9UZGTZYTMar4Uw==}
|
||||
bits-ui@2.9.4:
|
||||
resolution: {integrity: sha512-Cqn685P6DDuEyBZT/CWMyS5+8JAnYbctvoEVPcmiut+HUpG3SozVgjoDaUib5VG4ZYUKEi1FPwHxiXo9c6J0PA==}
|
||||
engines: {node: '>=20'}
|
||||
peerDependencies:
|
||||
'@internationalized/date': ^3.8.1
|
||||
|
|
@ -1675,8 +1687,8 @@ packages:
|
|||
css.escape@1.5.1:
|
||||
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
||||
|
||||
cssdb@8.3.1:
|
||||
resolution: {integrity: sha512-XnDRQMXucLueX92yDe0LPKupXetWoFOgawr4O4X41l5TltgK2NVbJJVDnnOywDYfW1sTJ28AcXGKOqdRKwCcmQ==}
|
||||
cssdb@8.4.0:
|
||||
resolution: {integrity: sha512-lyATYGyvXwQ8h55WeQeEHXhI+47rl52pXSYkFK/ZrCbAJSgVIaPFjYc3RM8TpRHKk7W3wsAZImmLps+P5VyN9g==}
|
||||
|
||||
cssesc@3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
|
|
@ -2060,8 +2072,8 @@ packages:
|
|||
lower-case@2.0.2:
|
||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||
|
||||
lucide-svelte@0.539.0:
|
||||
resolution: {integrity: sha512-p4k3GOje/9Si1eIkg1W1OQUhozeja5Ka5shjVpfyP5X2ye+B7sfyMnX3d5D2et+MYJwUFGrMna5MIYgq6bLfqw==}
|
||||
lucide-svelte@0.541.0:
|
||||
resolution: {integrity: sha512-Jk+LiOYDl62R/0nWkG1s5XL2k6LHmPq3wUfiJ6qtBhb8jGefB4PU10x5HJrAihwaKqVc2vH5wjKMELGjHJenEQ==}
|
||||
peerDependencies:
|
||||
svelte: ^3 || ^4 || ^5.0.0-next.42
|
||||
|
||||
|
|
@ -2198,8 +2210,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4.6
|
||||
|
||||
postcss-color-functional-notation@7.0.10:
|
||||
resolution: {integrity: sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA==}
|
||||
postcss-color-functional-notation@7.0.11:
|
||||
resolution: {integrity: sha512-zfqoUSaHMko/k2PA9xnaydVTHqYv5vphq5Q2AHcG/dCdv/OkHYWcVWfVTBKZ526uzT8L7NghuvSw3C9PxlKnLg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -2240,8 +2252,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
postcss-double-position-gradients@6.0.2:
|
||||
resolution: {integrity: sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q==}
|
||||
postcss-double-position-gradients@6.0.3:
|
||||
resolution: {integrity: sha512-Dl0Z9sdbMwrPslgOaGBZRGo3TASmmgTcqcUODr82MTYyJk6devXZM6MlQjpQKMJqlLJ6oL1w78U7IXFdPA5+ug==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -2281,8 +2293,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
|
||||
postcss-lab-function@7.0.10:
|
||||
resolution: {integrity: sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ==}
|
||||
postcss-lab-function@7.0.11:
|
||||
resolution: {integrity: sha512-BEA4jId8uQe1gyjZZ6Bunb6ZsH2izks+v25AxQJDBtigXCjTLmCPWECwQpLTtcxH589MVxhs/9TAmRC6lUEmXQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -2340,8 +2352,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
postcss-preset-env@10.2.4:
|
||||
resolution: {integrity: sha512-q+lXgqmTMdB0Ty+EQ31SuodhdfZetUlwCA/F0zRcd/XdxjzI+Rl2JhZNz5US2n/7t9ePsvuhCnEN4Bmu86zXlA==}
|
||||
postcss-preset-env@10.3.0:
|
||||
resolution: {integrity: sha512-khE99iwEbWLzXBVFNsS0QdnfYXDpqH/pxoHFcaCaVlh+e29swc3UyiLSSJ89dTK8e+Si3wNKYDGs6jEMmbE8TQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
|
@ -2876,39 +2888,39 @@ snapshots:
|
|||
|
||||
'@babel/runtime@7.28.3': {}
|
||||
|
||||
'@biomejs/biome@2.2.0':
|
||||
'@biomejs/biome@2.2.2':
|
||||
optionalDependencies:
|
||||
'@biomejs/cli-darwin-arm64': 2.2.0
|
||||
'@biomejs/cli-darwin-x64': 2.2.0
|
||||
'@biomejs/cli-linux-arm64': 2.2.0
|
||||
'@biomejs/cli-linux-arm64-musl': 2.2.0
|
||||
'@biomejs/cli-linux-x64': 2.2.0
|
||||
'@biomejs/cli-linux-x64-musl': 2.2.0
|
||||
'@biomejs/cli-win32-arm64': 2.2.0
|
||||
'@biomejs/cli-win32-x64': 2.2.0
|
||||
'@biomejs/cli-darwin-arm64': 2.2.2
|
||||
'@biomejs/cli-darwin-x64': 2.2.2
|
||||
'@biomejs/cli-linux-arm64': 2.2.2
|
||||
'@biomejs/cli-linux-arm64-musl': 2.2.2
|
||||
'@biomejs/cli-linux-x64': 2.2.2
|
||||
'@biomejs/cli-linux-x64-musl': 2.2.2
|
||||
'@biomejs/cli-win32-arm64': 2.2.2
|
||||
'@biomejs/cli-win32-x64': 2.2.2
|
||||
|
||||
'@biomejs/cli-darwin-arm64@2.2.0':
|
||||
'@biomejs/cli-darwin-arm64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-darwin-x64@2.2.0':
|
||||
'@biomejs/cli-darwin-x64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-arm64-musl@2.2.0':
|
||||
'@biomejs/cli-linux-arm64-musl@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-arm64@2.2.0':
|
||||
'@biomejs/cli-linux-arm64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-x64-musl@2.2.0':
|
||||
'@biomejs/cli-linux-x64-musl@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-x64@2.2.0':
|
||||
'@biomejs/cli-linux-x64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-win32-arm64@2.2.0':
|
||||
'@biomejs/cli-win32-arm64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-win32-x64@2.2.0':
|
||||
'@biomejs/cli-win32-x64@2.2.2':
|
||||
optional: true
|
||||
|
||||
'@chromatic-com/storybook@4.1.1(storybook@9.1.3(@testing-library/dom@10.4.1)(vite@6.3.5(yaml@2.7.0)))':
|
||||
|
|
@ -2928,16 +2940,16 @@ snapshots:
|
|||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
|
||||
'@csstools/color-helpers@5.0.2': {}
|
||||
'@csstools/color-helpers@5.1.0': {}
|
||||
|
||||
'@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
|
||||
dependencies:
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
|
||||
'@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
|
||||
'@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
|
||||
dependencies:
|
||||
'@csstools/color-helpers': 5.0.2
|
||||
'@csstools/color-helpers': 5.1.0
|
||||
'@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
|
|
@ -2953,44 +2965,62 @@ snapshots:
|
|||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
|
||||
'@csstools/postcss-alpha-function@1.0.0(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0)
|
||||
postcss: 8.5.6
|
||||
postcss-selector-parser: 7.1.0
|
||||
|
||||
'@csstools/postcss-color-function@4.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-color-function-display-p3-linear@1.0.0(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-color-mix-function@3.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-color-function@4.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments@1.0.0(postcss@8.5.6)':
|
||||
'@csstools/postcss-color-mix-function@3.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-content-alt-text@2.0.6(postcss@8.5.6)':
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments@1.0.1(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-content-alt-text@2.0.7(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
|
|
@ -3007,34 +3037,34 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
'@csstools/postcss-gamut-mapping@2.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-gradients-interpolation-method@5.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-gradients-interpolation-method@5.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-hwb-function@4.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-hwb-function@4.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-ic-unit@4.0.2(postcss@8.5.6)':
|
||||
'@csstools/postcss-ic-unit@4.0.3(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
|
@ -3049,11 +3079,11 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-selector-parser: 7.1.0
|
||||
|
||||
'@csstools/postcss-light-dark-function@2.0.9(postcss@8.5.6)':
|
||||
'@csstools/postcss-light-dark-function@2.0.10(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
|
|
@ -3106,16 +3136,16 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
'@csstools/postcss-oklab-function@4.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-oklab-function@4.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-progressive-custom-properties@4.1.0(postcss@8.5.6)':
|
||||
'@csstools/postcss-progressive-custom-properties@4.2.0(postcss@8.5.6)':
|
||||
dependencies:
|
||||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
|
@ -3127,12 +3157,12 @@ snapshots:
|
|||
'@csstools/css-tokenizer': 3.0.4
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-relative-color-syntax@3.0.10(postcss@8.5.6)':
|
||||
'@csstools/postcss-relative-color-syntax@3.0.11(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
|
|
@ -3155,9 +3185,9 @@ snapshots:
|
|||
'@csstools/css-tokenizer': 3.0.4
|
||||
postcss: 8.5.6
|
||||
|
||||
'@csstools/postcss-text-decoration-shorthand@4.0.2(postcss@8.5.6)':
|
||||
'@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.6)':
|
||||
dependencies:
|
||||
'@csstools/color-helpers': 5.0.2
|
||||
'@csstools/color-helpers': 5.1.0
|
||||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
|
|
@ -3273,7 +3303,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@floating-ui/utils': 0.2.10
|
||||
|
||||
'@floating-ui/dom@1.7.3':
|
||||
'@floating-ui/dom@1.7.4':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.7.3
|
||||
'@floating-ui/utils': 0.2.10
|
||||
|
|
@ -3809,12 +3839,12 @@ snapshots:
|
|||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
'@sveltejs/adapter-node@5.3.1(@sveltejs/kit@2.36.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))':
|
||||
'@sveltejs/adapter-node@5.3.1(@sveltejs/kit@2.36.2(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))':
|
||||
dependencies:
|
||||
'@rollup/plugin-commonjs': 28.0.2(rollup@4.34.8)
|
||||
'@rollup/plugin-json': 6.1.0(rollup@4.34.8)
|
||||
'@rollup/plugin-node-resolve': 16.0.0(rollup@4.34.8)
|
||||
'@sveltejs/kit': 2.36.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
'@sveltejs/kit': 2.36.2(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))
|
||||
rollup: 4.34.8
|
||||
|
||||
'@sveltejs/enhanced-img@0.5.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(rollup@4.34.8)(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))':
|
||||
|
|
@ -3830,7 +3860,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- rollup
|
||||
|
||||
'@sveltejs/kit@2.36.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))':
|
||||
'@sveltejs/kit@2.36.2(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0)))(svelte@5.38.2)(vite@6.3.5(yaml@2.7.0))':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.0.0
|
||||
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
|
||||
|
|
@ -4049,10 +4079,10 @@ snapshots:
|
|||
dependencies:
|
||||
open: 8.4.2
|
||||
|
||||
bits-ui@2.9.2(@internationalized/date@3.8.2)(svelte@5.38.2):
|
||||
bits-ui@2.9.4(@internationalized/date@3.8.2)(svelte@5.38.2):
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.7.3
|
||||
'@floating-ui/dom': 1.7.3
|
||||
'@floating-ui/dom': 1.7.4
|
||||
'@internationalized/date': 3.8.2
|
||||
esm-env: 1.2.2
|
||||
runed: 0.29.2(svelte@5.38.2)
|
||||
|
|
@ -4216,7 +4246,7 @@ snapshots:
|
|||
|
||||
css.escape@1.5.1: {}
|
||||
|
||||
cssdb@8.3.1: {}
|
||||
cssdb@8.4.0: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
|
|
@ -4396,10 +4426,6 @@ snapshots:
|
|||
optionalDependencies:
|
||||
picomatch: 4.0.2
|
||||
|
||||
fdir@6.4.4(picomatch@4.0.3):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.3
|
||||
|
||||
fdir@6.4.6(picomatch@4.0.3):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.3
|
||||
|
|
@ -4564,7 +4590,7 @@ snapshots:
|
|||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
lucide-svelte@0.539.0(svelte@5.38.2):
|
||||
lucide-svelte@0.541.0(svelte@5.38.2):
|
||||
dependencies:
|
||||
svelte: 5.38.2
|
||||
|
||||
|
|
@ -4682,12 +4708,12 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
postcss-color-functional-notation@7.0.10(postcss@8.5.6):
|
||||
postcss-color-functional-notation@7.0.11(postcss@8.5.6):
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
|
|
@ -4733,9 +4759,9 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-selector-parser: 7.1.0
|
||||
|
||||
postcss-double-position-gradients@6.0.2(postcss@8.5.6):
|
||||
postcss-double-position-gradients@6.0.3(postcss@8.5.6):
|
||||
dependencies:
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
|
@ -4771,12 +4797,12 @@ snapshots:
|
|||
read-cache: 1.0.0
|
||||
resolve: 1.22.10
|
||||
|
||||
postcss-lab-function@7.0.10(postcss@8.5.6):
|
||||
postcss-lab-function@7.0.11(postcss@8.5.6):
|
||||
dependencies:
|
||||
'@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
|
||||
'@csstools/css-tokenizer': 3.0.4
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/utilities': 2.0.0(postcss@8.5.6)
|
||||
postcss: 8.5.6
|
||||
|
||||
|
|
@ -4817,22 +4843,24 @@ snapshots:
|
|||
postcss: 8.5.6
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
postcss-preset-env@10.2.4(postcss@8.5.6):
|
||||
postcss-preset-env@10.3.0(postcss@8.5.6):
|
||||
dependencies:
|
||||
'@csstools/postcss-alpha-function': 1.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.6)
|
||||
'@csstools/postcss-color-function': 4.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-color-mix-function': 3.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments': 1.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-content-alt-text': 2.0.6(postcss@8.5.6)
|
||||
'@csstools/postcss-color-function': 4.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-color-function-display-p3-linear': 1.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-color-mix-function': 3.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-color-mix-variadic-function-arguments': 1.0.1(postcss@8.5.6)
|
||||
'@csstools/postcss-content-alt-text': 2.0.7(postcss@8.5.6)
|
||||
'@csstools/postcss-exponential-functions': 2.0.9(postcss@8.5.6)
|
||||
'@csstools/postcss-font-format-keywords': 4.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-gamut-mapping': 2.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-gradients-interpolation-method': 5.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-hwb-function': 4.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-ic-unit': 4.0.2(postcss@8.5.6)
|
||||
'@csstools/postcss-gamut-mapping': 2.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-gradients-interpolation-method': 5.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-hwb-function': 4.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-ic-unit': 4.0.3(postcss@8.5.6)
|
||||
'@csstools/postcss-initial': 2.0.1(postcss@8.5.6)
|
||||
'@csstools/postcss-is-pseudo-class': 5.0.3(postcss@8.5.6)
|
||||
'@csstools/postcss-light-dark-function': 2.0.9(postcss@8.5.6)
|
||||
'@csstools/postcss-light-dark-function': 2.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-logical-float-and-clear': 3.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-logical-overflow': 2.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-logical-overscroll-behavior': 2.0.0(postcss@8.5.6)
|
||||
|
|
@ -4842,14 +4870,14 @@ snapshots:
|
|||
'@csstools/postcss-media-queries-aspect-ratio-number-values': 3.0.5(postcss@8.5.6)
|
||||
'@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-normalize-display-values': 4.0.0(postcss@8.5.6)
|
||||
'@csstools/postcss-oklab-function': 4.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.1.0(postcss@8.5.6)
|
||||
'@csstools/postcss-oklab-function': 4.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-progressive-custom-properties': 4.2.0(postcss@8.5.6)
|
||||
'@csstools/postcss-random-function': 2.0.1(postcss@8.5.6)
|
||||
'@csstools/postcss-relative-color-syntax': 3.0.10(postcss@8.5.6)
|
||||
'@csstools/postcss-relative-color-syntax': 3.0.11(postcss@8.5.6)
|
||||
'@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.6)
|
||||
'@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.6)
|
||||
'@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.6)
|
||||
'@csstools/postcss-text-decoration-shorthand': 4.0.2(postcss@8.5.6)
|
||||
'@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.6)
|
||||
'@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.6)
|
||||
'@csstools/postcss-unset-value': 4.0.0(postcss@8.5.6)
|
||||
autoprefixer: 10.4.21(postcss@8.5.6)
|
||||
|
|
@ -4857,24 +4885,24 @@ snapshots:
|
|||
css-blank-pseudo: 7.0.1(postcss@8.5.6)
|
||||
css-has-pseudo: 7.0.2(postcss@8.5.6)
|
||||
css-prefers-color-scheme: 10.0.0(postcss@8.5.6)
|
||||
cssdb: 8.3.1
|
||||
cssdb: 8.4.0
|
||||
postcss: 8.5.6
|
||||
postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.6)
|
||||
postcss-clamp: 4.1.0(postcss@8.5.6)
|
||||
postcss-color-functional-notation: 7.0.10(postcss@8.5.6)
|
||||
postcss-color-functional-notation: 7.0.11(postcss@8.5.6)
|
||||
postcss-color-hex-alpha: 10.0.0(postcss@8.5.6)
|
||||
postcss-color-rebeccapurple: 10.0.0(postcss@8.5.6)
|
||||
postcss-custom-media: 11.0.6(postcss@8.5.6)
|
||||
postcss-custom-properties: 14.0.6(postcss@8.5.6)
|
||||
postcss-custom-selectors: 8.0.5(postcss@8.5.6)
|
||||
postcss-dir-pseudo-class: 9.0.1(postcss@8.5.6)
|
||||
postcss-double-position-gradients: 6.0.2(postcss@8.5.6)
|
||||
postcss-double-position-gradients: 6.0.3(postcss@8.5.6)
|
||||
postcss-focus-visible: 10.0.1(postcss@8.5.6)
|
||||
postcss-focus-within: 9.0.1(postcss@8.5.6)
|
||||
postcss-font-variant: 5.0.0(postcss@8.5.6)
|
||||
postcss-gap-properties: 6.0.0(postcss@8.5.6)
|
||||
postcss-image-set-function: 7.0.0(postcss@8.5.6)
|
||||
postcss-lab-function: 7.0.10(postcss@8.5.6)
|
||||
postcss-lab-function: 7.0.11(postcss@8.5.6)
|
||||
postcss-logical: 8.1.0(postcss@8.5.6)
|
||||
postcss-nesting: 13.0.2(postcss@8.5.6)
|
||||
postcss-opacity-percentage: 3.0.0(postcss@8.5.6)
|
||||
|
|
@ -5198,11 +5226,11 @@ snapshots:
|
|||
svelte: 5.38.2
|
||||
zimmerframe: 1.1.2
|
||||
|
||||
svelte-check@4.3.1(picomatch@4.0.3)(svelte@5.38.2)(typescript@5.9.2):
|
||||
svelte-check@4.3.1(picomatch@4.0.2)(svelte@5.38.2)(typescript@5.9.2):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
chokidar: 4.0.3
|
||||
fdir: 6.4.4(picomatch@4.0.3)
|
||||
fdir: 6.4.4(picomatch@4.0.2)
|
||||
picocolors: 1.1.1
|
||||
sade: 1.8.1
|
||||
svelte: 5.38.2
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
/* Write your global styles here, in PostCSS syntax */
|
||||
|
|
@ -1,34 +1,28 @@
|
|||
<script lang="ts">
|
||||
import { ExternalLink } from "lucide-svelte";
|
||||
import type {
|
||||
ExternalLinkType,
|
||||
LinkIconType,
|
||||
} from "$lib/types/externalLinkTypes";
|
||||
import { ExternalLink } from 'lucide-svelte';
|
||||
import type { ExternalLinkType, LinkIconType } from '$lib/types/externalLinkTypes';
|
||||
|
||||
const { iconData, linkData, textData }: ExternalLinkType = $props();
|
||||
|
||||
let textLocationClass = "";
|
||||
if (textData?.location === "top") {
|
||||
textLocationClass = "text-top";
|
||||
} else if (textData?.location === "bottom") {
|
||||
textLocationClass = "text-bottom";
|
||||
} else if (textData?.location === "left") {
|
||||
textLocationClass = "text-left";
|
||||
} else if (textData?.location === "right") {
|
||||
textLocationClass = "text-right";
|
||||
let textLocationClass = '';
|
||||
if (textData?.location === 'top') {
|
||||
textLocationClass = 'text-top';
|
||||
} else if (textData?.location === 'bottom') {
|
||||
textLocationClass = 'text-bottom';
|
||||
} else if (textData?.location === 'left') {
|
||||
textLocationClass = 'text-left';
|
||||
} else if (textData?.location === 'right') {
|
||||
textLocationClass = 'text-right';
|
||||
} else {
|
||||
textLocationClass = "text-left";
|
||||
textLocationClass = 'text-left';
|
||||
}
|
||||
|
||||
const linkDecoration =
|
||||
linkData?.textDecoration && linkData?.textDecoration === "none"
|
||||
? `text-decoration-${linkData?.textDecoration}`
|
||||
: "text-decoration-underline";
|
||||
const linkClass =
|
||||
`${linkData?.clazz || ""} ${textLocationClass} ${linkDecoration}`.trim();
|
||||
linkData?.textDecoration && linkData?.textDecoration === 'none' ? `text-decoration-${linkData?.textDecoration}` : 'text-decoration-underline';
|
||||
const linkClass = `${linkData?.clazz || ''} ${textLocationClass} ${linkDecoration}`.trim();
|
||||
|
||||
// Default icon config to satisfy typings when no iconData is provided
|
||||
const defaultIconData: LinkIconType = { type: "icon", icon: ExternalLink };
|
||||
const defaultIconData: LinkIconType = { type: 'icon', icon: ExternalLink };
|
||||
</script>
|
||||
|
||||
{#snippet externalLink({ iconData, linkData, textData }: ExternalLinkType)}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { page } from "$app/state";
|
||||
import ContactHub from "$lib/components/ContactHub.svelte";
|
||||
import { page } from '$app/state';
|
||||
import ContactHub from '$lib/components/ContactHub.svelte';
|
||||
|
||||
const userNames = {
|
||||
github: "BradNut",
|
||||
linkedIn: "bradley-shellnut",
|
||||
email: "website[at]bradleyshellnut.com",
|
||||
github: 'BradNut',
|
||||
linkedIn: 'bradley-shellnut',
|
||||
email: 'website[at]bradleyshellnut.com',
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
231
tests/about.test.ts
Normal file
231
tests/about.test.ts
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
|
||||
test.describe('About page', () => {
|
||||
test('has expected main heading', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
await expect(page.getByRole('heading', { level: 1, name: 'About' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('header/footer links hover: color becomes shellYellow', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
|
||||
const shellYellow = await page.evaluate(() => {
|
||||
const probe = document.createElement('div');
|
||||
probe.style.color = 'var(--shellYellow)';
|
||||
document.body.appendChild(probe);
|
||||
const color = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
return color;
|
||||
});
|
||||
|
||||
const areas = [
|
||||
'header[aria-label="header navigation"]',
|
||||
'footer nav[aria-label="footer navigation"]',
|
||||
];
|
||||
|
||||
for (const area of areas) {
|
||||
const nav = page.locator(area);
|
||||
await expect(nav).toBeVisible();
|
||||
|
||||
const link = nav.getByRole('link', { name: 'Portfolio', exact: true });
|
||||
await expect(link).toBeVisible();
|
||||
|
||||
const before = await link.evaluate((el) => {
|
||||
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
|
||||
return { color: cs.color };
|
||||
});
|
||||
await link.hover();
|
||||
const after = await link.evaluate((el) => {
|
||||
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
|
||||
return { color: cs.color };
|
||||
});
|
||||
|
||||
expect(after.color).toBe(shellYellow);
|
||||
// Sanity: it should change from the default color
|
||||
expect(after.color).not.toBe(before.color);
|
||||
}
|
||||
});
|
||||
|
||||
test('current page (About) link is active in header and footer', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const areas = [
|
||||
'header[aria-label="header navigation"]',
|
||||
'footer nav[aria-label="footer navigation"]',
|
||||
];
|
||||
for (const area of areas) {
|
||||
const nav = page.locator(area);
|
||||
const aboutLink = nav.getByRole('link', { name: 'About', exact: true });
|
||||
await expect(aboutLink).toBeVisible();
|
||||
const isActive = await aboutLink.evaluate((el) => (el as Element).classList.contains('active'));
|
||||
expect(isActive).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
test('tech list hover changes color to shellYellow', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const techList = page.locator('.tech-list');
|
||||
await expect(techList).toBeVisible();
|
||||
|
||||
// Resolve the actual computed rgb color value for --shellYellow in the browser context
|
||||
const shellYellow = await page.evaluate(() => {
|
||||
const probe = document.createElement('div');
|
||||
probe.style.color = 'var(--shellYellow)';
|
||||
document.body.appendChild(probe);
|
||||
const color = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
return color;
|
||||
});
|
||||
|
||||
const names = ['Svelte', 'Hono', 'TypeScript', 'Drizzle ORM', 'React', 'Next.js', 'Docker'];
|
||||
for (const name of names) {
|
||||
const link = techList.locator(`a[title="${name}"]`).first();
|
||||
await expect(link).toBeVisible();
|
||||
|
||||
const before = await link.evaluate((el) => getComputedStyle(el as Element).color);
|
||||
await link.hover();
|
||||
const after = await link.evaluate((el) => getComputedStyle(el as Element).color);
|
||||
|
||||
expect(before).not.toBe(shellYellow);
|
||||
expect(after).toBe(shellYellow);
|
||||
}
|
||||
});
|
||||
|
||||
test('tech list has accessible links for key technologies', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const techList = page.locator('.tech-list');
|
||||
await expect(techList).toBeVisible();
|
||||
const names = ['Svelte', 'Hono', 'TypeScript', 'Drizzle ORM', 'React', 'Next.js', 'Docker'];
|
||||
for (const name of names) {
|
||||
const link = techList.locator(`a[title="${name}"]`).first();
|
||||
await expect(link).toBeVisible();
|
||||
await expect(link).toHaveAccessibleName(new RegExp(name, 'i'));
|
||||
}
|
||||
});
|
||||
|
||||
test('tablet viewport (~800px): extracurricular wraps to multiple rows', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 800, height: 1000 });
|
||||
await page.goto('/about');
|
||||
const container = page.locator('.extracurricular');
|
||||
await expect(container).toBeVisible();
|
||||
const cards = container.locator('.card');
|
||||
const count = await cards.count();
|
||||
expect(count).toBeGreaterThanOrEqual(3);
|
||||
const [c0, c1, c2] = await Promise.all([
|
||||
cards.nth(0).boundingBox(),
|
||||
cards.nth(1).boundingBox(),
|
||||
cards.nth(2).boundingBox(),
|
||||
]);
|
||||
expect(c0 && c1 && c2).toBeTruthy();
|
||||
if (c0 && c1 && c2) {
|
||||
// first two side-by-side on same row, third wrapped below
|
||||
expect(Math.abs(c0.y - c1.y)).toBeLessThan(10);
|
||||
expect(c2.y).toBeGreaterThan(c0.y + 10);
|
||||
}
|
||||
});
|
||||
|
||||
test('mobile viewport (375px): extracurricular cards stack vertically', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 900 });
|
||||
await page.goto('/about');
|
||||
const container = page.locator('.extracurricular');
|
||||
const cards = container.locator('.card');
|
||||
const count = await cards.count();
|
||||
expect(count).toBeGreaterThanOrEqual(2);
|
||||
const [a, b] = await Promise.all([
|
||||
cards.nth(0).boundingBox(),
|
||||
cards.nth(1).boundingBox(),
|
||||
]);
|
||||
expect(a && b).toBeTruthy();
|
||||
if (a && b) {
|
||||
expect(b.y).toBeGreaterThan(a.y + 10);
|
||||
expect(Math.abs(b.x - a.x)).toBeLessThan(40);
|
||||
}
|
||||
});
|
||||
|
||||
// Mirror header link presence from home tests
|
||||
test('header navigation shows expected links', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const headerNav = page.locator('header[aria-label="header navigation"]');
|
||||
await expect(headerNav).toBeVisible();
|
||||
await expect(headerNav.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
|
||||
await expect(headerNav.getByRole('link', { name: 'About', exact: true })).toBeVisible();
|
||||
await expect(headerNav.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
|
||||
await expect(headerNav.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
// Mirror header navigation flow from home tests (starting on /about)
|
||||
test('header navigation links go to correct routes (from /about)', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const headerNav = page.locator('header[aria-label="header navigation"]');
|
||||
|
||||
await headerNav.getByRole('link', { name: 'Portfolio', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/portfolio\/?$/);
|
||||
|
||||
await headerNav.getByRole('link', { name: 'Uses', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/uses\/?$/);
|
||||
|
||||
await headerNav.getByRole('link', { name: 'Home', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/?$/);
|
||||
|
||||
await headerNav.getByRole('link', { name: 'About', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/about\/?$/);
|
||||
});
|
||||
|
||||
// Mirror footer link presence from home tests
|
||||
test('footer shows expected links', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const footerNav = page.getByRole('navigation', { name: 'footer navigation' });
|
||||
await expect(footerNav).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'About', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Privacy', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Favorite Articles', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
// Mirror footer navigation flow from home tests (starting on /about)
|
||||
test('footer navigation links go to correct routes (from /about)', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
const footerNav = page.getByRole('navigation', { name: 'footer navigation' });
|
||||
|
||||
await footerNav.getByRole('link', { name: 'Privacy', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/privacy\/?$/);
|
||||
|
||||
// Favorite Articles may route to /articles or /articles/1
|
||||
await footerNav.getByRole('link', { name: 'Favorite Articles', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/articles(\/\d+)?\/?$/);
|
||||
|
||||
await footerNav.getByRole('link', { name: 'About', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/about\/?$/);
|
||||
|
||||
await footerNav.getByRole('link', { name: 'Home', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/?$/);
|
||||
});
|
||||
|
||||
// Mobile viewport: ensure cat section has no horizontal overflow and second image fits viewport
|
||||
test('mobile: cat section no horizontal overflow; second cat image fully visible', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 800 });
|
||||
await page.goto('/about');
|
||||
|
||||
const catSection = page.locator('.cat-pics');
|
||||
await catSection.scrollIntoViewIfNeeded();
|
||||
|
||||
// The cat section itself should not horizontally overflow its own box
|
||||
const sectionOverflowX = await catSection.evaluate((el) => el.scrollWidth - el.clientWidth);
|
||||
expect(sectionOverflowX).toBeLessThanOrEqual(2);
|
||||
|
||||
// Second image inside .cat-pics is fully within the cat section horizontally
|
||||
const img = page.locator('.cat-pics figure:nth-of-type(2) img');
|
||||
await expect(img).toBeVisible();
|
||||
|
||||
const [imgBox, sectionBox] = await Promise.all([
|
||||
img.boundingBox(),
|
||||
catSection.boundingBox(),
|
||||
]);
|
||||
expect(imgBox && sectionBox).toBeTruthy();
|
||||
if (imgBox && sectionBox) {
|
||||
expect(imgBox.x).toBeGreaterThanOrEqual(sectionBox.x - 1);
|
||||
expect(imgBox.x + imgBox.width).toBeLessThanOrEqual(sectionBox.x + sectionBox.width + 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,225 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
|
||||
test('index page has expected h1', async ({ page }) => {
|
||||
test.describe('Home page', () => {
|
||||
test('has expected main heading', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
expect(await page.textContent('h1')).toBe("Hello! I'm Bradley Shellnut.");
|
||||
await expect(page.locator('h1')).toHaveText("Hello! I'm Bradley Shellnut.");
|
||||
});
|
||||
|
||||
test('header/footer links hover: color becomes shellYellow', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const shellYellow = await page.evaluate(() => {
|
||||
const probe = document.createElement('div');
|
||||
probe.style.color = 'var(--shellYellow)';
|
||||
document.body.appendChild(probe);
|
||||
const color = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
return color;
|
||||
});
|
||||
|
||||
const areas = [
|
||||
'header[aria-label="header navigation"]',
|
||||
'footer nav[aria-label="footer navigation"]',
|
||||
];
|
||||
|
||||
for (const area of areas) {
|
||||
const nav = page.locator(area);
|
||||
await expect(nav).toBeVisible();
|
||||
|
||||
const link = nav.getByRole('link', { name: 'Portfolio', exact: true });
|
||||
await expect(link).toBeVisible();
|
||||
|
||||
const before = await link.evaluate((el) => {
|
||||
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
|
||||
return { color: cs.color };
|
||||
});
|
||||
await link.hover();
|
||||
const after = await link.evaluate((el) => {
|
||||
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
|
||||
return { color: cs.color };
|
||||
});
|
||||
|
||||
expect(after.color).toBe(shellYellow);
|
||||
expect(after.color).not.toBe(before.color);
|
||||
}
|
||||
});
|
||||
|
||||
test('current page (Home) link is active in header and footer', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const areas = [
|
||||
'header[aria-label="header navigation"]',
|
||||
'footer nav[aria-label="footer navigation"]',
|
||||
];
|
||||
for (const area of areas) {
|
||||
const nav = page.locator(area);
|
||||
const link = nav.getByRole('link', { name: 'Home', exact: true });
|
||||
await expect(link).toBeVisible();
|
||||
const isActive = await link.evaluate((el) => (el as Element).classList.contains('active'));
|
||||
expect(isActive).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
test('header navigation links go to correct routes', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const headerNav = page.locator('header[aria-label="header navigation"]');
|
||||
|
||||
// About
|
||||
await headerNav.getByRole('link', { name: 'About', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/about\/?$/);
|
||||
|
||||
// Portfolio
|
||||
await headerNav.getByRole('link', { name: 'Portfolio', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/portfolio\/?$/);
|
||||
|
||||
// Uses
|
||||
await headerNav.getByRole('link', { name: 'Uses', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/uses\/?$/);
|
||||
|
||||
// Home
|
||||
await headerNav.getByRole('link', { name: 'Home', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/?$/);
|
||||
});
|
||||
|
||||
test('header navigation shows expected links', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const headerNavContainer = page.locator('header[aria-label="header navigation"]');
|
||||
await expect(headerNavContainer).toBeVisible();
|
||||
await expect(headerNavContainer.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
|
||||
await expect(headerNavContainer.getByRole('link', { name: 'About', exact: true })).toBeVisible();
|
||||
await expect(headerNavContainer.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
|
||||
await expect(headerNavContainer.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows key sections', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByRole('heading', { level: 2, name: 'Currently listening to:' })).toBeVisible();
|
||||
await expect(page.getByRole('heading', { level: 2, name: 'Favorite Articles' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('renders Bandcamp albums (max 6)', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const albumImages = page.locator('.albumsStyles .album-artwork');
|
||||
const count = await albumImages.count();
|
||||
expect(count).toBeGreaterThan(0);
|
||||
expect(count).toBeLessThanOrEqual(6);
|
||||
});
|
||||
|
||||
test('renders at least one favorite article card', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const cards = page.locator('section.articles article.card');
|
||||
await expect(cards.first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('"more articles" link points to /articles and navigates', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const more = page.locator('a.moreArticles');
|
||||
await expect(more).toHaveAttribute('href', '/articles');
|
||||
await expect(more).toContainText('more articles');
|
||||
await more.click();
|
||||
await expect(page).toHaveURL(/\/articles(\/\d+)?\/?$/);
|
||||
});
|
||||
|
||||
test('has social/contact links', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByRole('link', { name: 'Contact through LinkedIn', exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: 'Contact through Github', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('footer shows expected links', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const footerNav = page.getByRole('navigation', { name: 'footer navigation' });
|
||||
await expect(footerNav).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'About', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Privacy', exact: true })).toBeVisible();
|
||||
await expect(footerNav.getByRole('link', { name: 'Favorite Articles', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('small viewport: Bandcamp grid 2x3 above Articles', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 800, height: 1000 }); // <1000px and >575px
|
||||
await page.goto('/');
|
||||
|
||||
const albumsGrid = page.locator('.albumsStyles');
|
||||
const articlesSection = page.locator('section.articles');
|
||||
|
||||
await expect(albumsGrid).toBeVisible();
|
||||
await expect(articlesSection).toBeVisible();
|
||||
|
||||
// Order: Bandcamp above Articles
|
||||
const [albumsTop, articlesTop] = await Promise.all([
|
||||
albumsGrid.boundingBox().then((b) => b?.y ?? Number.POSITIVE_INFINITY),
|
||||
articlesSection.boundingBox().then((b) => b?.y ?? Number.NEGATIVE_INFINITY),
|
||||
]);
|
||||
expect(albumsTop).toBeLessThan(articlesTop);
|
||||
|
||||
// Layout: assert first two items share the same row, third wraps to next row
|
||||
const albumItems = page.locator('.albumsStyles .album-artwork');
|
||||
const n = await albumItems.count();
|
||||
expect(n).toBeGreaterThanOrEqual(3);
|
||||
const [b0, b1, b2] = await Promise.all([
|
||||
albumItems.nth(0).boundingBox(),
|
||||
albumItems.nth(1).boundingBox(),
|
||||
albumItems.nth(2).boundingBox(),
|
||||
]);
|
||||
expect(b0 && b1 && b2).toBeTruthy();
|
||||
if (b0 && b1 && b2) {
|
||||
expect(Math.abs(b0.y - b1.y)).toBeLessThan(6); // same row
|
||||
expect(b2.y).toBeGreaterThan(b0.y + 10); // next row
|
||||
}
|
||||
});
|
||||
|
||||
test('mobile viewport: Bandcamp vertical scroll, Articles stacked', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 800 }); // <=575px rules apply
|
||||
await page.goto('/');
|
||||
|
||||
const albumsGrid = page.locator('.albumsStyles');
|
||||
const articlesSection = page.locator('section.articles');
|
||||
|
||||
await expect(albumsGrid).toBeVisible();
|
||||
await expect(articlesSection).toBeVisible();
|
||||
|
||||
// Order: Bandcamp above Articles
|
||||
const [albumsTop, articlesTop] = await Promise.all([
|
||||
albumsGrid.boundingBox().then((b) => b?.y ?? Number.POSITIVE_INFINITY),
|
||||
articlesSection.boundingBox().then((b) => b?.y ?? Number.NEGATIVE_INFINITY),
|
||||
]);
|
||||
expect(albumsTop).toBeLessThan(articlesTop);
|
||||
|
||||
// Layout: single column and scrollable vertically
|
||||
const scrollInfo = await albumsGrid.evaluate((el) => ({
|
||||
overflowY: getComputedStyle(el as HTMLElement).overflowY,
|
||||
scrollHeight: (el as HTMLElement).scrollHeight,
|
||||
clientHeight: (el as HTMLElement).clientHeight,
|
||||
}));
|
||||
expect(scrollInfo.clientHeight).toBeLessThan(scrollInfo.scrollHeight);
|
||||
expect(['auto', 'scroll']).toContain(scrollInfo.overflowY);
|
||||
|
||||
// Albums are a vertical list (y increasing); first two must be on different rows
|
||||
const albumItems = page.locator('.albumsStyles .album-artwork');
|
||||
const m = await albumItems.count();
|
||||
expect(m).toBeGreaterThanOrEqual(2);
|
||||
const [a0, a1] = await Promise.all([
|
||||
albumItems.nth(0).boundingBox(),
|
||||
albumItems.nth(1).boundingBox(),
|
||||
]);
|
||||
expect(a0 && a1).toBeTruthy();
|
||||
if (a0 && a1) {
|
||||
expect(a1.y).toBeGreaterThan(a0.y + 10);
|
||||
expect(Math.abs(a1.x - a0.x)).toBeLessThan(6);
|
||||
}
|
||||
|
||||
// Articles are a vertical list (same x, increasing y)
|
||||
const boxes = await page.locator('section.articles article.card').evaluateAll((els) =>
|
||||
(els as HTMLElement[]).slice(0, Math.min(4, els.length)).map((el) => el.getBoundingClientRect())
|
||||
);
|
||||
expect(boxes.length).toBeGreaterThan(0);
|
||||
const x0 = boxes[0].left;
|
||||
for (let i = 1; i < boxes.length; i++) {
|
||||
expect(Math.abs(boxes[i].left - x0)).toBeLessThan(6);
|
||||
expect(boxes[i].top).toBeGreaterThan(boxes[i - 1].top);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue