chore: prepare production deployment
This commit is contained in:
+12
-1
@@ -1,13 +1,24 @@
|
||||
# Production identity
|
||||
PUBLIC_SITE_URL=https://trade.flamy.studio
|
||||
PUBLIC_SITE_NAME=Flamy Trade
|
||||
PUBLIC_SITE_DESCRIPTION=Публичная витрина ML-прогнозов для крипторынка.
|
||||
PUBLIC_DASHBOARD_DATA_MODE=research-static
|
||||
|
||||
# SvelteKit adapter-node runtime
|
||||
HOST=0.0.0.0
|
||||
PORT=3000
|
||||
ORIGIN=https://trade.flamy.studio
|
||||
BODY_SIZE_LIMIT=1M
|
||||
SHUTDOWN_TIMEOUT=15
|
||||
APP_STOP_GRACE_PERIOD=20s
|
||||
|
||||
# Docker image provenance
|
||||
APP_IMAGE_REPOSITORY=registry.example.com/flamy-trade
|
||||
APP_IMAGE_TAG=local
|
||||
BUILD_DATE=
|
||||
VCS_REF=
|
||||
|
||||
# Reverse proxy publishing
|
||||
APP_HOST_IP=10.20.0.20
|
||||
APP_PUBLISHED_PORT=18082
|
||||
APP_IMAGE_TAG=local
|
||||
NGINX_IMAGE=nginxinc/nginx-unprivileged:1.30.4-alpine-perl@sha256:36fa38fb8f34faba45e7e1857644d6561f2faf45e7ce6b15e97d1a2a1682a0cd
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
node_modules
|
||||
.npm-cache
|
||||
.corepack
|
||||
.pnpm-store
|
||||
|
||||
# Output
|
||||
.output
|
||||
@@ -27,3 +28,4 @@ vite.config.ts.timestamp-*
|
||||
#IDE & AI
|
||||
.claude
|
||||
.idea
|
||||
.vscode
|
||||
@@ -1,6 +1,6 @@
|
||||
# Flamy Trade
|
||||
|
||||
Публичный frontend для `trade.flamy.studio`: лендинг, блог и демонстрационный дашборд ML-прогнозов по крипторынку.
|
||||
Публичный frontend для `trade.flamy.studio`: лендинг, блог и исследовательский дашборд ML-прогнозов по крипторынку.
|
||||
|
||||
Проект построен на SvelteKit, Svelte 5 Runes, Tailwind CSS v4, TypeScript и `lightweight-charts`.
|
||||
|
||||
@@ -38,94 +38,75 @@ pnpm preview # preview production build
|
||||
pnpm audit # аудит зависимостей
|
||||
```
|
||||
|
||||
`pnpm outdated` может показывать `@types/node` 26.x и TypeScript 7.x. Это не ошибка текущего стека: проект закреплён на Node 24 LTS, а `@sveltejs/kit` и `typescript-eslint` на текущих версиях требуют TypeScript `<6.1`.
|
||||
`prepare` намеренно выполняет `svelte-kit sync` без подавления ошибок. Если синхронизация SvelteKit падает, установка зависимостей тоже должна завершаться ошибкой.
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Основные изменяемые значения вынесены в `.env.example`.
|
||||
`.env.example` описывает production-настройки. Для сервера скопируйте его в `.env` и заполните значения без локальных заглушек.
|
||||
|
||||
Публичные значения сайта:
|
||||
Основные переменные:
|
||||
|
||||
```bash
|
||||
PUBLIC_SITE_URL=https://trade.flamy.studio
|
||||
PUBLIC_SITE_NAME=Flamy Trade
|
||||
PUBLIC_SITE_DESCRIPTION=Публичная витрина ML-прогнозов для крипторынка.
|
||||
```
|
||||
PUBLIC_DASHBOARD_DATA_MODE=research-static
|
||||
|
||||
Runtime-переменные SvelteKit adapter-node:
|
||||
|
||||
```bash
|
||||
HOST=0.0.0.0
|
||||
PORT=3000
|
||||
ORIGIN=https://trade.flamy.studio
|
||||
BODY_SIZE_LIMIT=1M
|
||||
SHUTDOWN_TIMEOUT=15
|
||||
```
|
||||
APP_STOP_GRACE_PERIOD=20s
|
||||
|
||||
Docker Compose:
|
||||
APP_IMAGE_REPOSITORY=registry.example.com/flamy-trade
|
||||
APP_IMAGE_TAG=<git-sha>
|
||||
BUILD_DATE=<utc-iso-date>
|
||||
VCS_REF=<git-sha>
|
||||
|
||||
```bash
|
||||
APP_HOST_IP=10.20.0.20
|
||||
APP_PUBLISHED_PORT=18082
|
||||
APP_IMAGE_TAG=<git-sha>
|
||||
NGINX_IMAGE=nginxinc/nginx-unprivileged:1.30.4-alpine-perl@sha256:36fa38fb8f34faba45e7e1857644d6561f2faf45e7ce6b15e97d1a2a1682a0cd
|
||||
```
|
||||
|
||||
`PUBLIC_DASHBOARD_DATA_MODE=research-static` означает, что дашборд показывает исследовательские синтетические данные. Это production-поведение текущего публичного этапа, а не интеграция с реальным торговым API.
|
||||
|
||||
## Структура
|
||||
|
||||
```text
|
||||
src/lib/blog/posts.ts # статические статьи блога
|
||||
src/lib/config/site.ts # единая конфигурация сайта и canonical URL
|
||||
src/lib/stores/chartStore.ts # типы графика и демонстрационный provider
|
||||
src/lib/components/Chart.svelte # lightweight-charts компонент
|
||||
src/lib/blog/posts.ts # типизированные статьи блога
|
||||
src/lib/config/site.ts # единая конфигурация сайта, canonical и metadata
|
||||
src/lib/data/dashboard.ts # provider данных дашборда
|
||||
src/lib/stores/chartStore.ts # типы графика и research-static генератор
|
||||
src/lib/components/Chart.svelte # компонент lightweight-charts
|
||||
src/routes/healthz/+server.ts # health endpoint
|
||||
src/routes/sitemap.xml/+server.ts # sitemap
|
||||
docker/nginx/default.conf # project nginx
|
||||
src/routes/robots.txt/+server.ts # runtime robots.txt
|
||||
src/routes/sitemap.xml/+server.ts # runtime sitemap
|
||||
docker/nginx/default.conf # nginx server config
|
||||
docker/nginx/includes # общие nginx include-файлы
|
||||
docs/deployment.md # runbook развёртывания
|
||||
```
|
||||
|
||||
## Данные дашборда
|
||||
|
||||
Текущий provider в `chartStore.ts` генерирует демонстрационные данные. Он не является реальным торговым API и не меняет контракт будущего backend.
|
||||
|
||||
Ожидаемая форма `ChartData`:
|
||||
|
||||
```typescript
|
||||
type ChartData = {
|
||||
candles: Array<{ time: number; open: number; high: number; low: number; close: number }>;
|
||||
prediction: Array<{ time: number; value: number }>;
|
||||
signal: {
|
||||
direction: 'long' | 'short';
|
||||
confidence: number;
|
||||
entry: number;
|
||||
tp: number;
|
||||
sl: number;
|
||||
};
|
||||
currentPrice: number;
|
||||
change24h: number;
|
||||
change24hPct: number;
|
||||
};
|
||||
```
|
||||
|
||||
## Блог
|
||||
|
||||
Статьи хранятся как типизированные блоки, а не как HTML-строки. Это позволяет рендерить контент без `{@html}` и без отдельной санитаризации.
|
||||
|
||||
## Production
|
||||
|
||||
Production-сборка рассчитана на схему:
|
||||
Production-схема:
|
||||
|
||||
```text
|
||||
Internet -> Caddy -> 10.20.0.20:18082 -> nginx -> app:3000
|
||||
```
|
||||
|
||||
Публикуется только nginx. Node-приложение доступно только во внутренней Docker-сети. Nginx запускается через unprivileged image с `cap_drop: ALL`, `read_only` и `no-new-privileges`.
|
||||
|
||||
Подробный порядок развёртывания, Caddy block, smoke-check и rollback описаны в [docs/deployment.md](docs/deployment.md).
|
||||
|
||||
## Зависимости
|
||||
|
||||
Renovate закрепляет версии и digest Docker-образов, а также ждёт 3 дня перед обновлением свежих релизов. TypeScript 6.x является осознанным compatibility hold до обновления peer constraints в SvelteKit/typescript-eslint.
|
||||
|
||||
## Что не входит в текущий этап
|
||||
|
||||
Пока не подключаются:
|
||||
|
||||
- ML-runtime;
|
||||
- реальный API;
|
||||
- реальный торговый API;
|
||||
- S3;
|
||||
- база данных;
|
||||
- Redis;
|
||||
|
||||
+7
-2
@@ -1,3 +1,5 @@
|
||||
name: flamy_trade
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
@@ -6,10 +8,12 @@ services:
|
||||
args:
|
||||
BUILD_DATE: ${BUILD_DATE:-}
|
||||
VCS_REF: ${VCS_REF:-}
|
||||
image: flamy-trade:${APP_IMAGE_TAG:-local}
|
||||
image: ${APP_IMAGE_REPOSITORY:-flamy-trade}:${APP_IMAGE_TAG:-local}
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
read_only: true
|
||||
stop_signal: SIGTERM
|
||||
stop_grace_period: ${APP_STOP_GRACE_PERIOD:-20s}
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
HOST: 0.0.0.0
|
||||
@@ -52,7 +56,7 @@ services:
|
||||
max-file: '3'
|
||||
|
||||
nginx:
|
||||
image: nginx:1.30.4-alpine@sha256:97d490c12ba55b4946b01546d1c3ed324e8d41ab1c9fcb2a616aa470620e5b46
|
||||
image: ${NGINX_IMAGE:-nginxinc/nginx-unprivileged:1.30.4-alpine-perl@sha256:36fa38fb8f34faba45e7e1857644d6561f2faf45e7ce6b15e97d1a2a1682a0cd}
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
read_only: true
|
||||
@@ -68,6 +72,7 @@ services:
|
||||
app_protocol: http
|
||||
volumes:
|
||||
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./docker/nginx/includes:/etc/nginx/includes:ro
|
||||
networks:
|
||||
- backend
|
||||
cpus: 0.10
|
||||
|
||||
+13
-22
@@ -8,44 +8,35 @@ server {
|
||||
server_name _;
|
||||
|
||||
client_max_body_size 1m;
|
||||
add_header_inherit merge;
|
||||
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
|
||||
|
||||
location /_app/immutable/ {
|
||||
location = /healthz {
|
||||
access_log off;
|
||||
proxy_pass http://app:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $forwarded_proto;
|
||||
include /etc/nginx/includes/proxy-headers.conf;
|
||||
add_header Cache-Control "no-cache" always;
|
||||
}
|
||||
|
||||
location ^~ /_app/immutable/ {
|
||||
proxy_pass http://app:3000;
|
||||
include /etc/nginx/includes/proxy-headers.conf;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
}
|
||||
|
||||
location ~* \.(?:css|js|mjs|svg|png|jpg|jpeg|gif|webp|ico|ttf|woff2?)$ {
|
||||
proxy_pass http://app:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $forwarded_proto;
|
||||
include /etc/nginx/includes/proxy-headers.conf;
|
||||
add_header Cache-Control "public, max-age=86400" always;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://app:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $forwarded_proto;
|
||||
proxy_set_header Connection "";
|
||||
add_header Cache-Control "no-store" always;
|
||||
include /etc/nginx/includes/proxy-headers.conf;
|
||||
add_header Cache-Control "no-cache" always;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $forwarded_proto;
|
||||
proxy_set_header Connection "";
|
||||
+82
-21
@@ -1,6 +1,6 @@
|
||||
# Развёртывание Flamy Trade
|
||||
|
||||
Документ описывает production-развёртывание сайта `trade.flamy.studio` без ML-runtime и без будущего API. Эти части подключаются отдельно.
|
||||
Документ описывает production-развёртывание сайта `trade.flamy.studio` без ML-runtime и будущего API. Эти части подключаются отдельным этапом.
|
||||
|
||||
## Схема
|
||||
|
||||
@@ -9,11 +9,11 @@ Internet
|
||||
-> Router :80/:443
|
||||
-> edge-proxy VM / Caddy
|
||||
-> 10.20.0.20:18082
|
||||
-> flamy_trade_nginx
|
||||
-> flamy_trade_app:3000
|
||||
-> flamy_trade-nginx-1
|
||||
-> flamy_trade-app-1:3000
|
||||
```
|
||||
|
||||
На VM публикуется только nginx. Node-приложение доступно только во внутренней Docker-сети.
|
||||
Compose project name зафиксирован как `flamy_trade`. `container_name` не задаётся, чтобы не ломать стандартное управление Compose.
|
||||
|
||||
## Переменные
|
||||
|
||||
@@ -23,16 +23,23 @@ Internet
|
||||
PUBLIC_SITE_URL=https://trade.flamy.studio
|
||||
PUBLIC_SITE_NAME=Flamy Trade
|
||||
PUBLIC_SITE_DESCRIPTION=Публичная витрина ML-прогнозов для крипторынка.
|
||||
PUBLIC_DASHBOARD_DATA_MODE=research-static
|
||||
|
||||
HOST=0.0.0.0
|
||||
PORT=3000
|
||||
ORIGIN=https://trade.flamy.studio
|
||||
BODY_SIZE_LIMIT=1M
|
||||
SHUTDOWN_TIMEOUT=15
|
||||
APP_STOP_GRACE_PERIOD=20s
|
||||
|
||||
APP_IMAGE_REPOSITORY=registry.example.com/flamy-trade
|
||||
APP_IMAGE_TAG=<git-sha>
|
||||
BUILD_DATE=<utc-iso-date>
|
||||
VCS_REF=<git-sha>
|
||||
|
||||
APP_HOST_IP=10.20.0.20
|
||||
APP_PUBLISHED_PORT=18082
|
||||
APP_IMAGE_TAG=<git-sha>
|
||||
NGINX_IMAGE=nginxinc/nginx-unprivileged:1.30.4-alpine-perl@sha256:36fa38fb8f34faba45e7e1857644d6561f2faf45e7ce6b15e97d1a2a1682a0cd
|
||||
```
|
||||
|
||||
Перед фиксацией порта проверьте, что `18082` свободен:
|
||||
@@ -42,7 +49,7 @@ sudo ss -lntup | grep ':18082'
|
||||
docker ps --format 'table {{.Names}}\t{{.Ports}}'
|
||||
```
|
||||
|
||||
## Сборка
|
||||
## Проверки перед сборкой
|
||||
|
||||
```bash
|
||||
pnpm install --frozen-lockfile
|
||||
@@ -51,14 +58,22 @@ pnpm lint
|
||||
pnpm check
|
||||
pnpm build
|
||||
pnpm audit
|
||||
docker compose config
|
||||
```
|
||||
|
||||
`pnpm outdated` должен проверяться вручную. На текущем стеке допустимы только осознанные удержания: `@types/node` на ветке 24 под Node 24 LTS и TypeScript 6.x до обновления peer constraints в SvelteKit/typescript-eslint.
|
||||
## Сборка
|
||||
|
||||
Docker:
|
||||
Перед сборкой image задайте provenance:
|
||||
|
||||
```bash
|
||||
export BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
export VCS_REF="$(git rev-parse HEAD)"
|
||||
export APP_IMAGE_TAG="$VCS_REF"
|
||||
```
|
||||
|
||||
Сборка и запуск:
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
docker compose build --pull
|
||||
docker compose up -d --wait
|
||||
docker compose ps
|
||||
@@ -76,6 +91,8 @@ trade.flamy.studio {
|
||||
reverse_proxy 10.20.0.20:18082 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -90,19 +107,22 @@ sudo systemctl reload caddy
|
||||
|
||||
## Smoke-check
|
||||
|
||||
С docker-runtime:
|
||||
С Docker-runtime:
|
||||
|
||||
```bash
|
||||
curl -fsS http://10.20.0.20:18082/healthz
|
||||
curl -I http://10.20.0.20:18082/
|
||||
curl -fsSI http://10.20.0.20:18082/
|
||||
curl -fsSI http://10.20.0.20:18082/robots.txt
|
||||
curl -fsSI http://10.20.0.20:18082/sitemap.xml
|
||||
```
|
||||
|
||||
Снаружи:
|
||||
|
||||
```bash
|
||||
curl -I http://trade.flamy.studio
|
||||
curl -I https://trade.flamy.studio
|
||||
curl -fsSI https://trade.flamy.studio/
|
||||
curl -fsS https://trade.flamy.studio/healthz
|
||||
curl -fsS https://trade.flamy.studio/robots.txt
|
||||
curl -fsS https://trade.flamy.studio/sitemap.xml
|
||||
```
|
||||
|
||||
Маршруты:
|
||||
@@ -120,15 +140,56 @@ curl -fsS https://trade.flamy.studio/healthz
|
||||
/nesuschestvuyuschiy-url 404
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
1. Каждый image получает тег git SHA через `APP_IMAGE_TAG`.
|
||||
2. Предыдущий image не удаляется до успешного smoke-check.
|
||||
3. Для отката поменяйте `APP_IMAGE_TAG` на предыдущий SHA.
|
||||
4. Выполните:
|
||||
Проверка headers:
|
||||
|
||||
```bash
|
||||
docker compose up -d --no-build
|
||||
curl -fsSI https://trade.flamy.studio/
|
||||
curl -fsSI https://trade.flamy.studio/favicon.svg
|
||||
curl -fsSI https://trade.flamy.studio/_app/immutable/<real-file>.js
|
||||
```
|
||||
|
||||
Если проблема в маршрутизации, восстановите backup Caddyfile и выполните `sudo systemctl reload caddy`.
|
||||
Ожидаемо:
|
||||
|
||||
```text
|
||||
X-Content-Type-Options: nosniff
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
X-Frame-Options: SAMEORIGIN
|
||||
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
|
||||
```
|
||||
|
||||
`Content-Security-Policy` задаётся SvelteKit и ожидается на HTML-ответах приложения.
|
||||
|
||||
Для `/_app/immutable/*` ожидается:
|
||||
|
||||
```text
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
```
|
||||
|
||||
Для HTML:
|
||||
|
||||
```text
|
||||
Cache-Control: no-cache
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
Надёжный rollback должен опираться на immutable image tag:
|
||||
|
||||
```text
|
||||
${APP_IMAGE_REPOSITORY}:<git-sha>
|
||||
```
|
||||
|
||||
На production-сервере меняется только `APP_IMAGE_TAG`, затем выполняется:
|
||||
|
||||
```bash
|
||||
docker compose pull app
|
||||
docker compose up -d --no-build --wait
|
||||
```
|
||||
|
||||
Если проблема в маршрутизации, восстановите backup Caddyfile и выполните:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload caddy
|
||||
```
|
||||
|
||||
Предыдущий image не удаляется до успешного smoke-check нового релиза.
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"prepare": "svelte-kit sync",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"format:check": "prettier --check .",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@types/node": "24.12.4",
|
||||
"eslint": "10.7.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-svelte": "3.21.0",
|
||||
"eslint-plugin-svelte": "3.20.0",
|
||||
"globals": "17.7.0",
|
||||
"prettier": "3.9.5",
|
||||
"prettier-plugin-svelte": "4.1.1",
|
||||
@@ -41,7 +41,7 @@
|
||||
"vite": "8.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/kit": "2.70.1",
|
||||
"@sveltejs/kit": "2.69.3",
|
||||
"clsx": "2.1.1",
|
||||
"gsap": "3.15.0",
|
||||
"lightweight-charts": "5.2.0",
|
||||
|
||||
Generated
+214
-243
@@ -12,8 +12,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@sveltejs/kit':
|
||||
specifier: 2.70.1
|
||||
version: 2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
specifier: 2.69.3
|
||||
version: 2.69.3(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
clsx:
|
||||
specifier: 2.1.1
|
||||
version: 2.1.1
|
||||
@@ -35,7 +35,7 @@ importers:
|
||||
version: 10.0.1(eslint@10.7.0(jiti@2.7.0))
|
||||
'@sveltejs/adapter-node':
|
||||
specifier: 5.5.7
|
||||
version: 5.5.7(@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))
|
||||
version: 5.5.7(@sveltejs/kit@2.69.3(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: 7.2.0
|
||||
version: 7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
@@ -52,8 +52,8 @@ importers:
|
||||
specifier: 10.1.8
|
||||
version: 10.1.8(eslint@10.7.0(jiti@2.7.0))
|
||||
eslint-plugin-svelte:
|
||||
specifier: 3.21.0
|
||||
version: 3.21.0(eslint@10.7.0(jiti@2.7.0))(svelte@5.56.6(@typescript-eslint/types@8.64.0))
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(eslint@10.7.0(jiti@2.7.0))(svelte@5.56.6(@typescript-eslint/types@8.64.0))
|
||||
globals:
|
||||
specifier: 17.7.0
|
||||
version: 17.7.0
|
||||
@@ -71,7 +71,7 @@ importers:
|
||||
version: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
svelte-check:
|
||||
specifier: 4.7.3
|
||||
version: 4.7.3(picomatch@4.0.4)(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)
|
||||
version: 4.7.3(picomatch@4.0.5)(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)
|
||||
tailwindcss:
|
||||
specifier: 4.3.3
|
||||
version: 4.3.3
|
||||
@@ -290,8 +290,8 @@ packages:
|
||||
'@rolldown/pluginutils@1.0.1':
|
||||
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
|
||||
|
||||
'@rollup/plugin-commonjs@29.0.2':
|
||||
resolution: {integrity: sha512-S/ggWH1LU7jTyi9DxZOKyxpVd4hF/OZ0JrEbeLjXk/DFXwRny0tjD2c992zOUYQobLrVkRVMDdmHP16HKP7GRg==}
|
||||
'@rollup/plugin-commonjs@29.0.3':
|
||||
resolution: {integrity: sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==}
|
||||
engines: {node: '>=16.0.0 || 14 >= 14.17'}
|
||||
peerDependencies:
|
||||
rollup: ^2.68.0||^3.0.0||^4.0.0
|
||||
@@ -326,8 +326,8 @@ packages:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/pluginutils@5.3.0':
|
||||
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
|
||||
'@rollup/pluginutils@5.4.0':
|
||||
resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
@@ -335,149 +335,149 @@ packages:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.60.4':
|
||||
resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==}
|
||||
'@rollup/rollup-android-arm-eabi@4.62.2':
|
||||
resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.60.4':
|
||||
resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==}
|
||||
'@rollup/rollup-android-arm64@4.62.2':
|
||||
resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.60.4':
|
||||
resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==}
|
||||
'@rollup/rollup-darwin-arm64@4.62.2':
|
||||
resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.60.4':
|
||||
resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==}
|
||||
'@rollup/rollup-darwin-x64@4.62.2':
|
||||
resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.60.4':
|
||||
resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==}
|
||||
'@rollup/rollup-freebsd-arm64@4.62.2':
|
||||
resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.60.4':
|
||||
resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==}
|
||||
'@rollup/rollup-freebsd-x64@4.62.2':
|
||||
resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.4':
|
||||
resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==}
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.62.2':
|
||||
resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.60.4':
|
||||
resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==}
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.62.2':
|
||||
resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==}
|
||||
'@rollup/rollup-linux-arm64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==}
|
||||
'@rollup/rollup-linux-arm64-musl@4.62.2':
|
||||
resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==}
|
||||
'@rollup/rollup-linux-loong64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==}
|
||||
'@rollup/rollup-linux-loong64-musl@4.62.2':
|
||||
resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==}
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==}
|
||||
'@rollup/rollup-linux-ppc64-musl@4.62.2':
|
||||
resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==}
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==}
|
||||
'@rollup/rollup-linux-riscv64-musl@4.62.2':
|
||||
resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==}
|
||||
'@rollup/rollup-linux-s390x-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==}
|
||||
'@rollup/rollup-linux-x64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==}
|
||||
'@rollup/rollup-linux-x64-musl@4.62.2':
|
||||
resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.60.4':
|
||||
resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==}
|
||||
'@rollup/rollup-openbsd-x64@4.62.2':
|
||||
resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.60.4':
|
||||
resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==}
|
||||
'@rollup/rollup-openharmony-arm64@4.62.2':
|
||||
resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.60.4':
|
||||
resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==}
|
||||
'@rollup/rollup-win32-arm64-msvc@4.62.2':
|
||||
resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.60.4':
|
||||
resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==}
|
||||
'@rollup/rollup-win32-ia32-msvc@4.62.2':
|
||||
resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==}
|
||||
'@rollup/rollup-win32-x64-gnu@4.62.2':
|
||||
resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.60.4':
|
||||
resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==}
|
||||
'@rollup/rollup-win32-x64-msvc@4.62.2':
|
||||
resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@standard-schema/spec@1.1.0':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@sveltejs/acorn-typescript@1.0.10':
|
||||
resolution: {integrity: sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==}
|
||||
'@sveltejs/acorn-typescript@1.0.11':
|
||||
resolution: {integrity: sha512-LFuZUkjJ9iF7JZye/aG5XM0SFcQ5VyL0oVX4WJ9dc0Va3R3s0OauX1BESVCb+YN/ol8TAfqGDDAQsTG627Y5kw==}
|
||||
peerDependencies:
|
||||
acorn: ^8.9.0
|
||||
|
||||
@@ -486,8 +486,8 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^2.4.0
|
||||
|
||||
'@sveltejs/kit@2.70.1':
|
||||
resolution: {integrity: sha512-nY9SPHGOZro3doud9vZXDBwl9tCZIouuJztjgSHs6PAIrv9M/z5O7eOhPV5xU7CgVHA976Jwu3BA1hIFvXztkA==}
|
||||
'@sveltejs/kit@2.69.3':
|
||||
resolution: {integrity: sha512-cphwqMRcE19/9VkrIPr5qZhQ0SptSSDfDzRUpYHu9OJDFGuYBFyJzK+KQA27wB4YG32O/yF2QjBkDmTyo0vtCw==}
|
||||
engines: {node: '>=18.13'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -616,9 +616,6 @@ packages:
|
||||
'@types/esrecurse@4.3.1':
|
||||
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/estree@1.0.9':
|
||||
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
|
||||
|
||||
@@ -698,8 +695,8 @@ packages:
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
|
||||
acorn@8.16.0:
|
||||
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
|
||||
acorn@8.17.0:
|
||||
resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -718,8 +715,8 @@ packages:
|
||||
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
||||
engines: {node: 18 || 20 || >=22}
|
||||
|
||||
brace-expansion@5.0.6:
|
||||
resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
|
||||
brace-expansion@5.0.7:
|
||||
resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==}
|
||||
engines: {node: 18 || 20 || >=22}
|
||||
|
||||
chokidar@4.0.3:
|
||||
@@ -787,8 +784,8 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
|
||||
eslint-plugin-svelte@3.21.0:
|
||||
resolution: {integrity: sha512-2dkuAk77FzQn5Ad5bJvcS6gU9iRCjywzQv6wVBR7RNseZzDsxfaIu+yzah/hTBB2znDd8Hl4oOISdhQuNyjTdQ==}
|
||||
eslint-plugin-svelte@3.20.0:
|
||||
resolution: {integrity: sha512-AElKLVt7Hjy4d7ljwhrhw9hux60DCxCNkmK8cY/aAXvjs8tpR7PvU4DlyI/SA1PaJww1gh0wPGo2pbyURuEwxQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.1 || ^9.0.0 || ^10.0.0
|
||||
@@ -927,16 +924,16 @@ packages:
|
||||
gsap@3.15.0:
|
||||
resolution: {integrity: sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==}
|
||||
|
||||
hasown@2.0.3:
|
||||
resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==}
|
||||
hasown@2.0.4:
|
||||
resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ignore@5.3.2:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
ignore@7.0.5:
|
||||
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
||||
ignore@7.0.6:
|
||||
resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
imurmurhash@0.1.4:
|
||||
@@ -1100,16 +1097,17 @@ packages:
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
nanoid@3.3.12:
|
||||
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
|
||||
nanoid@3.3.16:
|
||||
resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
obug@2.1.1:
|
||||
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
|
||||
obug@2.1.4:
|
||||
resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
|
||||
optionator@0.9.4:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
@@ -1137,10 +1135,6 @@ packages:
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
picomatch@4.0.4:
|
||||
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
picomatch@4.0.5:
|
||||
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1169,14 +1163,10 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.4.29
|
||||
|
||||
postcss-selector-parser@7.1.1:
|
||||
resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==}
|
||||
postcss-selector-parser@7.1.4:
|
||||
resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postcss@8.5.15:
|
||||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
postcss@8.5.19:
|
||||
resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -1270,8 +1260,8 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
rollup@4.60.4:
|
||||
resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==}
|
||||
rollup@4.62.2:
|
||||
resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -1279,13 +1269,13 @@ packages:
|
||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
semver@7.8.0:
|
||||
resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==}
|
||||
semver@7.8.5:
|
||||
resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
set-cookie-parser@3.1.0:
|
||||
resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==}
|
||||
set-cookie-parser@3.1.2:
|
||||
resolution: {integrity: sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
@@ -1338,10 +1328,6 @@ packages:
|
||||
resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
tinyglobby@0.2.16:
|
||||
resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinyglobby@0.2.17:
|
||||
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -1610,153 +1596,153 @@ snapshots:
|
||||
|
||||
'@rolldown/pluginutils@1.0.1': {}
|
||||
|
||||
'@rollup/plugin-commonjs@29.0.2(rollup@4.60.4)':
|
||||
'@rollup/plugin-commonjs@29.0.3(rollup@4.62.2)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.4)
|
||||
'@rollup/pluginutils': 5.4.0(rollup@4.62.2)
|
||||
commondir: 1.0.1
|
||||
estree-walker: 2.0.2
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
fdir: 6.5.0(picomatch@4.0.5)
|
||||
is-reference: 1.2.1
|
||||
magic-string: 0.30.21
|
||||
picomatch: 4.0.4
|
||||
picomatch: 4.0.5
|
||||
optionalDependencies:
|
||||
rollup: 4.60.4
|
||||
rollup: 4.62.2
|
||||
|
||||
'@rollup/plugin-json@6.1.0(rollup@4.60.4)':
|
||||
'@rollup/plugin-json@6.1.0(rollup@4.62.2)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.4)
|
||||
'@rollup/pluginutils': 5.4.0(rollup@4.62.2)
|
||||
optionalDependencies:
|
||||
rollup: 4.60.4
|
||||
rollup: 4.62.2
|
||||
|
||||
'@rollup/plugin-node-resolve@16.0.3(rollup@4.60.4)':
|
||||
'@rollup/plugin-node-resolve@16.0.3(rollup@4.62.2)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.4)
|
||||
'@rollup/pluginutils': 5.4.0(rollup@4.62.2)
|
||||
'@types/resolve': 1.20.2
|
||||
deepmerge: 4.3.1
|
||||
is-module: 1.0.0
|
||||
resolve: 1.22.12
|
||||
optionalDependencies:
|
||||
rollup: 4.60.4
|
||||
rollup: 4.62.2
|
||||
|
||||
'@rollup/plugin-replace@6.0.3(rollup@4.60.4)':
|
||||
'@rollup/plugin-replace@6.0.3(rollup@4.62.2)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.4)
|
||||
'@rollup/pluginutils': 5.4.0(rollup@4.62.2)
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
rollup: 4.60.4
|
||||
rollup: 4.62.2
|
||||
|
||||
'@rollup/pluginutils@5.3.0(rollup@4.60.4)':
|
||||
'@rollup/pluginutils@5.4.0(rollup@4.62.2)':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.9
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 4.0.4
|
||||
picomatch: 4.0.5
|
||||
optionalDependencies:
|
||||
rollup: 4.60.4
|
||||
rollup: 4.62.2
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.60.4':
|
||||
'@rollup/rollup-android-arm-eabi@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.60.4':
|
||||
'@rollup/rollup-android-arm64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.60.4':
|
||||
'@rollup/rollup-darwin-arm64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.60.4':
|
||||
'@rollup/rollup-darwin-x64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.60.4':
|
||||
'@rollup/rollup-freebsd-arm64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.60.4':
|
||||
'@rollup/rollup-freebsd-x64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.4':
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.60.4':
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-arm64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.60.4':
|
||||
'@rollup/rollup-linux-arm64-musl@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-loong64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.60.4':
|
||||
'@rollup/rollup-linux-loong64-musl@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.60.4':
|
||||
'@rollup/rollup-linux-ppc64-musl@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.60.4':
|
||||
'@rollup/rollup-linux-riscv64-musl@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-s390x-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.60.4':
|
||||
'@rollup/rollup-linux-x64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.60.4':
|
||||
'@rollup/rollup-linux-x64-musl@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.60.4':
|
||||
'@rollup/rollup-openbsd-x64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.60.4':
|
||||
'@rollup/rollup-openharmony-arm64@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.60.4':
|
||||
'@rollup/rollup-win32-arm64-msvc@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.60.4':
|
||||
'@rollup/rollup-win32-ia32-msvc@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.60.4':
|
||||
'@rollup/rollup-win32-x64-gnu@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.60.4':
|
||||
'@rollup/rollup-win32-x64-msvc@4.62.2':
|
||||
optional: true
|
||||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@sveltejs/acorn-typescript@1.0.10(acorn@8.16.0)':
|
||||
'@sveltejs/acorn-typescript@1.0.11(acorn@8.17.0)':
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
acorn: 8.17.0
|
||||
|
||||
'@sveltejs/adapter-node@5.5.7(@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))':
|
||||
'@sveltejs/adapter-node@5.5.7(@sveltejs/kit@2.69.3(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))':
|
||||
dependencies:
|
||||
'@rollup/plugin-commonjs': 29.0.2(rollup@4.60.4)
|
||||
'@rollup/plugin-json': 6.1.0(rollup@4.60.4)
|
||||
'@rollup/plugin-node-resolve': 16.0.3(rollup@4.60.4)
|
||||
'@rollup/plugin-replace': 6.0.3(rollup@4.60.4)
|
||||
'@sveltejs/kit': 2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
rollup: 4.60.4
|
||||
'@rollup/plugin-commonjs': 29.0.3(rollup@4.62.2)
|
||||
'@rollup/plugin-json': 6.1.0(rollup@4.62.2)
|
||||
'@rollup/plugin-node-resolve': 16.0.3(rollup@4.62.2)
|
||||
'@rollup/plugin-replace': 6.0.3(rollup@4.62.2)
|
||||
'@sveltejs/kit': 2.69.3(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
rollup: 4.62.2
|
||||
|
||||
'@sveltejs/kit@2.70.1(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))':
|
||||
'@sveltejs/kit@2.69.3(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0)))(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3)(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.1.0
|
||||
'@sveltejs/acorn-typescript': 1.0.10(acorn@8.16.0)
|
||||
'@sveltejs/acorn-typescript': 1.0.11(acorn@8.17.0)
|
||||
'@sveltejs/vite-plugin-svelte': 7.2.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
'@types/cookie': 0.6.0
|
||||
acorn: 8.16.0
|
||||
acorn: 8.17.0
|
||||
cookie: 0.7.2
|
||||
devalue: 5.8.1
|
||||
esm-env: 1.2.2
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.21
|
||||
mrmime: 2.0.1
|
||||
set-cookie-parser: 3.1.0
|
||||
set-cookie-parser: 3.1.2
|
||||
sirv: 3.0.2
|
||||
svelte: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
vite: 8.1.5(@types/node@24.12.4)(jiti@2.7.0)
|
||||
@@ -1769,7 +1755,7 @@ snapshots:
|
||||
dependencies:
|
||||
deepmerge: 4.3.1
|
||||
magic-string: 0.30.21
|
||||
obug: 2.1.1
|
||||
obug: 2.1.4
|
||||
svelte: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
vite: 8.1.5(@types/node@24.12.4)(jiti@2.7.0)
|
||||
vitefu: 1.1.3(vite@8.1.5(@types/node@24.12.4)(jiti@2.7.0))
|
||||
@@ -1851,8 +1837,6 @@ snapshots:
|
||||
|
||||
'@types/esrecurse@4.3.1': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/estree@1.0.9': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
@@ -1874,7 +1858,7 @@ snapshots:
|
||||
'@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.64.0
|
||||
eslint: 10.7.0(jiti@2.7.0)
|
||||
ignore: 7.0.5
|
||||
ignore: 7.0.6
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
@@ -1933,8 +1917,8 @@ snapshots:
|
||||
'@typescript-eslint/visitor-keys': 8.64.0
|
||||
debug: 4.4.3
|
||||
minimatch: 10.2.5
|
||||
semver: 7.8.0
|
||||
tinyglobby: 0.2.16
|
||||
semver: 7.8.5
|
||||
tinyglobby: 0.2.17
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -1956,11 +1940,11 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.64.0
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.16.0):
|
||||
acorn-jsx@5.3.2(acorn@8.17.0):
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
acorn: 8.17.0
|
||||
|
||||
acorn@8.16.0: {}
|
||||
acorn@8.17.0: {}
|
||||
|
||||
ajv@6.15.0:
|
||||
dependencies:
|
||||
@@ -1975,7 +1959,7 @@ snapshots:
|
||||
|
||||
balanced-match@4.0.4: {}
|
||||
|
||||
brace-expansion@5.0.6:
|
||||
brace-expansion@5.0.7:
|
||||
dependencies:
|
||||
balanced-match: 4.0.4
|
||||
|
||||
@@ -2022,7 +2006,7 @@ snapshots:
|
||||
dependencies:
|
||||
eslint: 10.7.0(jiti@2.7.0)
|
||||
|
||||
eslint-plugin-svelte@3.21.0(eslint@10.7.0(jiti@2.7.0))(svelte@5.56.6(@typescript-eslint/types@8.64.0)):
|
||||
eslint-plugin-svelte@3.20.0(eslint@10.7.0(jiti@2.7.0))(svelte@5.56.6(@typescript-eslint/types@8.64.0)):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.7.0(jiti@2.7.0))
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
@@ -2030,10 +2014,10 @@ snapshots:
|
||||
esutils: 2.0.3
|
||||
globals: 16.5.0
|
||||
known-css-properties: 0.37.0
|
||||
postcss: 8.5.15
|
||||
postcss-load-config: 3.1.4(postcss@8.5.15)
|
||||
postcss-safe-parser: 7.0.1(postcss@8.5.15)
|
||||
semver: 7.8.0
|
||||
postcss: 8.5.19
|
||||
postcss-load-config: 3.1.4(postcss@8.5.19)
|
||||
postcss-safe-parser: 7.0.1(postcss@8.5.19)
|
||||
semver: 7.8.5
|
||||
svelte-eslint-parser: 1.8.0(svelte@5.56.6(@typescript-eslint/types@8.64.0))
|
||||
optionalDependencies:
|
||||
svelte: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
@@ -2099,14 +2083,14 @@ snapshots:
|
||||
|
||||
espree@10.4.0:
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
acorn-jsx: 5.3.2(acorn@8.16.0)
|
||||
acorn: 8.17.0
|
||||
acorn-jsx: 5.3.2(acorn@8.17.0)
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
espree@11.2.0:
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
acorn-jsx: 5.3.2(acorn@8.16.0)
|
||||
acorn: 8.17.0
|
||||
acorn-jsx: 5.3.2(acorn@8.17.0)
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
esquery@1.7.0:
|
||||
@@ -2137,9 +2121,9 @@ snapshots:
|
||||
|
||||
fast-levenshtein@2.0.6: {}
|
||||
|
||||
fdir@6.5.0(picomatch@4.0.4):
|
||||
fdir@6.5.0(picomatch@4.0.5):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.4
|
||||
picomatch: 4.0.5
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
dependencies:
|
||||
@@ -2174,19 +2158,19 @@ snapshots:
|
||||
|
||||
gsap@3.15.0: {}
|
||||
|
||||
hasown@2.0.3:
|
||||
hasown@2.0.4:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
ignore@7.0.5: {}
|
||||
ignore@7.0.6: {}
|
||||
|
||||
imurmurhash@0.1.4: {}
|
||||
|
||||
is-core-module@2.16.2:
|
||||
dependencies:
|
||||
hasown: 2.0.3
|
||||
hasown: 2.0.4
|
||||
|
||||
is-extglob@2.1.1: {}
|
||||
|
||||
@@ -2294,7 +2278,7 @@ snapshots:
|
||||
|
||||
minimatch@10.2.5:
|
||||
dependencies:
|
||||
brace-expansion: 5.0.6
|
||||
brace-expansion: 5.0.7
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
@@ -2302,11 +2286,11 @@ snapshots:
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
nanoid@3.3.12: {}
|
||||
nanoid@3.3.16: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
obug@2.1.1: {}
|
||||
obug@2.1.4: {}
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
@@ -2333,39 +2317,31 @@ snapshots:
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@4.0.4: {}
|
||||
|
||||
picomatch@4.0.5: {}
|
||||
|
||||
postcss-load-config@3.1.4(postcss@8.5.15):
|
||||
postcss-load-config@3.1.4(postcss@8.5.19):
|
||||
dependencies:
|
||||
lilconfig: 2.1.0
|
||||
yaml: 1.10.3
|
||||
optionalDependencies:
|
||||
postcss: 8.5.15
|
||||
postcss: 8.5.19
|
||||
|
||||
postcss-safe-parser@7.0.1(postcss@8.5.15):
|
||||
postcss-safe-parser@7.0.1(postcss@8.5.19):
|
||||
dependencies:
|
||||
postcss: 8.5.15
|
||||
postcss: 8.5.19
|
||||
|
||||
postcss-scss@4.0.9(postcss@8.5.15):
|
||||
postcss-scss@4.0.9(postcss@8.5.19):
|
||||
dependencies:
|
||||
postcss: 8.5.15
|
||||
postcss: 8.5.19
|
||||
|
||||
postcss-selector-parser@7.1.1:
|
||||
postcss-selector-parser@7.1.4:
|
||||
dependencies:
|
||||
cssesc: 3.0.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
postcss@8.5.15:
|
||||
dependencies:
|
||||
nanoid: 3.3.12
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postcss@8.5.19:
|
||||
dependencies:
|
||||
nanoid: 3.3.12
|
||||
nanoid: 3.3.16
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
@@ -2416,44 +2392,44 @@ snapshots:
|
||||
'@rolldown/binding-win32-arm64-msvc': 1.1.5
|
||||
'@rolldown/binding-win32-x64-msvc': 1.1.5
|
||||
|
||||
rollup@4.60.4:
|
||||
rollup@4.62.2:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/estree': 1.0.9
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.60.4
|
||||
'@rollup/rollup-android-arm64': 4.60.4
|
||||
'@rollup/rollup-darwin-arm64': 4.60.4
|
||||
'@rollup/rollup-darwin-x64': 4.60.4
|
||||
'@rollup/rollup-freebsd-arm64': 4.60.4
|
||||
'@rollup/rollup-freebsd-x64': 4.60.4
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.60.4
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.60.4
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-arm64-musl': 4.60.4
|
||||
'@rollup/rollup-linux-loong64-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-loong64-musl': 4.60.4
|
||||
'@rollup/rollup-linux-ppc64-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-ppc64-musl': 4.60.4
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.60.4
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-x64-gnu': 4.60.4
|
||||
'@rollup/rollup-linux-x64-musl': 4.60.4
|
||||
'@rollup/rollup-openbsd-x64': 4.60.4
|
||||
'@rollup/rollup-openharmony-arm64': 4.60.4
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.60.4
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.60.4
|
||||
'@rollup/rollup-win32-x64-gnu': 4.60.4
|
||||
'@rollup/rollup-win32-x64-msvc': 4.60.4
|
||||
'@rollup/rollup-android-arm-eabi': 4.62.2
|
||||
'@rollup/rollup-android-arm64': 4.62.2
|
||||
'@rollup/rollup-darwin-arm64': 4.62.2
|
||||
'@rollup/rollup-darwin-x64': 4.62.2
|
||||
'@rollup/rollup-freebsd-arm64': 4.62.2
|
||||
'@rollup/rollup-freebsd-x64': 4.62.2
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.62.2
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.62.2
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-arm64-musl': 4.62.2
|
||||
'@rollup/rollup-linux-loong64-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-loong64-musl': 4.62.2
|
||||
'@rollup/rollup-linux-ppc64-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-ppc64-musl': 4.62.2
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.62.2
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-x64-gnu': 4.62.2
|
||||
'@rollup/rollup-linux-x64-musl': 4.62.2
|
||||
'@rollup/rollup-openbsd-x64': 4.62.2
|
||||
'@rollup/rollup-openharmony-arm64': 4.62.2
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.62.2
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.62.2
|
||||
'@rollup/rollup-win32-x64-gnu': 4.62.2
|
||||
'@rollup/rollup-win32-x64-msvc': 4.62.2
|
||||
fsevents: 2.3.3
|
||||
|
||||
sade@1.8.1:
|
||||
dependencies:
|
||||
mri: 1.2.0
|
||||
|
||||
semver@7.8.0: {}
|
||||
semver@7.8.5: {}
|
||||
|
||||
set-cookie-parser@3.1.0: {}
|
||||
set-cookie-parser@3.1.2: {}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
@@ -2471,12 +2447,12 @@ snapshots:
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
svelte-check@4.7.3(picomatch@4.0.4)(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3):
|
||||
svelte-check@4.7.3(picomatch@4.0.5)(svelte@5.56.6(@typescript-eslint/types@8.64.0))(typescript@6.0.3):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
'@sveltejs/load-config': 0.2.0
|
||||
chokidar: 4.0.3
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
fdir: 6.5.0(picomatch@4.0.5)
|
||||
picocolors: 1.1.1
|
||||
sade: 1.8.1
|
||||
svelte: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
@@ -2489,10 +2465,10 @@ snapshots:
|
||||
eslint-scope: 8.4.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
espree: 10.4.0
|
||||
postcss: 8.5.15
|
||||
postcss-scss: 4.0.9(postcss@8.5.15)
|
||||
postcss-selector-parser: 7.1.1
|
||||
semver: 7.8.0
|
||||
postcss: 8.5.19
|
||||
postcss-scss: 4.0.9(postcss@8.5.19)
|
||||
postcss-selector-parser: 7.1.4
|
||||
semver: 7.8.5
|
||||
optionalDependencies:
|
||||
svelte: 5.56.6(@typescript-eslint/types@8.64.0)
|
||||
|
||||
@@ -2500,10 +2476,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
'@sveltejs/acorn-typescript': 1.0.10(acorn@8.16.0)
|
||||
'@sveltejs/acorn-typescript': 1.0.11(acorn@8.17.0)
|
||||
'@types/estree': 1.0.9
|
||||
'@types/trusted-types': 2.0.7
|
||||
acorn: 8.16.0
|
||||
acorn: 8.17.0
|
||||
aria-query: 5.3.1
|
||||
axobject-query: 4.1.0
|
||||
clsx: 2.1.1
|
||||
@@ -2523,15 +2499,10 @@ snapshots:
|
||||
|
||||
tapable@2.3.3: {}
|
||||
|
||||
tinyglobby@0.2.16:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
picomatch: 4.0.4
|
||||
|
||||
tinyglobby@0.2.17:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
picomatch: 4.0.4
|
||||
fdir: 6.5.0(picomatch@4.0.5)
|
||||
picomatch: 4.0.5
|
||||
|
||||
totalist@3.0.1: {}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
packages:
|
||||
- .
|
||||
|
||||
minimumReleaseAgeExclude:
|
||||
- '@sveltejs/kit@2.70.1'
|
||||
- eslint-plugin-svelte@3.21.0
|
||||
|
||||
overrides:
|
||||
cookie: 0.7.2
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"extends": ["config:recommended"],
|
||||
"dependencyDashboard": true,
|
||||
"labels": ["dependencies"],
|
||||
"minimumReleaseAge": "3 days",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchManagers": ["npm"],
|
||||
|
||||
@@ -39,7 +39,7 @@ export const posts: Post[] = [
|
||||
{ type: 'heading', text: 'Stop Loss: где ваша позиция неправа' },
|
||||
{
|
||||
type: 'paragraph',
|
||||
text: 'Stop Loss — уровень, при достижении которого позиция закрывается автоматически. Это не признание ошибки, а часть стратегии. На графиках Flamy AI уровень SL рассчитывается моделью на основе исторической волатильности инструмента.'
|
||||
text: 'Stop Loss — уровень, при достижении которого позиция закрывается автоматически. Это не признание ошибки, а часть стратегии. На графиках Flamy Trade уровень SL рассчитывается моделью на основе исторической волатильности инструмента.'
|
||||
},
|
||||
{ type: 'heading', text: 'Take Profit: когда забирать прибыль' },
|
||||
{
|
||||
@@ -70,13 +70,13 @@ export const posts: Post[] = [
|
||||
id: 2,
|
||||
slug: 'kak-chitat-grafiki-flamy-ai',
|
||||
date: '2026-05-17',
|
||||
title: 'Как читать графики Flamy AI',
|
||||
description: 'Краткое объяснение свечей, прогнозной зоны, TP и SL на графиках Flamy AI.',
|
||||
title: 'Как читать графики Flamy Trade',
|
||||
description: 'Краткое объяснение свечей, прогнозной зоны, TP и SL на графиках Flamy Trade.',
|
||||
tags: ['ML', 'FORECAST', 'CHARTS'],
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
text: 'Графики Flamy AI содержат три слоя: исторические свечи, прогнозную зону и уровни торгового плана. Разберём каждый из них.'
|
||||
text: 'Графики Flamy Trade содержат три слоя: исторические свечи, прогнозную зону и уровни торгового плана. Разберём каждый из них.'
|
||||
},
|
||||
{ type: 'heading', text: 'Исторические свечи' },
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
CrosshairMode,
|
||||
LineStyle,
|
||||
type IChartApi,
|
||||
type IPriceLine,
|
||||
type ISeriesApi,
|
||||
type MouseEventParams,
|
||||
type UTCTimestamp
|
||||
@@ -25,8 +26,7 @@
|
||||
let chart: IChartApi | undefined;
|
||||
let candleSeries: ISeriesApi<'Candlestick'> | undefined;
|
||||
let predSeries: ISeriesApi<'Line'> | undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let priceLines: any[] = [];
|
||||
let priceLines: IPriceLine[] = [];
|
||||
|
||||
type Tooltip = {
|
||||
visible: boolean;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { tick } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { gsap } from 'gsap';
|
||||
import { cn } from '$lib/utils';
|
||||
@@ -13,6 +15,9 @@
|
||||
|
||||
let mobileOpen = $state(false);
|
||||
let header = $state<HTMLElement>(null!);
|
||||
let menuButton = $state<HTMLButtonElement>(null!);
|
||||
|
||||
const mobileMenuId = 'mobile-navigation';
|
||||
|
||||
onMount(() => {
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
@@ -24,8 +29,33 @@
|
||||
clearProps: 'transform,opacity'
|
||||
});
|
||||
});
|
||||
|
||||
function isActive(href: string) {
|
||||
const pathname = page.url.pathname;
|
||||
return href === '/' ? pathname === href : pathname === href || pathname.startsWith(`${href}/`);
|
||||
}
|
||||
|
||||
async function toggleMobileMenu() {
|
||||
mobileOpen = !mobileOpen;
|
||||
if (mobileOpen) {
|
||||
await tick();
|
||||
header.querySelector<HTMLAnchorElement>(`#${mobileMenuId} a`)?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function closeMobileMenu({ restoreFocus = false } = {}) {
|
||||
mobileOpen = false;
|
||||
if (restoreFocus) menuButton?.focus();
|
||||
}
|
||||
|
||||
function handleWindowKeydown(event: KeyboardEvent) {
|
||||
if (event.key !== 'Escape' || !mobileOpen) return;
|
||||
closeMobileMenu({ restoreFocus: true });
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={handleWindowKeydown} />
|
||||
|
||||
<header bind:this={header} class="fixed right-0 left-0 z-9999 border-b border-b-bg-h bg-bg-e">
|
||||
<div class="mx-auto flex max-w-400 items-center justify-between px-5 py-5 sm:px-10 lg:px-5">
|
||||
<Logo />
|
||||
@@ -37,6 +67,7 @@
|
||||
<a
|
||||
href={link.href}
|
||||
class={cn('transition-colors duration-300', link.isButton ? 'nav-btn' : 'nav-link')}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
>
|
||||
{link.text}
|
||||
</a>
|
||||
@@ -46,10 +77,13 @@
|
||||
</nav>
|
||||
|
||||
<button
|
||||
bind:this={menuButton}
|
||||
type="button"
|
||||
class="flex flex-col justify-center gap-1.5 p-1 lg:hidden"
|
||||
onclick={() => (mobileOpen = !mobileOpen)}
|
||||
onclick={toggleMobileMenu}
|
||||
aria-label={mobileOpen ? 'Закрыть меню' : 'Открыть меню'}
|
||||
aria-expanded={mobileOpen}
|
||||
aria-controls={mobileMenuId}
|
||||
>
|
||||
<span
|
||||
class={cn(
|
||||
@@ -74,7 +108,7 @@
|
||||
|
||||
<!-- Мобильное выпадающее меню -->
|
||||
{#if mobileOpen}
|
||||
<nav class="border-t border-white/6 px-5 pb-4 sm:px-10 lg:hidden">
|
||||
<nav id={mobileMenuId} class="border-t border-white/6 px-5 pb-4 sm:px-10 lg:hidden">
|
||||
<ul class="flex flex-col">
|
||||
{#each menuLinks as link (link.id)}
|
||||
<li>
|
||||
@@ -82,7 +116,8 @@
|
||||
<a
|
||||
href={link.href}
|
||||
class="nav-btn mt-3 block text-center"
|
||||
onclick={() => (mobileOpen = false)}
|
||||
onclick={() => closeMobileMenu()}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
>
|
||||
{link.text}
|
||||
</a>
|
||||
@@ -90,7 +125,8 @@
|
||||
<a
|
||||
href={link.href}
|
||||
class="nav-link block border-b border-white/6 py-3.5 last:border-0"
|
||||
onclick={() => (mobileOpen = false)}
|
||||
onclick={() => closeMobileMenu()}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
>
|
||||
{link.text}
|
||||
</a>
|
||||
|
||||
@@ -5,29 +5,45 @@
|
||||
type Props = {
|
||||
href?: string;
|
||||
target?: string;
|
||||
type?: 'button' | 'submit' | 'reset';
|
||||
variant?: 'primary' | 'secondary';
|
||||
class?: string;
|
||||
children: Snippet;
|
||||
};
|
||||
|
||||
let { href, target = '_self', variant = 'primary', class: className, children }: Props = $props();
|
||||
</script>
|
||||
let {
|
||||
href,
|
||||
target = '_self',
|
||||
type = 'button',
|
||||
variant = 'primary',
|
||||
class: className,
|
||||
children
|
||||
}: Props = $props();
|
||||
|
||||
<svelte:element
|
||||
this={href ? 'a' : 'button'}
|
||||
{href}
|
||||
{target}
|
||||
rel={target === '_blank' ? 'noopener noreferrer' : undefined}
|
||||
class={cn(
|
||||
const classes = $derived(
|
||||
cn(
|
||||
'flex w-fit items-center justify-center gap-2 rounded-xl px-6 py-3 font-display text-lg font-medium transition-colors duration-300',
|
||||
variant === 'primary' && 'bg-primary hover:bg-primary-h',
|
||||
variant === 'secondary' && 'border bg-bg hover:text-desc',
|
||||
className
|
||||
)}
|
||||
>
|
||||
)
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a {href} {target} rel={target === '_blank' ? 'noopener noreferrer' : undefined} class={classes}>
|
||||
{@render children()}
|
||||
|
||||
{#if variant === 'primary'}
|
||||
<img src="images/icons/arrow-right.svg" alt="Перейти" class="h-5 w-5" />
|
||||
<img src="/images/icons/arrow-right.svg" alt="" aria-hidden="true" class="h-5 w-5" />
|
||||
{/if}
|
||||
</a>
|
||||
{:else}
|
||||
<button {type} class={classes}>
|
||||
{@render children()}
|
||||
|
||||
{#if variant === 'primary'}
|
||||
<img src="/images/icons/arrow-right.svg" alt="" aria-hidden="true" class="h-5 w-5" />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
</svelte:element>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
</script>
|
||||
|
||||
<a href="/" class="flex max-w-fit items-center gap-2.5 no-underline">
|
||||
<img src="images/icons/logo.svg" alt="Логотип" class="h-8 w-8" />
|
||||
<img src="/images/icons/logo.svg" alt="" aria-hidden="true" class="h-8 w-8" />
|
||||
<span class="font-display text-xl font-black tracking-tighter">
|
||||
FLAMY<span class="text-primary">TRADE</span>
|
||||
</span>
|
||||
|
||||
@@ -6,6 +6,12 @@ export const site = {
|
||||
description: env.PUBLIC_SITE_DESCRIPTION || 'Публичная витрина ML-прогнозов для крипторынка.'
|
||||
};
|
||||
|
||||
export type PageMeta = {
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export function pageTitle(title?: string): string {
|
||||
return title ? `${title} | ${site.name}` : site.name;
|
||||
}
|
||||
@@ -14,3 +20,19 @@ export function canonical(path = '/'): string {
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
||||
return `${site.url}${normalizedPath}`;
|
||||
}
|
||||
|
||||
export function pageMeta({
|
||||
title,
|
||||
description = site.description,
|
||||
path = '/'
|
||||
}: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
path?: string;
|
||||
} = {}): PageMeta {
|
||||
return {
|
||||
title: pageTitle(title),
|
||||
description,
|
||||
url: canonical(path)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { env } from '$env/dynamic/public';
|
||||
import {
|
||||
generateChartData,
|
||||
SYMBOLS,
|
||||
TIMEFRAMES,
|
||||
type ChartData,
|
||||
type TimeframeId
|
||||
} from '$lib/stores/chartStore';
|
||||
|
||||
const supportedModes = ['research-static'] as const;
|
||||
|
||||
export type DashboardDataMode = (typeof supportedModes)[number];
|
||||
|
||||
export const dashboardDataMode: DashboardDataMode = supportedModes.includes(
|
||||
env.PUBLIC_DASHBOARD_DATA_MODE as DashboardDataMode
|
||||
)
|
||||
? (env.PUBLIC_DASHBOARD_DATA_MODE as DashboardDataMode)
|
||||
: 'research-static';
|
||||
|
||||
export const dashboardDataNotice =
|
||||
dashboardDataMode === 'research-static'
|
||||
? 'Исследовательские синтетические данные'
|
||||
: 'Исследовательские данные';
|
||||
|
||||
export function getDashboardChartData(symbolId: string, timeframeId: TimeframeId): ChartData {
|
||||
return generateChartData(symbolId, timeframeId);
|
||||
}
|
||||
|
||||
export { SYMBOLS, TIMEFRAMES };
|
||||
@@ -70,10 +70,6 @@
|
||||
<DashboardMockup />
|
||||
</div>
|
||||
|
||||
<!-- Визуальные элементы -->
|
||||
<span
|
||||
class="absolute -top-60 left-0 z-0 h-80 w-full rotate-3 rounded-full bg-primary opacity-30 blur-[200px]"
|
||||
></span>
|
||||
<span class="absolute bottom-35 left-0 z-0 hidden h-px w-full bg-bg-h xl:block"></span>
|
||||
<span class="absolute top-55 left-0 z-0 hidden h-px w-full bg-bg-h xl:block"></span>
|
||||
</section>
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { pageTitle } from '$lib/config/site';
|
||||
|
||||
const title = $derived(
|
||||
page.status === 404
|
||||
? 'Страница не найдена'
|
||||
: page.status >= 500
|
||||
? 'Внутренняя ошибка'
|
||||
: 'Произошла ошибка'
|
||||
);
|
||||
|
||||
const description = $derived(
|
||||
page.status === 404
|
||||
? 'Проверьте адрес или вернитесь к публичному дашборду Flamy Trade.'
|
||||
: 'Запрос не удалось обработать. Попробуйте обновить страницу позже.'
|
||||
);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle('Страница не найдена')}</title>
|
||||
<title>{pageTitle(title)}</title>
|
||||
<meta name="robots" content="noindex" />
|
||||
</svelte:head>
|
||||
|
||||
<section class="flex min-h-screen items-center justify-center px-5 pt-16 text-center">
|
||||
@@ -13,10 +28,10 @@
|
||||
Ошибка {page.status}
|
||||
</p>
|
||||
<h1 class="font-display text-[clamp(2.75rem,9vw,6.5rem)] leading-none font-black uppercase">
|
||||
Страница не найдена
|
||||
{title}
|
||||
</h1>
|
||||
<p class="mx-auto mt-5 max-w-lg text-base leading-relaxed text-desc sm:text-lg">
|
||||
Проверьте адрес или вернитесь к публичному дашборду Flamy Trade.
|
||||
{description}
|
||||
</p>
|
||||
<a
|
||||
href="/"
|
||||
|
||||
@@ -2,24 +2,15 @@
|
||||
import './layout.css';
|
||||
import Header from '$lib/components/layout/Header.svelte';
|
||||
import Footer from '$lib/components/layout/Footer.svelte';
|
||||
import { canonical, pageTitle, site } from '$lib/config/site';
|
||||
import { site } from '$lib/config/site';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle()}</title>
|
||||
<meta name="description" content={site.description} />
|
||||
<link rel="canonical" href={canonical('/')} />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content={site.name} />
|
||||
<meta property="og:title" content={pageTitle()} />
|
||||
<meta property="og:description" content={site.description} />
|
||||
<meta property="og:url" content={canonical('/')} />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:title" content={pageTitle()} />
|
||||
<meta name="twitter:description" content={site.description} />
|
||||
</svelte:head>
|
||||
|
||||
<div class="noise"></div>
|
||||
|
||||
+12
-7
@@ -7,16 +7,21 @@
|
||||
import BlogPreview from './(sections)/BlogPreview.svelte';
|
||||
import Cta from './(sections)/Cta.svelte';
|
||||
import { posts } from '$lib/blog/posts';
|
||||
import { canonical, pageTitle, site } from '$lib/config/site';
|
||||
import { pageMeta } from '$lib/config/site';
|
||||
|
||||
const meta = pageMeta();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle()}</title>
|
||||
<meta name="description" content={site.description} />
|
||||
<link rel="canonical" href={canonical('/')} />
|
||||
<meta property="og:title" content={pageTitle()} />
|
||||
<meta property="og:description" content={site.description} />
|
||||
<meta property="og:url" content={canonical('/')} />
|
||||
<title>{meta.title}</title>
|
||||
<meta name="description" content={meta.description} />
|
||||
<link rel="canonical" href={meta.url} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={meta.title} />
|
||||
<meta property="og:description" content={meta.description} />
|
||||
<meta property="og:url" content={meta.url} />
|
||||
<meta name="twitter:title" content={meta.title} />
|
||||
<meta name="twitter:description" content={meta.description} />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
import { about, params } from './_data';
|
||||
import { canonical, pageTitle } from '$lib/config/site';
|
||||
import { pageMeta } from '$lib/config/site';
|
||||
import { scrollFadeUp, scrollRevealLeft } from '$lib/gsap/actions';
|
||||
import { about, params } from './_data';
|
||||
|
||||
const meta = pageMeta({
|
||||
title: 'О проекте',
|
||||
description:
|
||||
'Flamy Trade показывает исследовательские результаты ML-модели для анализа крипторынка.',
|
||||
path: '/about'
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle('О проекте')}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Flamy Trade показывает демонстрационные результаты ML-модели для анализа крипторынка."
|
||||
/>
|
||||
<link rel="canonical" href={canonical('/about')} />
|
||||
<meta property="og:title" content={pageTitle('О проекте')} />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Flamy Trade показывает демонстрационные результаты ML-модели для анализа крипторынка."
|
||||
/>
|
||||
<meta property="og:url" content={canonical('/about')} />
|
||||
<title>{meta.title}</title>
|
||||
<meta name="description" content={meta.description} />
|
||||
<link rel="canonical" href={meta.url} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={meta.title} />
|
||||
<meta property="og:description" content={meta.description} />
|
||||
<meta property="og:url" content={meta.url} />
|
||||
<meta name="twitter:title" content={meta.title} />
|
||||
<meta name="twitter:description" content={meta.description} />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
@@ -39,10 +43,6 @@
|
||||
Публичная витрина результатов ML-модели, обученной на исторических рыночных данных.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<span
|
||||
class="absolute -top-20 -right-20 z-0 h-80 w-full rotate-3 rounded-full bg-primary opacity-30 blur-[200px]"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<section class="grid max-h-full! grid-cols-1 lg:grid-cols-[1fr_420px]">
|
||||
@@ -74,7 +74,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- padding на родителе — не margin/w-full на самом блоке -->
|
||||
<div class="border-b border-b-bg-h px-5 py-12 sm:px-10 sm:py-16">
|
||||
<div
|
||||
class="flex h-[50vh] w-full items-center justify-center rounded-2xl
|
||||
@@ -108,7 +107,7 @@
|
||||
<p
|
||||
class="mb-2 flex items-center gap-2 font-display text-xs font-bold tracking-widest text-primary uppercase"
|
||||
>
|
||||
⚠ Дисклеймер
|
||||
Дисклеймер
|
||||
</p>
|
||||
<p class="text-sm leading-normal text-desc">
|
||||
Материалы являются результатом работы исследовательской ML-модели и используются в
|
||||
|
||||
@@ -19,7 +19,7 @@ export const about: About[] = [
|
||||
desc: 'Назначение',
|
||||
title: 'Исследовательская платформа',
|
||||
text: [
|
||||
'Flamy AI — публичная витрина результатов ML-модели, обученной на исторических рыночных данных. Показывает прогнозы по крипто-инструментам: направление, уровни входа, Take Profit и Stop Loss.',
|
||||
'Flamy Trade — публичная витрина результатов ML-модели, обученной на исторических рыночных данных. Показывает прогнозы по крипто-инструментам: направление, уровни входа, Take Profit и Stop Loss.',
|
||||
'Платформа создана для изучения поведения ML-модели в рыночных условиях — не для торговли реальными средствами.'
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts">
|
||||
import { posts } from '$lib/blog/posts';
|
||||
import { canonical, pageTitle } from '$lib/config/site';
|
||||
import { scrollRevealLeft, scrollFadeUp, scrollStagger } from '$lib/gsap/actions';
|
||||
import { pageMeta } from '$lib/config/site';
|
||||
import { scrollFadeUp, scrollRevealLeft, scrollStagger } from '$lib/gsap/actions';
|
||||
|
||||
const meta = pageMeta({
|
||||
title: 'Блог',
|
||||
description:
|
||||
'Гайды Flamy Trade по чтению графиков, управлению рисками и работе с ML-прогнозами.',
|
||||
path: '/blog'
|
||||
});
|
||||
|
||||
function fmtDate(d: string) {
|
||||
try {
|
||||
@@ -17,18 +24,15 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle('Блог')}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Гайды Flamy Trade по чтению графиков, управлению рисками и работе с ML-прогнозами."
|
||||
/>
|
||||
<link rel="canonical" href={canonical('/blog')} />
|
||||
<meta property="og:title" content={pageTitle('Блог')} />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Гайды Flamy Trade по чтению графиков, управлению рисками и работе с ML-прогнозами."
|
||||
/>
|
||||
<meta property="og:url" content={canonical('/blog')} />
|
||||
<title>{meta.title}</title>
|
||||
<meta name="description" content={meta.description} />
|
||||
<link rel="canonical" href={meta.url} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={meta.title} />
|
||||
<meta property="og:description" content={meta.description} />
|
||||
<meta property="og:url" content={meta.url} />
|
||||
<meta name="twitter:title" content={meta.title} />
|
||||
<meta name="twitter:description" content={meta.description} />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
@@ -47,10 +51,6 @@
|
||||
Гайды по чтению графиков, управлению рисками и работе с ML-прогнозами.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<span
|
||||
class="absolute -right-20 -bottom-40 z-0 h-80 w-full -rotate-3 rounded-full bg-primary opacity-30 blur-[200px]"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -113,7 +113,7 @@
|
||||
<div
|
||||
class="mr-6 shrink-0 pt-1 text-desc/30 transition-[color,translate] duration-700 group-hover:translate-x-2 group-hover:text-primary"
|
||||
>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
|
||||
<path
|
||||
d="M4 10 H16 M12 6 L16 10 L12 14"
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { canonical, pageTitle } from '$lib/config/site';
|
||||
import { pageMeta } from '$lib/config/site';
|
||||
|
||||
let { data }: { data: PageData } = $props();
|
||||
const { post } = $derived(data);
|
||||
const meta = $derived(
|
||||
pageMeta({
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
path: `/blog/${post.slug}`
|
||||
})
|
||||
);
|
||||
|
||||
function fmtDate(d: string) {
|
||||
try {
|
||||
@@ -19,16 +26,16 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle(post.title)}</title>
|
||||
<meta name="description" content={post.description} />
|
||||
<link rel="canonical" href={canonical(`/blog/${post.slug}`)} />
|
||||
<title>{meta.title}</title>
|
||||
<meta name="description" content={meta.description} />
|
||||
<link rel="canonical" href={meta.url} />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content={pageTitle(post.title)} />
|
||||
<meta property="og:description" content={post.description} />
|
||||
<meta property="og:url" content={canonical(`/blog/${post.slug}`)} />
|
||||
<meta property="og:title" content={meta.title} />
|
||||
<meta property="og:description" content={meta.description} />
|
||||
<meta property="og:url" content={meta.url} />
|
||||
<meta property="article:published_time" content={post.date} />
|
||||
<meta name="twitter:title" content={pageTitle(post.title)} />
|
||||
<meta name="twitter:description" content={post.description} />
|
||||
<meta name="twitter:title" content={meta.title} />
|
||||
<meta name="twitter:description" content={meta.description} />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
@@ -37,7 +44,7 @@
|
||||
href="/blog"
|
||||
class="back-link mb-6 inline-flex items-center gap-1.5 font-mono text-[0.625rem] tracking-[0.08em] uppercase transition-colors"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
||||
<path
|
||||
d="M11 7 H3 M6 4 L3 7 L6 10"
|
||||
stroke="currentColor"
|
||||
@@ -63,7 +70,7 @@
|
||||
{/if}
|
||||
|
||||
<h1
|
||||
class="mb-5 font-display text-[clamp(1.875rem,5vw,2.75rem)] leading-[1.08] font-black tracking-[-0.035em] text-title"
|
||||
class="mb-5 font-display text-[clamp(1.875rem,5vw,2.75rem)] leading-[1.08] font-black tracking-tight text-title"
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
@@ -101,7 +108,7 @@
|
||||
href="/blog"
|
||||
class="back-link inline-flex items-center gap-1.5 font-mono text-[0.625rem] tracking-[0.08em] uppercase transition-colors"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
||||
<path
|
||||
d="M11 7 H3 M6 4 L3 7 L6 10"
|
||||
stroke="currentColor"
|
||||
@@ -118,7 +125,7 @@
|
||||
class="inline-flex items-center gap-2 rounded-xl bg-primary px-5 py-3 font-display text-sm font-normal transition-colors hover:bg-primary-h"
|
||||
>
|
||||
Открыть дашборд
|
||||
<img src="/images/icons/arrow-right.svg" alt="" class="h-4 w-4" />
|
||||
<img src="/images/icons/arrow-right.svg" alt="" aria-hidden="true" class="h-4 w-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,7 +146,7 @@
|
||||
font-size: 1.25rem;
|
||||
font-weight: 800;
|
||||
color: var(--color-title);
|
||||
letter-spacing: -0.025em;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.2;
|
||||
margin-top: 2.25em;
|
||||
margin-bottom: 0.75em;
|
||||
@@ -149,7 +156,7 @@
|
||||
font-size: 1.0625rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-title);
|
||||
letter-spacing: -0.02em;
|
||||
letter-spacing: 0;
|
||||
margin-top: 1.75em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { getPostBySlug } from '$lib/blog/posts';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { gsap } from 'gsap';
|
||||
import { generateChartData, SYMBOLS, TIMEFRAMES, type TimeframeId } from '$lib/stores/chartStore';
|
||||
import Chart from '$lib/components/Chart.svelte';
|
||||
import { canonical, pageTitle } from '$lib/config/site';
|
||||
import {
|
||||
dashboardDataNotice,
|
||||
getDashboardChartData,
|
||||
SYMBOLS,
|
||||
TIMEFRAMES
|
||||
} from '$lib/data/dashboard';
|
||||
import type { TimeframeId } from '$lib/stores/chartStore';
|
||||
import { pageMeta } from '$lib/config/site';
|
||||
import { cn } from '$lib/utils';
|
||||
|
||||
const meta = pageMeta({
|
||||
title: 'Дашборд',
|
||||
description:
|
||||
'Публичный исследовательский дашборд Flamy Trade с графиком, ML-прогнозом и уровнями Entry, TP и SL.',
|
||||
path: '/dashboard'
|
||||
});
|
||||
|
||||
let activeSymbol = $state('BTCUSDT');
|
||||
let activeTimeframe = $state<TimeframeId>('5m');
|
||||
let chartHeight = $state(520);
|
||||
|
||||
const sym = $derived(SYMBOLS.find((s) => s.id === activeSymbol) ?? SYMBOLS[0]);
|
||||
const data = $derived(generateChartData(activeSymbol, activeTimeframe));
|
||||
const data = $derived(getDashboardChartData(activeSymbol, activeTimeframe));
|
||||
|
||||
let titleEl = $state<HTMLElement>(null!);
|
||||
let panelEl = $state<HTMLElement>(null!);
|
||||
@@ -66,18 +79,15 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{pageTitle('Дашборд')}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Демонстрационный дашборд Flamy Trade с графиком, ML-прогнозом и уровнями Entry, TP и SL."
|
||||
/>
|
||||
<link rel="canonical" href={canonical('/dashboard')} />
|
||||
<meta property="og:title" content={pageTitle('Дашборд')} />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Демонстрационный дашборд Flamy Trade с графиком, ML-прогнозом и уровнями Entry, TP и SL."
|
||||
/>
|
||||
<meta property="og:url" content={canonical('/dashboard')} />
|
||||
<title>{meta.title}</title>
|
||||
<meta name="description" content={meta.description} />
|
||||
<link rel="canonical" href={meta.url} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={meta.title} />
|
||||
<meta property="og:description" content={meta.description} />
|
||||
<meta property="og:url" content={meta.url} />
|
||||
<meta name="twitter:title" content={meta.title} />
|
||||
<meta name="twitter:description" content={meta.description} />
|
||||
</svelte:head>
|
||||
|
||||
<main class="min-h-screen bg-bg">
|
||||
@@ -89,7 +99,7 @@
|
||||
Дашборд
|
||||
</h1>
|
||||
<p class="mt-1.5 font-mono text-[0.625rem] tracking-widest text-desc uppercase sm:text-xs">
|
||||
ML-прогноз · Горизонт 19 свечей · Таймфрейм 5M
|
||||
{dashboardDataNotice} · Горизонт 19 свечей · Таймфрейм {activeTimeframe.toUpperCase()}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -112,6 +122,7 @@
|
||||
: 'border-transparent text-desc hover:text-title'
|
||||
)}
|
||||
onclick={() => (activeSymbol = s.id)}
|
||||
aria-pressed={activeSymbol === s.id}
|
||||
>
|
||||
{s.short}
|
||||
</button>
|
||||
@@ -126,6 +137,7 @@
|
||||
activeTimeframe === tf.id ? 'bg-bg-h text-title' : 'text-desc hover:text-title'
|
||||
)}
|
||||
onclick={() => (activeTimeframe = tf.id)}
|
||||
aria-pressed={activeTimeframe === tf.id}
|
||||
>
|
||||
{tf.label}
|
||||
</button>
|
||||
@@ -177,7 +189,14 @@
|
||||
>
|
||||
Уверенность
|
||||
</span>
|
||||
<div class="h-1.5 w-16 overflow-hidden rounded-full bg-bg-h sm:w-20">
|
||||
<div
|
||||
class="h-1.5 w-16 overflow-hidden rounded-full bg-bg-h sm:w-20"
|
||||
role="progressbar"
|
||||
aria-label="Уверенность прогноза"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
aria-valuenow={data.signal.confidence}
|
||||
>
|
||||
<div
|
||||
class={cn(
|
||||
'h-full rounded-full transition-all duration-700',
|
||||
@@ -251,14 +270,9 @@
|
||||
</div>
|
||||
|
||||
<span class="ml-auto font-mono text-[0.5rem] tracking-widest text-desc/60 uppercase">
|
||||
не является инвестиционной рекомендацией
|
||||
исследовательские данные · не является инвестиционной рекомендацией
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="pointer-events-none fixed top-0 left-1/2 h-80 w-full max-w-3xl -translate-x-1/2 rounded-full bg-primary opacity-[0.07] blur-[160px]"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { canonical } from '$lib/config/site';
|
||||
|
||||
export const GET = () => {
|
||||
const body = `User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: ${canonical('/sitemap.xml')}
|
||||
`;
|
||||
|
||||
return new Response(body, {
|
||||
headers: {
|
||||
'content-type': 'text/plain; charset=utf-8',
|
||||
'cache-control': 'public, max-age=3600'
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://trade.flamy.studio/sitemap.xml
|
||||
+18
-1
@@ -6,7 +6,24 @@ const config = {
|
||||
// Force runes mode for the project, except for libraries. Can be removed in svelte 6.
|
||||
runes: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : true)
|
||||
},
|
||||
kit: { adapter: adapter() }
|
||||
kit: {
|
||||
adapter: adapter(),
|
||||
csp: {
|
||||
mode: 'auto',
|
||||
directives: {
|
||||
'default-src': ['self'],
|
||||
'script-src': ['self'],
|
||||
'style-src': ['self', 'unsafe-inline'],
|
||||
'img-src': ['self', 'data:'],
|
||||
'font-src': ['self'],
|
||||
'connect-src': ['self'],
|
||||
'object-src': ['none'],
|
||||
'base-uri': ['self'],
|
||||
'frame-ancestors': ['self'],
|
||||
'form-action': ['self']
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
Reference in New Issue
Block a user