From 74de2a6b0a360a745b791a099ae64c2885b8fe8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 6 Apr 2026 00:00:38 -0400 Subject: [PATCH 01/24] docs: add bilingual title to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 65d408a..cc3eceb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Vibe Coding - La Guía Definitiva +# Vibe Coding - The Ultimate Guide / La Guía Definitiva > Basado en el trabajo de Peter Wong · Creado por > [@daesdev](https://github.com/daesdev) From 22cf79ccd866efc8555570474132873b680543c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 6 Apr 2026 00:00:38 -0400 Subject: [PATCH 02/24] docs: add bilingual title to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 65d408a..cc3eceb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Vibe Coding - La Guía Definitiva +# Vibe Coding - The Ultimate Guide / La Guía Definitiva > Basado en el trabajo de Peter Wong · Creado por > [@daesdev](https://github.com/daesdev) From cac9087d473ef6814890ae77b7fa1f3ec5950dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 6 Apr 2026 00:03:10 -0400 Subject: [PATCH 03/24] fix: add imports alias to wrangler.jsonc for Cloudflare build --- wrangler.jsonc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wrangler.jsonc b/wrangler.jsonc index bbe053b..dc2947e 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -11,5 +11,10 @@ "pattern": "vibe-coding.daes.dev", "custom_domain": true } - ] + ], + "alias": { + "$fresh/": "https://deno.land/x/fresh@1.7.3/", + "preact": "https://esm.sh/preact@10.22.0", + "preact/": "https://esm.sh/preact@10.22.0/" + } } From 606f6cd17ca397fc0945bf6162105d52ed5e4bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 17:57:31 -0400 Subject: [PATCH 04/24] chore: configurar Husky y migrar a Cloudflare Workers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agregar Husky para pre-commit hooks con autoformateo - Agregar tasks: fmt, precommit, prepare en deno.json - Configurar pre-commit hook para ejecutar deno fmt + lint + check - Arreglar wrangler.jsonc: eliminar coma trailing, agregar nodejs_compat - Simplificar deploy.yml: eliminar cp innecesarios de _fresh - Refactor utils/i18n.ts: usar imports estáticos para CF Workers - Actualizar routes/_app.tsx: quitar async/await de función síncrona - Documentar workflow de desarrollo y limitaciones de CF Workers - Actualizar README.md y CLAUDE.md con guías completas --- .github/workflows/deploy.yml | 33 +---------- .gitignore | 3 + .husky/pre-commit | 5 ++ CLAUDE.md | 106 ++++++++++++++++++++++++++++++++--- README.md | 43 ++++++++++++++ deno.json | 3 + locales/es.json | 1 + routes/_app.tsx | 4 +- utils/i18n.ts | 43 +++++++------- wrangler.jsonc | 10 +--- 10 files changed, 184 insertions(+), 67 deletions(-) create mode 100755 .husky/pre-commit diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 661d0cc..c8cb6ed 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -6,8 +6,7 @@ on: branches: ["main"] jobs: - verify: - name: Verify + deploy: runs-on: ubuntu-latest permissions: @@ -20,7 +19,7 @@ jobs: - name: Install Deno uses: denoland/setup-deno@v2 with: - deno-version: v2.x + deno-version: "2.6.8" - name: Type check and lint run: deno task check @@ -28,34 +27,6 @@ jobs: - name: Build step run: deno task build - - name: Upload build artifacts - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-artifact@v4 - with: - name: fresh-build - path: | - _fresh/ - retention-days: 1 - - deploy: - name: Deploy to Cloudflare - runs-on: ubuntu-latest - needs: verify - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - - permissions: - contents: read - - steps: - - name: Clone repository - uses: actions/checkout@v4 - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: fresh-build - path: _fresh/ - - name: Deploy to Cloudflare Workers uses: cloudflare/wrangler-action@v3 with: diff --git a/.gitignore b/.gitignore index 5b4bdef..579b201 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ _fresh/ # npm dependencies node_modules/ + +# Husky (archivos internos - no trackear) +.husky/_ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..e3fcba3 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +echo "🔍 Running pre-commit checks (auto-formatting enabled)..." +deno task precommit diff --git a/CLAUDE.md b/CLAUDE.md index 5ea7f42..fb2f147 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,15 +60,76 @@ interface SectionWrapperContentProps { ## Comandos Importantes ```bash -deno task start # Desarrollo con hot-reload -deno task check # Fmt + Lint + Type check (verificación completa) -deno task build # Build de producción -deno task deploy # Desplegar a Cloudflare Workers -deno fmt # Formatear código -deno lint # Verificar lint -deno check **/*.ts # Verificar tipos +deno task start # Desarrollo con hot-reload +deno task check # Fmt + Lint + Type check (verificación completa) +deno task fmt # Formatear código +deno task precommit # Formatear + validar (usado en pre-commit hook) +deno task build # Build de producción +deno task deploy # Desplegar a Cloudflare Workers +deno lint # Verificar lint +deno check **/*.ts # Verificar tipos ``` +## Git Hooks (Husky) + +El proyecto usa Husky para garantizar calidad de código antes de cada commit. + +### Pre-commit Hook + +Ejecuta automáticamente `deno task precommit`: + +1. **`deno fmt`** - Formatea código automáticamente +2. **`deno lint`** - Valida reglas de linting (bloquea si falla) +3. **`deno check **/*.ts **/*.tsx`** - Valida tipos TypeScript (bloquea si + falla) + +### Setup + +Después de clonar el repositorio: + +```bash +deno install # Instala dependencias npm (Tailwind, Wrangler, etc.) +deno task prepare # Configura git hooks de Husky +``` + +### Diferencia: `check` vs `precommit` + +- **`deno task check`**: Usado en CI - valida sin modificar (`fmt --check`) +- **`deno task precommit`**: Usado en hook - formatea automáticamente (`fmt`) + +### Bypass (solo emergencias) + +```bash +git commit --no-verify -m "mensaje" +``` + +**Nota:** El CI de GitHub Actions ejecuta `deno task check` y validará de todas +formas. + +### Troubleshooting + +**Hook no se ejecuta:** + +```bash +# Re-instalar hooks +deno task prepare +``` + +**Deno no encontrado en hook:** + +```bash +# Verificar que Deno está en PATH +which deno + +# Si no está, agregarlo a ~/.zshrc: +export PATH="$HOME/.deno/bin:$PATH" +``` + +**Hook muy lento:** + +- Considerar usar `lint-staged` para verificar solo archivos modificados +- Por ahora, `deno check` verifica todos los archivos .ts/.tsx + ## Patrones Comunes ### Ruta con Middleware State @@ -126,5 +187,34 @@ export default function Component() { ## Notas de Deployment - El proyecto está configurado para Cloudflare Workers -- Secrets necesarios para Wrangler si se agregan +- Secrets necesarios: `CLOUDFLARE_API_TOKEN` y `CLOUDFLARE_ACCOUNT_ID` en GitHub + Actions - El archivo `static/styles.css` es generado por Tailwind durante el build + +## Cloudflare Workers - Diferencias vs Deno Deploy + +### Runtime Edge + +- **V8 Isolates**: Sin filesystem, solo APIs Web Standards +- **Cold start**: ~5ms (súper rápido) +- **300+ edge locations**: Latencia ultra baja global + +### Limitaciones + +- ❌ NO `Deno.readTextFile()` / `Deno.writeFile()` - sin filesystem +- ❌ NO `Deno.env.get()` - usar env bindings de Cloudflare +- ✅ Usar imports estáticos para assets (JSON, archivos) +- ⚠️ Límite CPU: 50ms por request (plan gratuito) +- ⚠️ Bundle size: 1MB compressed + +### Assets Estáticos + +- Servidos desde Cloudflare CDN (configurado en `wrangler.jsonc`) +- Directorio `./static` sube automáticamente +- Accesibles vía rutas absolutas (ej: `/styles.css`) + +### Traducciones (i18n) + +- Importadas estáticamente en `utils/i18n.ts` +- Bundleadas en build time (no filesystem en runtime) +- Agregar nuevo idioma requiere rebuild + deploy diff --git a/README.md b/README.md index cc3eceb..04dacf3 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,46 @@ Then start the project: ```bash deno task start ``` + +### Development Workflow + +Este proyecto usa **Husky** para ejecutar validaciones automáticas antes de cada +commit. + +#### Setup inicial (solo una vez): + +```bash +# Instalar dependencias npm de Deno (Tailwind, Wrangler, etc.) +deno install + +# Configurar git hooks de Husky +deno task prepare +``` + +Esto instalará automáticamente los hooks en `.git/hooks/`. + +#### Pre-commit Hook + +Cada vez que hagas `git commit`, se ejecutan automáticamente: + +1. **`deno fmt`** - Formatea el código automáticamente +2. **`deno lint`** - Valida reglas de linting (bloquea si falla) +3. **`deno check`** - Valida tipos TypeScript (bloquea si falla) + +#### Comandos útiles: + +```bash +deno task fmt # Formatear código manualmente +deno task check # Validar sin modificar (como en CI) +deno task precommit # Formatear + validar (como en el hook) +deno task start # Desarrollo con hot-reload +``` + +#### Bypass de hooks (solo emergencias): + +```bash +git commit --no-verify -m "emergency fix" +``` + +**⚠️ NO abusar de `--no-verify`** - el CI de GitHub Actions igual validará el +código. diff --git a/deno.json b/deno.json index 47397b4..b66e048 100644 --- a/deno.json +++ b/deno.json @@ -2,6 +2,9 @@ "lock": false, "tasks": { "check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx", + "fmt": "deno fmt", + "precommit": "deno fmt && deno lint && deno check **/*.ts && deno check **/*.tsx", + "prepare": "deno run -A npm:husky install", "cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -", "manifest": "deno task cli manifest $(pwd)", "start": "deno run -A --watch=static/,routes/ dev.ts", diff --git a/locales/es.json b/locales/es.json index 1149f86..d996700 100644 --- a/locales/es.json +++ b/locales/es.json @@ -1,4 +1,5 @@ { + "site": { "title": "Codificación de vibraciones(vibe coding)", "description": "La codificación de vibraciones (vibe coding) es una técnica de programación que utiliza inteligencia artificial (IA) para construir software basado en descripciones en lenguaje natural." diff --git a/routes/_app.tsx b/routes/_app.tsx index 1fbc87d..97b04b4 100644 --- a/routes/_app.tsx +++ b/routes/_app.tsx @@ -6,13 +6,13 @@ interface State { lang: string; translations: typeof translations; } -export default async function App( +export default function App( req: Request, ctx: FreshContext, ) { const url = new URL(req.url); const lang = url.pathname.split("/")[1] || "es"; - const translations = await t(lang); + const translations = t(lang); ctx.state.lang = lang; ctx.state.translations = translations; return ( diff --git a/utils/i18n.ts b/utils/i18n.ts index 4ee8ccc..1d296dd 100644 --- a/utils/i18n.ts +++ b/utils/i18n.ts @@ -1,23 +1,28 @@ -import translations from "../locales/es.json" with { type: "json" }; +import translationsEs from "../locales/es.json" with { type: "json" }; +import translationsEn from "../locales/en.json" with { type: "json" }; -type Translations = typeof translations; +type Translations = typeof translationsEs; -export async function t( - lang: string = "es", -) { - try { - const fileLang = await Deno.readTextFile(`./locales/${lang}.json`); - return JSON.parse(fileLang) as Translations; - } catch { - const esFileLang = await Deno.readTextFile(`./locales/es.json`); - const jsonResponse = JSON.parse(esFileLang); - // add error message - jsonResponse.error = { - message: - `No se encontró el idioma ${lang}. Se ha cargado el idioma por defecto (español).`, - title: "Error de idioma", - lang: lang, - }; - return jsonResponse as Translations; +const TRANSLATIONS_MAP: Record = { + es: translationsEs, + en: translationsEn, +}; + +export function t(lang: string = "es"): Translations { + const translations = TRANSLATIONS_MAP[lang]; + + if (!translations) { + // Fallback a español con mensaje de error + return { + ...translationsEs, + error: { + message: + `No se encontró el idioma ${lang}. Se ha cargado el idioma por defecto (español).`, + title: "Error de idioma", + lang: lang, + }, + } as Translations; } + + return translations; } diff --git a/wrangler.jsonc b/wrangler.jsonc index dc2947e..3661e9c 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -1,7 +1,8 @@ { "name": "vibe-coding", - "main": "./server.ts", "compatibility_date": "2026-03-29", + "compatibility_flags": ["nodejs_compat"], + "main": "./main.ts", "assets": { "binding": "ASSETS", "directory": "./static" @@ -11,10 +12,5 @@ "pattern": "vibe-coding.daes.dev", "custom_domain": true } - ], - "alias": { - "$fresh/": "https://deno.land/x/fresh@1.7.3/", - "preact": "https://esm.sh/preact@10.22.0", - "preact/": "https://esm.sh/preact@10.22.0/" - } + ] } From 4093bc257f5315755495f0535ad4308b3321765d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 17:57:50 -0400 Subject: [PATCH 05/24] style: formatear locales/es.json --- locales/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/es.json b/locales/es.json index d996700..3af7bce 100644 --- a/locales/es.json +++ b/locales/es.json @@ -1,11 +1,11 @@ { - "site": { "title": "Codificación de vibraciones(vibe coding)", "description": "La codificación de vibraciones (vibe coding) es una técnica de programación que utiliza inteligencia artificial (IA) para construir software basado en descripciones en lenguaje natural." }, "index": { "header": "Peter Wong • Constellar.ai • Traducido por Midudev", + "sections": [ { "title": "¿Qué es el Vibe Coding?", From adefe0297d2bdb8f81603bb93c2c4475e3af537c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 18:11:49 -0400 Subject: [PATCH 06/24] fix: quitar async innecesario de App function en _app.tsx --- .husky/pre-commit | 4 ++-- CLAUDE.md | 9 ++++++--- locales/en.json | 1 + locales/es.json | 2 +- routes/[lang]/index.tsx | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index e3fcba3..1c4c99f 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,5 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" +# Husky pre-commit hook (v9 forward-compatible format) +export PATH="$HOME/.deno/bin:$PATH" echo "🔍 Running pre-commit checks (auto-formatting enabled)..." deno task precommit diff --git a/CLAUDE.md b/CLAUDE.md index fb2f147..fa8c5ad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,12 +117,15 @@ deno task prepare **Deno no encontrado en hook:** +El hook `.husky/pre-commit` ya incluye `export PATH="$HOME/.deno/bin:$PATH"` para +garantizar que Deno esté disponible. Si aún falla, verificar: + ```bash -# Verificar que Deno está en PATH +# Verificar que Deno está instalado which deno -# Si no está, agregarlo a ~/.zshrc: -export PATH="$HOME/.deno/bin:$PATH" +# Si no está, instalarlo: +curl -fsSL https://deno.land/install.sh | sh ``` **Hook muy lento:** diff --git a/locales/en.json b/locales/en.json index 071074f..39cf6ae 100644 --- a/locales/en.json +++ b/locales/en.json @@ -5,6 +5,7 @@ }, "index": { "header": "Peter Wong • Constellar.ai", + "title": "The Ultimate Guide to Vibe Coding", "sections": [ { "title": "What Is Vibe Coding?", diff --git a/locales/es.json b/locales/es.json index 3af7bce..fa6f67e 100644 --- a/locales/es.json +++ b/locales/es.json @@ -5,7 +5,7 @@ }, "index": { "header": "Peter Wong • Constellar.ai • Traducido por Midudev", - + "title": "La Guía Definitiva del Vibe Coding", "sections": [ { "title": "¿Qué es el Vibe Coding?", diff --git a/routes/[lang]/index.tsx b/routes/[lang]/index.tsx index 9cb603f..e87d7c2 100644 --- a/routes/[lang]/index.tsx +++ b/routes/[lang]/index.tsx @@ -39,7 +39,7 @@ export default function Home( {translations.index.header} - +
{translations.index.sections.map((section) => ( From bae7c356e7eab94ba4920c7d52c6cb279b6663df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 18:11:57 -0400 Subject: [PATCH 07/24] fix: actualizar hook de Husky a formato v9+ y agregar PATH de Deno --- CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index fa8c5ad..74b1557 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,8 +117,8 @@ deno task prepare **Deno no encontrado en hook:** -El hook `.husky/pre-commit` ya incluye `export PATH="$HOME/.deno/bin:$PATH"` para -garantizar que Deno esté disponible. Si aún falla, verificar: +El hook `.husky/pre-commit` ya incluye `export PATH="$HOME/.deno/bin:$PATH"` +para garantizar que Deno esté disponible. Si aún falla, verificar: ```bash # Verificar que Deno está instalado From a984aff57eee706830ca909f3d15f80d8dd3c6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 18:12:07 -0400 Subject: [PATCH 08/24] feat: add titles to translations in English and Spanish locales --- deno.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deno.json b/deno.json index b66e048..bff0e82 100644 --- a/deno.json +++ b/deno.json @@ -22,7 +22,9 @@ } }, "exclude": [ - "**/_fresh/*" + "**/_fresh/*", + "**/node_modules/*", + ".husky/*" ], "imports": { "$fresh/": "https://deno.land/x/fresh@1.7.3/", From 4ef111184e039b18e6bc8da3d6ec4444a8a83b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Sun, 12 Apr 2026 18:20:17 -0400 Subject: [PATCH 09/24] =?UTF-8?q?chore:=20agregar=20package.json=20m=C3=AD?= =?UTF-8?q?nimo=20para=20Wrangler=20en=20CI/CD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy.yml | 3 +++ CLAUDE.md | 5 +++++ README.md | 8 +++++--- package.json | 13 +++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 package.json diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c8cb6ed..b8d860a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,6 +21,9 @@ jobs: with: deno-version: "2.6.8" + - name: Install npm dependencies + run: npm install + - name: Type check and lint run: deno task check diff --git a/CLAUDE.md b/CLAUDE.md index 74b1557..94f7260 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,6 +14,11 @@ Proyecto construido con Deno Fresh con soporte para internacionalización - **CSS**: Tailwind CSS 3.4.1 - **Deployment**: Cloudflare Workers (via Wrangler) +**Nota sobre dependencias**: El proyecto usa Deno como runtime principal, pero +incluye un `package.json` mínimo con Wrangler 4.80.0 como devDependency +exclusivamente para GitHub Actions CI/CD. Tailwind y otras herramientas se +instalan vía Deno. + ## Convenciones de Código ### Componentes Fresh diff --git a/README.md b/README.md index 04dacf3..1a87ef2 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,16 @@ commit. #### Setup inicial (solo una vez): ```bash -# Instalar dependencias npm de Deno (Tailwind, Wrangler, etc.) -deno install +# Instalar dependencias npm (Wrangler para CI/CD) +npm install # Configurar git hooks de Husky deno task prepare ``` -Esto instalará automáticamente los hooks en `.git/hooks/`. +**Nota**: Este proyecto usa Deno como runtime principal, pero incluye un +`package.json` mínimo con Wrangler como devDependency para facilitar el deploy +en GitHub Actions. #### Pre-commit Hook diff --git a/package.json b/package.json new file mode 100644 index 0000000..8888386 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "landing-vibe-coding-peter-wong", + "version": "1.0.0", + "private": true, + "description": "Landing page informativa sobre Vibe Coding basada en el trabajo de Peter Wong", + "type": "module", + "scripts": { + "deploy": "wrangler deploy" + }, + "devDependencies": { + "wrangler": "4.80.0" + } +} From db812eb609ddf0274a3912366df5cb42ac1683d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:27:20 -0400 Subject: [PATCH 10/24] feat: upgrade to Fresh 2.2.2 with Vite and Tailwind CSS 4 - Update deno.json with Fresh 2.2.2, Vite 7.3.2, and Preact 10.22.0 - Replace fresh.config.ts with vite.config.ts for Vite-based build - Migrate from Fresh 1.x dev.ts/server.ts to Fresh 2 client.ts entry - Add utils.ts with State interface and define helper for type safety - Implement i18n middleware in main.ts for state injection - Update _app.tsx to read state instead of modifying it (Fresh 2 pattern) - Simplify route handlers to use state from middleware - Remove Fresh 1.x manifest (fresh.gen.ts) and legacy config files - Migrate to Tailwind CSS 4 with @theme in assets/css/styles.css - Remove tailwind.config.ts (Tailwind 4 uses CSS-only config) - Update wrangler.jsonc compatibility_date for Cloudflare Workers - Make utils Cloudflare Workers compatible (no filesystem APIs) - Add deno.lock for reproducible builds --- static/styles.css => assets/css/fonts.css | 8 +- assets/css/styles.css | 26 + client.ts | 2 + deno.json | 31 +- deno.lock | 1838 +++++++++++++++++++++ dev.ts | 8 - fresh.config.ts | 6 - fresh.gen.ts | 29 - main.ts | 38 +- package.json | 5 +- postcss.config.js | 5 - routes/[lang]/index.tsx | 46 +- routes/_app.tsx | 54 +- routes/index.tsx | 41 +- server.ts | 15 - tailwind.config.ts | 16 - utils.ts | 19 + utils/global.ts | 14 +- utils/i18n.ts | 4 +- vite.config.ts | 10 + wrangler.jsonc | 2 +- 21 files changed, 2011 insertions(+), 206 deletions(-) rename static/styles.css => assets/css/fonts.css (63%) create mode 100644 assets/css/styles.css create mode 100644 client.ts create mode 100644 deno.lock delete mode 100755 dev.ts delete mode 100644 fresh.config.ts delete mode 100644 fresh.gen.ts delete mode 100644 postcss.config.js delete mode 100644 server.ts delete mode 100644 tailwind.config.ts create mode 100644 utils.ts create mode 100644 vite.config.ts diff --git a/static/styles.css b/assets/css/fonts.css similarity index 63% rename from static/styles.css rename to assets/css/fonts.css index 5204e17..937a58b 100644 --- a/static/styles.css +++ b/assets/css/fonts.css @@ -1,11 +1,11 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - @font-face { font-family: "roboto-mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("/fonts/roboto-mono-latin-500-normal.woff") format("woff"); + size-adjust: 100%; + ascent-override: 0.1em; + descent-override: 0.1em; + line-gap-override: 0.1em; } diff --git a/assets/css/styles.css b/assets/css/styles.css new file mode 100644 index 0000000..24b79f9 --- /dev/null +++ b/assets/css/styles.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; +@import "./fonts.css"; + +@custom-variant dark (&:where(.dark, .dark *)); + +@theme { + --font-sans: "Inter var", "system-ui", "sans-serif"; + --font-roboto-mono: "roboto-mono", "monospace"; +} + +@layer theme { + :root { + color-scheme: light; + } + + :root.dark { + color-scheme: dark; + } +} + +html { + font-family: var(--font-sans); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; +} diff --git a/client.ts b/client.ts new file mode 100644 index 0000000..0abb687 --- /dev/null +++ b/client.ts @@ -0,0 +1,2 @@ +// Import CSS files here for hot module reloading to work. +import "./assets/css/styles.css"; diff --git a/deno.json b/deno.json index bff0e82..eabb907 100644 --- a/deno.json +++ b/deno.json @@ -1,16 +1,13 @@ { - "lock": false, "tasks": { - "check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx", + "check": "deno fmt --check && deno lint && deno check", "fmt": "deno fmt", "precommit": "deno fmt && deno lint && deno check **/*.ts && deno check **/*.tsx", "prepare": "deno run -A npm:husky install", - "cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -", - "manifest": "deno task cli manifest $(pwd)", - "start": "deno run -A --watch=static/,routes/ dev.ts", - "build": "deno run -A dev.ts build", - "preview": "deno run -A main.ts", - "update": "deno run -A -r https://fresh.deno.dev/update .", + "dev": "vite", + "build": "vite build", + "preview": "deno serve -A _fresh/server.js", + "update": "deno run -A -r jsr:@fresh/update .", "deploy": "deno run -A npm:wrangler deploy" }, "lint": { @@ -27,19 +24,19 @@ ".husky/*" ], "imports": { - "$fresh/": "https://deno.land/x/fresh@1.7.3/", - "preact": "https://esm.sh/preact@10.22.0", + "@fresh/plugin-tailwind": "jsr:@fresh/plugin-tailwind@^1.0.0", + "@fresh/plugin-vite": "jsr:@fresh/plugin-vite@^1.0.8", + "preact": "npm:preact@^10.28.3", "preact/": "https://esm.sh/preact@10.22.0/", - "@preact/signals": "https://esm.sh/*@preact/signals@1.2.2", - "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1", - "tailwindcss": "npm:tailwindcss@3.4.1", - "tailwindcss/": "npm:/tailwindcss@3.4.1/", - "tailwindcss/plugin": "npm:/tailwindcss@3.4.1/plugin.js", - "$std/": "https://deno.land/std@0.216.0/" + "@preact/signals": "npm:@preact/signals@^2.7.1", + "$std/": "https://deno.land/std@0.216.0/", + "fresh": "jsr:@fresh/core@^2.2.2", + "vite": "npm:vite@7.3.2", + "@/": "./" }, "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" }, - "nodeModulesDir": "auto" + "nodeModulesDir": "manual" } diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..9c50417 --- /dev/null +++ b/deno.lock @@ -0,0 +1,1838 @@ +{ + "version": "5", + "specifiers": { + "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.1", + "jsr:@deno/loader@~0.3.10": "0.3.14", + "jsr:@deno/loader@~0.3.2": "0.3.14", + "jsr:@fresh/build-id@1": "1.0.1", + "jsr:@fresh/core@2": "2.2.2", + "jsr:@fresh/core@^2.2.0": "2.2.2", + "jsr:@fresh/core@^2.2.2": "2.2.2", + "jsr:@fresh/plugin-tailwind@1": "1.0.0", + "jsr:@fresh/plugin-vite@^1.0.8": "1.0.8", + "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/dotenv@~0.225.5": "0.225.6", + "jsr:@std/encoding@^1.0.10": "1.0.10", + "jsr:@std/fmt@^1.0.7": "1.0.9", + "jsr:@std/fmt@^1.0.8": "1.0.9", + "jsr:@std/fs@^1.0.19": "1.0.23", + "jsr:@std/html@^1.0.5": "1.0.5", + "jsr:@std/http@^1.0.21": "1.0.25", + "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/json@^1.0.2": "1.0.3", + "jsr:@std/jsonc@^1.0.2": "1.0.2", + "jsr:@std/media-types@^1.1.0": "1.1.0", + "jsr:@std/path@1": "1.1.4", + "jsr:@std/path@^1.1.1": "1.1.4", + "jsr:@std/path@^1.1.2": "1.1.4", + "jsr:@std/path@^1.1.4": "1.1.4", + "jsr:@std/semver@^1.0.6": "1.0.8", + "jsr:@std/uuid@^1.0.9": "1.1.0", + "npm:@babel/core@^7.28.0": "7.29.0", + "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0", + "npm:@mjackson/node-fetch-server@0.7": "0.7.0", + "npm:@opentelemetry/api@^1.9.0": "1.9.1", + "npm:@preact/signals@^2.5.1": "2.9.0_preact@10.29.1", + "npm:@preact/signals@^2.7.1": "2.9.0_preact@10.29.1", + "npm:@prefresh/vite@^2.4.8": "2.4.12_preact@10.29.1_vite@7.3.2__picomatch@4.0.4", + "npm:@tailwindcss/postcss@^4.1.10": "4.2.2", + "npm:@tailwindcss/vite@^4.2.2": "4.2.2_vite@7.3.2__picomatch@4.0.4", + "npm:esbuild-wasm@~0.25.11": "0.25.12", + "npm:esbuild@0.25.7": "0.25.7", + "npm:esbuild@~0.25.5": "0.25.12", + "npm:postcss@8.5.6": "8.5.6", + "npm:preact-render-to-string@^6.6.3": "6.6.7_preact@10.29.1", + "npm:preact@^10.28.2": "10.29.1", + "npm:preact@^10.28.3": "10.29.1", + "npm:rollup@^4.50.0": "4.60.1", + "npm:vite@7.3.2": "7.3.2_picomatch@4.0.4", + "npm:vite@^7.1.4": "7.3.2_picomatch@4.0.4", + "npm:wrangler@4.81.1": "4.81.1_unenv@2.0.0-rc.24_workerd@1.20260409.1" + }, + "jsr": { + "@deno/esbuild-plugin@1.2.1": { + "integrity": "df629467913adc1f960149fdfa3a3430ba8c20381c310fba096db244e6c3c9f6", + "dependencies": [ + "jsr:@deno/loader@~0.3.10", + "jsr:@std/path@^1.1.1", + "npm:esbuild@~0.25.5" + ] + }, + "@deno/loader@0.3.14": { + "integrity": "97bc63a6cc2d27a60bcdc953f588c5213331d866d44212eebb24cebfb9b011ca" + }, + "@fresh/build-id@1.0.1": { + "integrity": "12a2ec25fd52ae9ec68c26848a5696cd1c9b537f7c983c7e56e4fb1e7e816c20", + "dependencies": [ + "jsr:@std/encoding" + ] + }, + "@fresh/core@2.2.2": { + "integrity": "c34873df58457720f7b915a65fef6fe5cd7215f237cf4d1064d1925b320de96c", + "dependencies": [ + "jsr:@deno/esbuild-plugin", + "jsr:@fresh/build-id", + "jsr:@std/encoding", + "jsr:@std/fmt@^1.0.8", + "jsr:@std/fs", + "jsr:@std/html", + "jsr:@std/http", + "jsr:@std/jsonc", + "jsr:@std/media-types", + "jsr:@std/path@^1.1.2", + "jsr:@std/semver", + "jsr:@std/uuid", + "npm:@opentelemetry/api", + "npm:@preact/signals@^2.5.1", + "npm:esbuild-wasm", + "npm:esbuild@0.25.7", + "npm:preact-render-to-string", + "npm:preact@^10.28.2", + "npm:preact@^10.28.3" + ] + }, + "@fresh/plugin-tailwind@1.0.0": { + "integrity": "3bb3598fb0422392d52ad017285f1d702f1d7b3bddd4028f9da90c0c3baebf37", + "dependencies": [ + "jsr:@fresh/core@2", + "npm:@tailwindcss/postcss", + "npm:postcss" + ] + }, + "@fresh/plugin-vite@1.0.8": { + "integrity": "5780d842ed82e4cbccd93dd8ba2d54bf59dff5aee65921134aab15a4cd457c56", + "dependencies": [ + "jsr:@deno/loader@~0.3.2", + "jsr:@fresh/core@2", + "jsr:@fresh/core@^2.2.0", + "jsr:@std/dotenv", + "jsr:@std/fmt@^1.0.7", + "jsr:@std/path@1", + "npm:@babel/core", + "npm:@babel/preset-react", + "npm:@mjackson/node-fetch-server", + "npm:@prefresh/vite", + "npm:rollup", + "npm:vite@^7.1.4" + ] + }, + "@std/bytes@1.0.6": { + "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" + }, + "@std/dotenv@0.225.6": { + "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" + }, + "@std/encoding@1.0.10": { + "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" + }, + "@std/fmt@1.0.9": { + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" + }, + "@std/fs@1.0.23": { + "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", + "dependencies": [ + "jsr:@std/path@^1.1.4" + ] + }, + "@std/html@1.0.5": { + "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" + }, + "@std/http@1.0.25": { + "integrity": "577b4252290af1097132812b339fffdd55fb0f4aeb98ff11bdbf67998aa17193", + "dependencies": [ + "jsr:@std/encoding" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/json@1.0.3": { + "integrity": "97d5710996293a027b7aa5f0d1f4fa29f246f269e6b5597e08807613f37d426c" + }, + "@std/jsonc@1.0.2": { + "integrity": "909605dae3af22bd75b1cbda8d64a32cf1fd2cf6efa3f9e224aba6d22c0f44c7", + "dependencies": [ + "jsr:@std/json" + ] + }, + "@std/media-types@1.1.0": { + "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/semver@1.0.8": { + "integrity": "dc830e8b8b6a380c895d53fbfd1258dc253704ca57bbe1629ac65fd7830179b7" + }, + "@std/uuid@1.1.0": { + "integrity": "6268db2ccf172849c9be80763354ca305d49ef4af41fe995623d44fcc3f7457c", + "dependencies": [ + "jsr:@std/bytes" + ] + } + }, + "npm": { + "@alloc/quick-lru@5.2.0": { + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" + }, + "@babel/code-frame@7.29.0": { + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dependencies": [ + "@babel/helper-validator-identifier", + "js-tokens", + "picocolors" + ] + }, + "@babel/compat-data@7.29.0": { + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==" + }, + "@babel/core@7.29.0": { + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-compilation-targets", + "@babel/helper-module-transforms", + "@babel/helpers", + "@babel/parser", + "@babel/template", + "@babel/traverse", + "@babel/types", + "@jridgewell/remapping", + "convert-source-map", + "debug", + "gensync", + "json5", + "semver@6.3.1" + ] + }, + "@babel/generator@7.29.1": { + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dependencies": [ + "@babel/parser", + "@babel/types", + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping@0.3.31", + "jsesc" + ] + }, + "@babel/helper-annotate-as-pure@7.27.3": { + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dependencies": [ + "@babel/types" + ] + }, + "@babel/helper-compilation-targets@7.28.6": { + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dependencies": [ + "@babel/compat-data", + "@babel/helper-validator-option", + "browserslist", + "lru-cache", + "semver@6.3.1" + ] + }, + "@babel/helper-globals@7.28.0": { + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" + }, + "@babel/helper-module-imports@7.28.6": { + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dependencies": [ + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helper-module-transforms@7.28.6_@babel+core@7.29.0": { + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-imports", + "@babel/helper-validator-identifier", + "@babel/traverse" + ] + }, + "@babel/helper-plugin-utils@7.28.6": { + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==" + }, + "@babel/helper-string-parser@7.27.1": { + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" + }, + "@babel/helper-validator-identifier@7.28.5": { + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" + }, + "@babel/helper-validator-option@7.27.1": { + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==" + }, + "@babel/helpers@7.29.2": { + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dependencies": [ + "@babel/template", + "@babel/types" + ] + }, + "@babel/parser@7.29.2": { + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dependencies": [ + "@babel/types" + ], + "bin": true + }, + "@babel/plugin-syntax-jsx@7.28.6_@babel+core@7.29.0": { + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.29.0": { + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.29.0": { + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "dependencies": [ + "@babel/core", + "@babel/plugin-transform-react-jsx" + ] + }, + "@babel/plugin-transform-react-jsx@7.28.6_@babel+core@7.29.0": { + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-module-imports", + "@babel/helper-plugin-utils", + "@babel/plugin-syntax-jsx", + "@babel/types" + ] + }, + "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.29.0": { + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-plugin-utils" + ] + }, + "@babel/preset-react@7.28.5_@babel+core@7.29.0": { + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-validator-option", + "@babel/plugin-transform-react-display-name", + "@babel/plugin-transform-react-jsx", + "@babel/plugin-transform-react-jsx-development", + "@babel/plugin-transform-react-pure-annotations" + ] + }, + "@babel/template@7.28.6": { + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dependencies": [ + "@babel/code-frame", + "@babel/parser", + "@babel/types" + ] + }, + "@babel/traverse@7.29.0": { + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-globals", + "@babel/parser", + "@babel/template", + "@babel/types", + "debug" + ] + }, + "@babel/types@7.29.0": { + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dependencies": [ + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" + ] + }, + "@cloudflare/kv-asset-handler@0.4.2": { + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==" + }, + "@cloudflare/unenv-preset@2.16.0_unenv@2.0.0-rc.24_workerd@1.20260409.1": { + "integrity": "sha512-8ovsRpwzPoEqPUzoErAYVv8l3FMZNeBVQfJTvtzP4AgLSRGZISRfuChFxHWUQd3n6cnrwkuTGxT+2cGo8EsyYg==", + "dependencies": [ + "unenv", + "workerd" + ], + "optionalPeers": [ + "workerd" + ] + }, + "@cloudflare/workerd-darwin-64@1.20260409.1": { + "integrity": "sha512-h/bkaC0HJL63aqAGnV0oagqpBiTSstabODThkeMSbG8kctl0Jb4jlq1pNHJPmYGazFNtfyagrUZFb6HN22GX7w==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@cloudflare/workerd-darwin-arm64@1.20260409.1": { + "integrity": "sha512-HTAC+B9uSYcm+GjN3UYJjuun19GqYtK1bAFJ0KECXyfsgIDwH1MTzxbTxzJpZUbWLw8s0jcwCU06MWZj6cgnxQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@cloudflare/workerd-linux-64@1.20260409.1": { + "integrity": "sha512-QIoNq5cgmn1ko8qlngmgZLXQr2KglrjvIwVFOyJI3rbIpt8631n/YMzHPiOWgt38Cb6tcni8fXOzkcvIX2lBDg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@cloudflare/workerd-linux-arm64@1.20260409.1": { + "integrity": "sha512-HJGBMTfPDb0GCjwdxWFx63wS20TYDVmtOuA5KVri/CiFnit71y++kmseVmemjsgLFFIzoEAuFG/xUh1FJLo6tg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@cloudflare/workerd-windows-64@1.20260409.1": { + "integrity": "sha512-GttFO0+TvE0rJNQbDlxC6kq2Q7uFxoZRo74Z9d/trUrLgA14HEVTTXobYyiWrDZ9Qp2W5KN1CrXQXiko0zE38Q==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@cspotcode/source-map-support@0.8.1": { + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": [ + "@jridgewell/trace-mapping@0.3.9" + ] + }, + "@emnapi/runtime@1.9.2": { + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dependencies": [ + "tslib" + ] + }, + "@esbuild/aix-ppc64@0.25.12": { + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/aix-ppc64@0.25.7": { + "integrity": "sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/aix-ppc64@0.27.3": { + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.25.12": { + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm64@0.25.7": { + "integrity": "sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm64@0.27.3": { + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.25.12": { + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-arm@0.25.7": { + "integrity": "sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-arm@0.27.3": { + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.25.12": { + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/android-x64@0.25.7": { + "integrity": "sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/android-x64@0.27.3": { + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.25.12": { + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-arm64@0.25.7": { + "integrity": "sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-arm64@0.27.3": { + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.25.12": { + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/darwin-x64@0.25.7": { + "integrity": "sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/darwin-x64@0.27.3": { + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.25.12": { + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-arm64@0.25.7": { + "integrity": "sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-arm64@0.27.3": { + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.25.12": { + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-x64@0.25.7": { + "integrity": "sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-x64@0.27.3": { + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.25.12": { + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm64@0.25.7": { + "integrity": "sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm64@0.27.3": { + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.25.12": { + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-arm@0.25.7": { + "integrity": "sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-arm@0.27.3": { + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.25.12": { + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-ia32@0.25.7": { + "integrity": "sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-ia32@0.27.3": { + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.25.12": { + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-loong64@0.25.7": { + "integrity": "sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-loong64@0.27.3": { + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.25.12": { + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-mips64el@0.25.7": { + "integrity": "sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-mips64el@0.27.3": { + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.25.12": { + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-ppc64@0.25.7": { + "integrity": "sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-ppc64@0.27.3": { + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.25.12": { + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-riscv64@0.25.7": { + "integrity": "sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-riscv64@0.27.3": { + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.25.12": { + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-s390x@0.25.7": { + "integrity": "sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-s390x@0.27.3": { + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.25.12": { + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/linux-x64@0.25.7": { + "integrity": "sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/linux-x64@0.27.3": { + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-arm64@0.25.12": { + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-arm64@0.25.7": { + "integrity": "sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-arm64@0.27.3": { + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-x64@0.25.12": { + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-x64@0.25.7": { + "integrity": "sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-x64@0.27.3": { + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.25.12": { + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-arm64@0.25.7": { + "integrity": "sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-arm64@0.27.3": { + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.25.12": { + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-x64@0.25.7": { + "integrity": "sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-x64@0.27.3": { + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openharmony-arm64@0.25.12": { + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/openharmony-arm64@0.25.7": { + "integrity": "sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/openharmony-arm64@0.27.3": { + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.25.12": { + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/sunos-x64@0.25.7": { + "integrity": "sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/sunos-x64@0.27.3": { + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.25.12": { + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-arm64@0.25.7": { + "integrity": "sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-arm64@0.27.3": { + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.25.12": { + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-ia32@0.25.7": { + "integrity": "sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-ia32@0.27.3": { + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.25.12": { + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@esbuild/win32-x64@0.25.7": { + "integrity": "sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@esbuild/win32-x64@0.27.3": { + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@img/colour@1.1.0": { + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==" + }, + "@img/sharp-darwin-arm64@0.34.5": { + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "optionalDependencies": [ + "@img/sharp-libvips-darwin-arm64" + ], + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@img/sharp-darwin-x64@0.34.5": { + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "optionalDependencies": [ + "@img/sharp-libvips-darwin-x64" + ], + "os": ["darwin"], + "cpu": ["x64"] + }, + "@img/sharp-libvips-darwin-arm64@1.2.4": { + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-darwin-x64@1.2.4": { + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@img/sharp-libvips-linux-arm64@1.2.4": { + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-linux-arm@1.2.4": { + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@img/sharp-libvips-linux-ppc64@1.2.4": { + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@img/sharp-libvips-linux-riscv64@1.2.4": { + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@img/sharp-libvips-linux-s390x@1.2.4": { + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@img/sharp-libvips-linux-x64@1.2.4": { + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-libvips-linuxmusl-arm64@1.2.4": { + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-libvips-linuxmusl-x64@1.2.4": { + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-linux-arm64@0.34.5": { + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-arm64" + ], + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-linux-arm@0.34.5": { + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-arm" + ], + "os": ["linux"], + "cpu": ["arm"] + }, + "@img/sharp-linux-ppc64@0.34.5": { + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-ppc64" + ], + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@img/sharp-linux-riscv64@0.34.5": { + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-riscv64" + ], + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@img/sharp-linux-s390x@0.34.5": { + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-s390x" + ], + "os": ["linux"], + "cpu": ["s390x"] + }, + "@img/sharp-linux-x64@0.34.5": { + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "optionalDependencies": [ + "@img/sharp-libvips-linux-x64" + ], + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-linuxmusl-arm64@0.34.5": { + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "optionalDependencies": [ + "@img/sharp-libvips-linuxmusl-arm64" + ], + "os": ["linux"], + "cpu": ["arm64"] + }, + "@img/sharp-linuxmusl-x64@0.34.5": { + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "optionalDependencies": [ + "@img/sharp-libvips-linuxmusl-x64" + ], + "os": ["linux"], + "cpu": ["x64"] + }, + "@img/sharp-wasm32@0.34.5": { + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "dependencies": [ + "@emnapi/runtime" + ], + "cpu": ["wasm32"] + }, + "@img/sharp-win32-arm64@0.34.5": { + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@img/sharp-win32-ia32@0.34.5": { + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@img/sharp-win32-x64@0.34.5": { + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@jridgewell/gen-mapping@0.3.13": { + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": [ + "@jridgewell/sourcemap-codec", + "@jridgewell/trace-mapping@0.3.31" + ] + }, + "@jridgewell/remapping@2.3.5": { + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dependencies": [ + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping@0.3.31" + ] + }, + "@jridgewell/resolve-uri@3.1.2": { + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/sourcemap-codec@1.5.5": { + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "@jridgewell/trace-mapping@0.3.31": { + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, + "@jridgewell/trace-mapping@0.3.9": { + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, + "@mjackson/node-fetch-server@0.7.0": { + "integrity": "sha512-un8diyEBKU3BTVj3GzlTPA1kIjCkGdD+AMYQy31Gf9JCkfoZzwgJ79GUtHrF2BN3XPNMLpubbzPcxys+a3uZEw==" + }, + "@opentelemetry/api@1.9.1": { + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==" + }, + "@poppinss/colors@4.1.6": { + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dependencies": [ + "kleur" + ] + }, + "@poppinss/dumper@0.6.5": { + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dependencies": [ + "@poppinss/colors", + "@sindresorhus/is", + "supports-color" + ] + }, + "@poppinss/exception@1.2.3": { + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==" + }, + "@preact/signals-core@1.14.1": { + "integrity": "sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng==" + }, + "@preact/signals@2.9.0_preact@10.29.1": { + "integrity": "sha512-hYrY0KyUqkDgOl1qba/JGn6y81pXnurn21PMaxfcMwdncdZ3M/oVdmpTvEnsGjh48dIwDVc7bjWHqIsngSjYug==", + "dependencies": [ + "@preact/signals-core", + "preact" + ] + }, + "@prefresh/babel-plugin@0.5.3": { + "integrity": "sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ==" + }, + "@prefresh/core@1.5.9_preact@10.29.1": { + "integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==", + "dependencies": [ + "preact" + ] + }, + "@prefresh/utils@1.2.1": { + "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" + }, + "@prefresh/vite@2.4.12_preact@10.29.1_vite@7.3.2__picomatch@4.0.4": { + "integrity": "sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA==", + "dependencies": [ + "@babel/core", + "@prefresh/babel-plugin", + "@prefresh/core", + "@prefresh/utils", + "@rollup/pluginutils", + "preact", + "vite" + ] + }, + "@rollup/pluginutils@4.2.1": { + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": [ + "estree-walker", + "picomatch@2.3.2" + ] + }, + "@rollup/rollup-android-arm-eabi@4.60.1": { + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@rollup/rollup-android-arm64@4.60.1": { + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-arm64@4.60.1": { + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-x64@4.60.1": { + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@rollup/rollup-freebsd-arm64@4.60.1": { + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@rollup/rollup-freebsd-x64@4.60.1": { + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-arm-gnueabihf@4.60.1": { + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm-musleabihf@4.60.1": { + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm64-gnu@4.60.1": { + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-arm64-musl@4.60.1": { + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-loong64-gnu@4.60.1": { + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-loong64-musl@4.60.1": { + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-ppc64-gnu@4.60.1": { + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-ppc64-musl@4.60.1": { + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-riscv64-gnu@4.60.1": { + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-riscv64-musl@4.60.1": { + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-s390x-gnu@4.60.1": { + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@rollup/rollup-linux-x64-gnu@4.60.1": { + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-x64-musl@4.60.1": { + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-openbsd-x64@4.60.1": { + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-openharmony-arm64@4.60.1": { + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-arm64-msvc@4.60.1": { + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-ia32-msvc@4.60.1": { + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@rollup/rollup-win32-x64-gnu@4.60.1": { + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@rollup/rollup-win32-x64-msvc@4.60.1": { + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@sindresorhus/is@7.2.0": { + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==" + }, + "@speed-highlight/core@1.2.15": { + "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==" + }, + "@tailwindcss/node@4.2.2": { + "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", + "dependencies": [ + "@jridgewell/remapping", + "enhanced-resolve", + "jiti", + "lightningcss", + "magic-string", + "source-map-js", + "tailwindcss" + ] + }, + "@tailwindcss/oxide-android-arm64@4.2.2": { + "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@tailwindcss/oxide-darwin-arm64@4.2.2": { + "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@tailwindcss/oxide-darwin-x64@4.2.2": { + "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@tailwindcss/oxide-freebsd-x64@4.2.2": { + "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2": { + "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@tailwindcss/oxide-linux-arm64-gnu@4.2.2": { + "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@tailwindcss/oxide-linux-arm64-musl@4.2.2": { + "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@tailwindcss/oxide-linux-x64-gnu@4.2.2": { + "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@tailwindcss/oxide-linux-x64-musl@4.2.2": { + "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@tailwindcss/oxide-wasm32-wasi@4.2.2": { + "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", + "cpu": ["wasm32"] + }, + "@tailwindcss/oxide-win32-arm64-msvc@4.2.2": { + "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@tailwindcss/oxide-win32-x64-msvc@4.2.2": { + "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@tailwindcss/oxide@4.2.2": { + "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", + "optionalDependencies": [ + "@tailwindcss/oxide-android-arm64", + "@tailwindcss/oxide-darwin-arm64", + "@tailwindcss/oxide-darwin-x64", + "@tailwindcss/oxide-freebsd-x64", + "@tailwindcss/oxide-linux-arm-gnueabihf", + "@tailwindcss/oxide-linux-arm64-gnu", + "@tailwindcss/oxide-linux-arm64-musl", + "@tailwindcss/oxide-linux-x64-gnu", + "@tailwindcss/oxide-linux-x64-musl", + "@tailwindcss/oxide-wasm32-wasi", + "@tailwindcss/oxide-win32-arm64-msvc", + "@tailwindcss/oxide-win32-x64-msvc" + ] + }, + "@tailwindcss/postcss@4.2.2": { + "integrity": "sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==", + "dependencies": [ + "@alloc/quick-lru", + "@tailwindcss/node", + "@tailwindcss/oxide", + "postcss", + "tailwindcss" + ] + }, + "@tailwindcss/vite@4.2.2_vite@7.3.2__picomatch@4.0.4": { + "integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==", + "dependencies": [ + "@tailwindcss/node", + "@tailwindcss/oxide", + "tailwindcss", + "vite" + ] + }, + "@types/estree@1.0.8": { + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "baseline-browser-mapping@2.10.18": { + "integrity": "sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==", + "bin": true + }, + "blake3-wasm@2.1.5": { + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==" + }, + "browserslist@4.28.2": { + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dependencies": [ + "baseline-browser-mapping", + "caniuse-lite", + "electron-to-chromium", + "node-releases", + "update-browserslist-db" + ], + "bin": true + }, + "caniuse-lite@1.0.30001787": { + "integrity": "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==" + }, + "convert-source-map@2.0.0": { + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "cookie@1.1.1": { + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==" + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, + "detect-libc@2.1.2": { + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + }, + "electron-to-chromium@1.5.335": { + "integrity": "sha512-q9n5T4BR4Xwa2cwbrwcsDJtHD/enpQ5S1xF1IAtdqf5AAgqDFmR/aakqH3ChFdqd/QXJhS3rnnXFtexU7rax6Q==" + }, + "enhanced-resolve@5.20.1": { + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", + "dependencies": [ + "graceful-fs", + "tapable" + ] + }, + "error-stack-parser-es@1.0.5": { + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==" + }, + "esbuild-wasm@0.25.12": { + "integrity": "sha512-rZqkjL3Y6FwLpSHzLnaEy8Ps6veCNo1kZa9EOfJvmWtBq5dJH4iVjfmOO6Mlkv9B0tt9WFPFmb/VxlgJOnueNg==", + "bin": true + }, + "esbuild@0.25.12": { + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.25.12", + "@esbuild/android-arm@0.25.12", + "@esbuild/android-arm64@0.25.12", + "@esbuild/android-x64@0.25.12", + "@esbuild/darwin-arm64@0.25.12", + "@esbuild/darwin-x64@0.25.12", + "@esbuild/freebsd-arm64@0.25.12", + "@esbuild/freebsd-x64@0.25.12", + "@esbuild/linux-arm@0.25.12", + "@esbuild/linux-arm64@0.25.12", + "@esbuild/linux-ia32@0.25.12", + "@esbuild/linux-loong64@0.25.12", + "@esbuild/linux-mips64el@0.25.12", + "@esbuild/linux-ppc64@0.25.12", + "@esbuild/linux-riscv64@0.25.12", + "@esbuild/linux-s390x@0.25.12", + "@esbuild/linux-x64@0.25.12", + "@esbuild/netbsd-arm64@0.25.12", + "@esbuild/netbsd-x64@0.25.12", + "@esbuild/openbsd-arm64@0.25.12", + "@esbuild/openbsd-x64@0.25.12", + "@esbuild/openharmony-arm64@0.25.12", + "@esbuild/sunos-x64@0.25.12", + "@esbuild/win32-arm64@0.25.12", + "@esbuild/win32-ia32@0.25.12", + "@esbuild/win32-x64@0.25.12" + ], + "scripts": true, + "bin": true + }, + "esbuild@0.25.7": { + "integrity": "sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.25.7", + "@esbuild/android-arm@0.25.7", + "@esbuild/android-arm64@0.25.7", + "@esbuild/android-x64@0.25.7", + "@esbuild/darwin-arm64@0.25.7", + "@esbuild/darwin-x64@0.25.7", + "@esbuild/freebsd-arm64@0.25.7", + "@esbuild/freebsd-x64@0.25.7", + "@esbuild/linux-arm@0.25.7", + "@esbuild/linux-arm64@0.25.7", + "@esbuild/linux-ia32@0.25.7", + "@esbuild/linux-loong64@0.25.7", + "@esbuild/linux-mips64el@0.25.7", + "@esbuild/linux-ppc64@0.25.7", + "@esbuild/linux-riscv64@0.25.7", + "@esbuild/linux-s390x@0.25.7", + "@esbuild/linux-x64@0.25.7", + "@esbuild/netbsd-arm64@0.25.7", + "@esbuild/netbsd-x64@0.25.7", + "@esbuild/openbsd-arm64@0.25.7", + "@esbuild/openbsd-x64@0.25.7", + "@esbuild/openharmony-arm64@0.25.7", + "@esbuild/sunos-x64@0.25.7", + "@esbuild/win32-arm64@0.25.7", + "@esbuild/win32-ia32@0.25.7", + "@esbuild/win32-x64@0.25.7" + ], + "scripts": true, + "bin": true + }, + "esbuild@0.27.3": { + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.27.3", + "@esbuild/android-arm@0.27.3", + "@esbuild/android-arm64@0.27.3", + "@esbuild/android-x64@0.27.3", + "@esbuild/darwin-arm64@0.27.3", + "@esbuild/darwin-x64@0.27.3", + "@esbuild/freebsd-arm64@0.27.3", + "@esbuild/freebsd-x64@0.27.3", + "@esbuild/linux-arm@0.27.3", + "@esbuild/linux-arm64@0.27.3", + "@esbuild/linux-ia32@0.27.3", + "@esbuild/linux-loong64@0.27.3", + "@esbuild/linux-mips64el@0.27.3", + "@esbuild/linux-ppc64@0.27.3", + "@esbuild/linux-riscv64@0.27.3", + "@esbuild/linux-s390x@0.27.3", + "@esbuild/linux-x64@0.27.3", + "@esbuild/netbsd-arm64@0.27.3", + "@esbuild/netbsd-x64@0.27.3", + "@esbuild/openbsd-arm64@0.27.3", + "@esbuild/openbsd-x64@0.27.3", + "@esbuild/openharmony-arm64@0.27.3", + "@esbuild/sunos-x64@0.27.3", + "@esbuild/win32-arm64@0.27.3", + "@esbuild/win32-ia32@0.27.3", + "@esbuild/win32-x64@0.27.3" + ], + "scripts": true, + "bin": true + }, + "escalade@3.2.0": { + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + "estree-walker@2.0.2": { + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "fdir@6.5.0_picomatch@4.0.4": { + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dependencies": [ + "picomatch@4.0.4" + ], + "optionalPeers": [ + "picomatch@4.0.4" + ] + }, + "fsevents@2.3.3": { + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "os": ["darwin"], + "scripts": true + }, + "gensync@1.0.0-beta.2": { + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "graceful-fs@4.2.11": { + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "jiti@2.6.1": { + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "bin": true + }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsesc@3.1.0": { + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": true + }, + "json5@2.2.3": { + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": true + }, + "kleur@4.1.5": { + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" + }, + "lightningcss-android-arm64@1.32.0": { + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "os": ["android"], + "cpu": ["arm64"] + }, + "lightningcss-darwin-arm64@1.32.0": { + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "lightningcss-darwin-x64@1.32.0": { + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "lightningcss-freebsd-x64@1.32.0": { + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "lightningcss-linux-arm-gnueabihf@1.32.0": { + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "lightningcss-linux-arm64-gnu@1.32.0": { + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "lightningcss-linux-arm64-musl@1.32.0": { + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "lightningcss-linux-x64-gnu@1.32.0": { + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "lightningcss-linux-x64-musl@1.32.0": { + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "lightningcss-win32-arm64-msvc@1.32.0": { + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "lightningcss-win32-x64-msvc@1.32.0": { + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "os": ["win32"], + "cpu": ["x64"] + }, + "lightningcss@1.32.0": { + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dependencies": [ + "detect-libc" + ], + "optionalDependencies": [ + "lightningcss-android-arm64", + "lightningcss-darwin-arm64", + "lightningcss-darwin-x64", + "lightningcss-freebsd-x64", + "lightningcss-linux-arm-gnueabihf", + "lightningcss-linux-arm64-gnu", + "lightningcss-linux-arm64-musl", + "lightningcss-linux-x64-gnu", + "lightningcss-linux-x64-musl", + "lightningcss-win32-arm64-msvc", + "lightningcss-win32-x64-msvc" + ] + }, + "lru-cache@5.1.1": { + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": [ + "yallist" + ] + }, + "magic-string@0.30.21": { + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": [ + "@jridgewell/sourcemap-codec" + ] + }, + "miniflare@4.20260409.0": { + "integrity": "sha512-ayl6To4av0YuXsSivGgWLj+Ug8xZ0Qz3sGV8+Ok2LhNVl6m8m5ktEBM3LX9iT9MtLZRJwBlJrKcraNs/DlZQfA==", + "dependencies": [ + "@cspotcode/source-map-support", + "sharp", + "undici", + "workerd", + "ws", + "youch" + ], + "bin": true + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "nanoid@3.3.11": { + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "bin": true + }, + "node-releases@2.0.37": { + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==" + }, + "path-to-regexp@6.3.0": { + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + }, + "pathe@2.0.3": { + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, + "picocolors@1.1.1": { + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch@2.3.2": { + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==" + }, + "picomatch@4.0.4": { + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==" + }, + "postcss@8.5.6": { + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dependencies": [ + "nanoid", + "picocolors", + "source-map-js" + ] + }, + "preact-render-to-string@6.6.7_preact@10.29.1": { + "integrity": "sha512-3XdbsX3+vn9dQW+jJI/FsI9rlkgl6dbeUpqLsChak6jp3j3auFqBCkno7VChbMFs5Q8ylBj6DrUkKRwtVN3nvw==", + "dependencies": [ + "preact" + ] + }, + "preact@10.29.1": { + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==" + }, + "rollup@4.60.1": { + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dependencies": [ + "@types/estree" + ], + "optionalDependencies": [ + "@rollup/rollup-android-arm-eabi", + "@rollup/rollup-android-arm64", + "@rollup/rollup-darwin-arm64", + "@rollup/rollup-darwin-x64", + "@rollup/rollup-freebsd-arm64", + "@rollup/rollup-freebsd-x64", + "@rollup/rollup-linux-arm-gnueabihf", + "@rollup/rollup-linux-arm-musleabihf", + "@rollup/rollup-linux-arm64-gnu", + "@rollup/rollup-linux-arm64-musl", + "@rollup/rollup-linux-loong64-gnu", + "@rollup/rollup-linux-loong64-musl", + "@rollup/rollup-linux-ppc64-gnu", + "@rollup/rollup-linux-ppc64-musl", + "@rollup/rollup-linux-riscv64-gnu", + "@rollup/rollup-linux-riscv64-musl", + "@rollup/rollup-linux-s390x-gnu", + "@rollup/rollup-linux-x64-gnu", + "@rollup/rollup-linux-x64-musl", + "@rollup/rollup-openbsd-x64", + "@rollup/rollup-openharmony-arm64", + "@rollup/rollup-win32-arm64-msvc", + "@rollup/rollup-win32-ia32-msvc", + "@rollup/rollup-win32-x64-gnu", + "@rollup/rollup-win32-x64-msvc", + "fsevents" + ], + "bin": true + }, + "semver@6.3.1": { + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": true + }, + "semver@7.7.4": { + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "bin": true + }, + "sharp@0.34.5": { + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dependencies": [ + "@img/colour", + "detect-libc", + "semver@7.7.4" + ], + "optionalDependencies": [ + "@img/sharp-darwin-arm64", + "@img/sharp-darwin-x64", + "@img/sharp-libvips-darwin-arm64", + "@img/sharp-libvips-darwin-x64", + "@img/sharp-libvips-linux-arm", + "@img/sharp-libvips-linux-arm64", + "@img/sharp-libvips-linux-ppc64", + "@img/sharp-libvips-linux-riscv64", + "@img/sharp-libvips-linux-s390x", + "@img/sharp-libvips-linux-x64", + "@img/sharp-libvips-linuxmusl-arm64", + "@img/sharp-libvips-linuxmusl-x64", + "@img/sharp-linux-arm", + "@img/sharp-linux-arm64", + "@img/sharp-linux-ppc64", + "@img/sharp-linux-riscv64", + "@img/sharp-linux-s390x", + "@img/sharp-linux-x64", + "@img/sharp-linuxmusl-arm64", + "@img/sharp-linuxmusl-x64", + "@img/sharp-wasm32", + "@img/sharp-win32-arm64", + "@img/sharp-win32-ia32", + "@img/sharp-win32-x64" + ], + "scripts": true + }, + "source-map-js@1.2.1": { + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "supports-color@10.2.2": { + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==" + }, + "tailwindcss@4.2.2": { + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==" + }, + "tapable@2.3.2": { + "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==" + }, + "tinyglobby@0.2.16_picomatch@4.0.4": { + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dependencies": [ + "fdir", + "picomatch@4.0.4" + ] + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "undici@7.24.4": { + "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==" + }, + "unenv@2.0.0-rc.24": { + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dependencies": [ + "pathe" + ] + }, + "update-browserslist-db@1.2.3_browserslist@4.28.2": { + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dependencies": [ + "browserslist", + "escalade", + "picocolors" + ], + "bin": true + }, + "vite@7.3.2_picomatch@4.0.4": { + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "dependencies": [ + "esbuild@0.27.3", + "fdir", + "picomatch@4.0.4", + "postcss", + "rollup", + "tinyglobby" + ], + "optionalDependencies": [ + "fsevents" + ], + "bin": true + }, + "workerd@1.20260409.1": { + "integrity": "sha512-kuWP20fAaqaLBqLbvUfY9nCF6c3C78L60G9lS6eVwBf+v8trVFIsAdLB/FtrnKm7vgVvpDzvFAfB80VIiVj95w==", + "optionalDependencies": [ + "@cloudflare/workerd-darwin-64", + "@cloudflare/workerd-darwin-arm64", + "@cloudflare/workerd-linux-64", + "@cloudflare/workerd-linux-arm64", + "@cloudflare/workerd-windows-64" + ], + "scripts": true, + "bin": true + }, + "wrangler@4.81.1_unenv@2.0.0-rc.24_workerd@1.20260409.1": { + "integrity": "sha512-fppPXi+W2KJ5bx1zxdUYe1e7CHj5cWPFVBPXy8hSMZhrHeIojMe3ozAktAOw1voVuQjXzbZJf/GVKyVeSjbF8w==", + "dependencies": [ + "@cloudflare/kv-asset-handler", + "@cloudflare/unenv-preset", + "blake3-wasm", + "esbuild@0.27.3", + "miniflare", + "path-to-regexp", + "unenv", + "workerd" + ], + "optionalDependencies": [ + "fsevents" + ], + "bin": true + }, + "ws@8.18.0": { + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" + }, + "yallist@3.1.1": { + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "youch-core@0.3.3": { + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dependencies": [ + "@poppinss/exception", + "error-stack-parser-es" + ] + }, + "youch@4.1.0-beta.10": { + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dependencies": [ + "@poppinss/colors", + "@poppinss/dumper", + "@speed-highlight/core", + "cookie", + "youch-core" + ] + } + }, + "remote": { + "https://esm.sh/preact@10.22.0/hooks": "8a1ea3148ef7373b9c3dc027a147ff6728a4e53e10e3506c1191b087f0e564e1", + "https://esm.sh/preact@10.22.0/jsx-runtime": "6c6117abd414386ed23785f7c198e03bee696c1fa0fee01b72a64abe5e7ae7fb" + }, + "workspace": { + "dependencies": [ + "jsr:@fresh/core@^2.2.2", + "jsr:@fresh/plugin-tailwind@1", + "jsr:@fresh/plugin-vite@^1.0.8", + "npm:@preact/signals@^2.7.1", + "npm:preact@^10.28.3", + "npm:vite@7.3.2" + ], + "packageJson": { + "dependencies": [ + "npm:@tailwindcss/vite@^4.2.2", + "npm:wrangler@4.81.1" + ] + } + } +} diff --git a/dev.ts b/dev.ts deleted file mode 100755 index ae73946..0000000 --- a/dev.ts +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env -S deno run -A --watch=static/,routes/ - -import dev from "$fresh/dev.ts"; -import config from "./fresh.config.ts"; - -import "$std/dotenv/load.ts"; - -await dev(import.meta.url, "./main.ts", config); diff --git a/fresh.config.ts b/fresh.config.ts deleted file mode 100644 index f50b17a..0000000 --- a/fresh.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from "$fresh/server.ts"; -import tailwind from "$fresh/plugins/tailwind.ts"; - -export default defineConfig({ - plugins: [tailwind()], -}); diff --git a/fresh.gen.ts b/fresh.gen.ts deleted file mode 100644 index 5c2bc71..0000000 --- a/fresh.gen.ts +++ /dev/null @@ -1,29 +0,0 @@ -// DO NOT EDIT. This file is generated by Fresh. -// This file SHOULD be checked into source version control. -// This file is automatically updated during development when running `dev.ts`. - -import * as $_lang_index from "./routes/[lang]/index.tsx"; -import * as $_404 from "./routes/_404.tsx"; -import * as $_app from "./routes/_app.tsx"; -import * as $index from "./routes/index.tsx"; -import * as $AnchorLang from "./islands/AnchorLang.tsx"; -import * as $ButtonPrint from "./islands/ButtonPrint.tsx"; -import * as $DarkMode from "./islands/DarkMode.tsx"; -import type { Manifest } from "$fresh/server.ts"; - -const manifest = { - routes: { - "./routes/[lang]/index.tsx": $_lang_index, - "./routes/_404.tsx": $_404, - "./routes/_app.tsx": $_app, - "./routes/index.tsx": $index, - }, - islands: { - "./islands/AnchorLang.tsx": $AnchorLang, - "./islands/ButtonPrint.tsx": $ButtonPrint, - "./islands/DarkMode.tsx": $DarkMode, - }, - baseUrl: import.meta.url, -} satisfies Manifest; - -export default manifest; diff --git a/main.ts b/main.ts index 675f529..441ec91 100644 --- a/main.ts +++ b/main.ts @@ -1,13 +1,31 @@ -/// -/// -/// -/// -/// +import { App, staticFiles, trailingSlashes } from "fresh"; +import { getLanguages } from "@/utils/global.ts"; +import { t } from "@/utils/i18n.ts"; +import type { FreshContext } from "fresh"; +import type { State } from "@/utils.ts"; -import "$std/dotenv/load.ts"; +// Middleware para inyectar lang, translations y languages en ctx.state +function i18nMiddleware(ctx: FreshContext) { + const url = new URL(ctx.url); + const lang = url.pathname.split("/")[1] || "es"; + const translations = t(lang); + const languages = getLanguages(); -import { start } from "$fresh/server.ts"; -import manifest from "./fresh.gen.ts"; -import config from "./fresh.config.ts"; + // Mutar el state directamente (ctx.state es un objeto mutable) + Object.assign(ctx.state, { + data: { languages }, + lang, + translations, + }); -await start(manifest, config); + return ctx.next(); +} + +export const app = new App() + // i18n middleware DEBE ir primero + .use(i18nMiddleware) + // Add static file serving middleware + .use(staticFiles()) + .use(trailingSlashes("never")) + // Enable file-system based routing + .fsRoutes(); diff --git a/package.json b/package.json index 8888386..83b34db 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ "scripts": { "deploy": "wrangler deploy" }, + "dependencies": { + "@tailwindcss/vite": "^4.2.2" + }, "devDependencies": { - "wrangler": "4.80.0" + "wrangler": "4.81.1" } } diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index c2ddf74..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - plugins: { - "@tailwindcss/postcss": {}, - }, -}; diff --git a/routes/[lang]/index.tsx b/routes/[lang]/index.tsx index e87d7c2..b9bb607 100644 --- a/routes/[lang]/index.tsx +++ b/routes/[lang]/index.tsx @@ -1,34 +1,14 @@ -import { Handlers, PageProps } from "$fresh/server.ts"; -import { Fragment } from "preact"; -import Footer from "../../components/Footer.tsx"; -import Header from "../../components/Header.tsx"; -import SectionWrapperContent from "../../components/SectionWrapperContent.tsx"; -import WrapperPage from "../../components/WrapperPage.tsx"; -import AnchorLang from "../../islands/AnchorLang.tsx"; -import translations from "../../locales/es.json" with { type: "json" }; -import { getLanguages } from "../../utils/global.ts"; +import Footer from "@/components/Footer.tsx"; +import Header from "@/components/Header.tsx"; +import SectionWrapperContent from "@/components/SectionWrapperContent.tsx"; +import WrapperPage from "@/components/WrapperPage.tsx"; +import AnchorLang from "@/islands/AnchorLang.tsx"; +import { define } from "@/utils.ts"; -interface MiddlewareState { - lang: string; - translations: typeof translations; -} - -interface Data { - languages: string[]; -} - -export const handler: Handlers = { - async GET(_, ctx) { - const languages = await getLanguages(); // Obtén los lenguajes en el servidor - return ctx.render({ languages }); - }, -}; - -export default function Home( - { state, data }: PageProps, -) { +export default define.page(function Home({ state }) { const { lang, translations } = state; - const { languages } = data; + const { languages } = state.data; + return ( <>
@@ -41,8 +21,8 @@ export default function Home(
- {translations.index.sections.map((section) => ( - + {translations.index.sections.map((section, sectionIdx) => ( +

{section.title}

@@ -59,7 +39,7 @@ export default function Home( ))} - +
))}
@@ -69,4 +49,4 @@ export default function Home( ); -} +}); diff --git a/routes/_app.tsx b/routes/_app.tsx index 97b04b4..67391c9 100644 --- a/routes/_app.tsx +++ b/routes/_app.tsx @@ -1,33 +1,49 @@ -import { FreshContext } from "$fresh/server.ts"; -import translations from "../locales/es.json" with { type: "json" }; -import { t } from "../utils/i18n.ts"; +import { define } from "@/utils.ts"; +import { asset } from "fresh/runtime"; + +export default define.page(function App({ Component, state }) { + // El state ya viene inyectado por el middleware en main.ts + const { lang, translations } = state; -interface State { - lang: string; - translations: typeof translations; -} -export default function App( - req: Request, - ctx: FreshContext, -) { - const url = new URL(req.url); - const lang = url.pathname.split("/")[1] || "es"; - const translations = t(lang); - ctx.state.lang = lang; - ctx.state.translations = translations; return ( - + {translations?.site?.title || "Vibe Coding - Idioma no encontrado"} + + {/* */} + + + + + {/* */} + + + - + {/* @ts-ignore - Fresh 2 Component type compatibility */} + ); -} +}); diff --git a/routes/index.tsx b/routes/index.tsx index 12a72c0..c8863f6 100644 --- a/routes/index.tsx +++ b/routes/index.tsx @@ -1,33 +1,14 @@ -import { Handlers, PageProps } from "$fresh/server.ts"; -import Footer from "../components/Footer.tsx"; -import Header from "../components/Header.tsx"; -import SectionWrapperContent from "../components/SectionWrapperContent.tsx"; -import WrapperPage from "../components/WrapperPage.tsx"; -import AnchorLang from "../islands/AnchorLang.tsx"; -import translations from "../locales/es.json" with { type: "json" }; -import { getLanguages } from "../utils/global.ts"; +import Footer from "@/components/Footer.tsx"; +import Header from "@/components/Header.tsx"; +import SectionWrapperContent from "@/components/SectionWrapperContent.tsx"; +import WrapperPage from "@/components/WrapperPage.tsx"; +import AnchorLang from "@/islands/AnchorLang.tsx"; +import { define } from "@/utils.ts"; -interface MiddlewareState { - lang: string; - translations: typeof translations; -} - -interface Data { - languages: string[]; -} - -export const handler: Handlers = { - async GET(_, ctx) { - const languages = await getLanguages(); // Obtén los lenguajes en el servidor - return ctx.render({ languages }); - }, -}; - -export default function Home( - { state, data }: PageProps, -) { +export default define.page(function Home({ state }) { const { lang, translations } = state; - const { languages } = data; + const { languages } = state.data; + return ( <>
@@ -38,7 +19,7 @@ export default function Home( {translations.index.header} - +
{translations.index.sections.map((section) => ( <> @@ -68,4 +49,4 @@ export default function Home( ); -} +}); diff --git a/server.ts b/server.ts deleted file mode 100644 index 5f50a49..0000000 --- a/server.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// -/// -/// -/// -/// - -import { ServerContext } from "$fresh/server.ts"; -import config from "./fresh.config.ts"; -import manifest from "./fresh.gen.ts"; - -const ctx = await ServerContext.fromManifest(manifest, config); - -export default { - fetch: ctx.handler(), -}; diff --git a/tailwind.config.ts b/tailwind.config.ts deleted file mode 100644 index 5ac6507..0000000 --- a/tailwind.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { type Config } from "tailwindcss"; - -export default { - content: [ - "{routes,islands,components,locales}/**/*.{ts,tsx,js,jsx,json}", - ], - darkMode: "class", // Enables dark mode using the "class" strategy - theme: { - extend: { - fontFamily: { - sans: ["Inter var", "system-ui", "sans-serif"], - "roboto-mono": ["roboto-mono", "monospace"], - }, - }, - }, -} satisfies Config; diff --git a/utils.ts b/utils.ts new file mode 100644 index 0000000..5e7e9ae --- /dev/null +++ b/utils.ts @@ -0,0 +1,19 @@ +import type { t } from "@/utils/i18n.ts"; +import { createDefine } from "fresh"; + +interface Data { + languages: string[]; +} + +// Tipo de retorno de la función t() +type Translations = ReturnType; + +// This specifies the type of "ctx.state" which is used to share +// data among middlewares, layouts and routes. +export interface State { + data: Data; + lang: string; + translations: Translations; +} + +export const define = createDefine(); diff --git a/utils/global.ts b/utils/global.ts index 4ddaaec..6de6cfb 100644 --- a/utils/global.ts +++ b/utils/global.ts @@ -1,11 +1,5 @@ -export const getLanguages = async () => { - const locales = []; - const files = Deno.readDir("./locales"); - for await (const file of files) { - if (file.isFile && file.name.endsWith(".json")) { - const lang = file.name.split(".")[0]; - locales.push(lang); - } - } - return locales; +// Compatible con Cloudflare Workers - sin filesystem +// Los idiomas disponibles están hardcodeados basados en los archivos en /locales +export const getLanguages = (): string[] => { + return ["es", "en"]; }; diff --git a/utils/i18n.ts b/utils/i18n.ts index 1d296dd..7adddb4 100644 --- a/utils/i18n.ts +++ b/utils/i18n.ts @@ -1,5 +1,5 @@ -import translationsEs from "../locales/es.json" with { type: "json" }; -import translationsEn from "../locales/en.json" with { type: "json" }; +import translationsEn from "@/locales/en.json" with { type: "json" }; +import translationsEs from "@/locales/es.json" with { type: "json" }; type Translations = typeof translationsEs; diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..0156a71 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { fresh } from "@fresh/plugin-vite"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [ + fresh(), + tailwindcss(), + ], +}); diff --git a/wrangler.jsonc b/wrangler.jsonc index 3661e9c..4c67431 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -5,7 +5,7 @@ "main": "./main.ts", "assets": { "binding": "ASSETS", - "directory": "./static" + "directory": "./assets" }, "routes": [ { From b9bd9c4909a164fb30a79fde45edac72c738f180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:27:39 -0400 Subject: [PATCH 11/24] fix: download Roboto Mono font file for proper loading The font file was empty (0 bytes placeholder). Downloaded actual Roboto Mono 500 weight from Google Fonts (12 KB woff2 format). Font now loads correctly in browser at /fonts/roboto-mono-latin-500-normal.woff --- static/fonts/roboto-mono-latin-500-normal.woff | Bin 0 -> 12764 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/static/fonts/roboto-mono-latin-500-normal.woff b/static/fonts/roboto-mono-latin-500-normal.woff index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..53d081f3a538a63578c15a5cc11219b32e6d5795 100644 GIT binary patch literal 12764 zcmV<2F(b}*Pew8T0RR9105RME4gdfE09y0_05O380RR9100000000000000000000 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 literal 0 HcmV?d00001 From ca496153d5e4e7f55294df84d1bbdaa6c0c7def6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:27:52 -0400 Subject: [PATCH 12/24] feat: add i18n support to 404 error page Rename 404.tsx to _404.tsx for Fresh 2 compatibility. Add bilingual error messages (Spanish/English) based on lang state. Page now responds correctly to /es and /en language routes. --- routes/_404.tsx | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/routes/_404.tsx b/routes/_404.tsx index 4bff0f3..f1da6cf 100644 --- a/routes/_404.tsx +++ b/routes/_404.tsx @@ -1,31 +1,32 @@ -import { Head } from "$fresh/runtime.ts"; -import { PageProps } from "$fresh/server.ts"; -export default function Error404(_props: PageProps<{ message: string }>) { +import { define } from "@/utils.ts"; + +export default define.page(function Error404({ state }) { + const { lang } = state; + return ( <> - - 404 - ¡Creo que andas perdido! -

Wow 🧉{" "} - ¡Creo que andas perdido! + {lang === "en" + ? "I think you're lost!" + : "¡Creo que andas perdido!"}

- Regresar a Vibe Coding + {lang === "en" ? "Back to Vibe Coding" : "Regresar a Vibe Coding"} - ir al repositorio + {lang === "en" ? "Go to repository" : "ir al repositorio"}
); -} +}); From c26153474703b107094ef7ed7e24a835db764bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:37:30 -0400 Subject: [PATCH 13/24] chore: add .wrangler/ to .gitignore for internal tracking --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 579b201..897f906 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ node_modules/ # Husky (archivos internos - no trackear) .husky/_ + +# Wrangler (archivos internos - no trackear) +.wrangler/ \ No newline at end of file From d774a77f89e185c3cd14605bb37acb52031b5671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:39:25 -0400 Subject: [PATCH 14/24] feat: upgrade dependencies and restructure project files for improved compatibility --- deno.lock | 17 +++++++++++++++-- package.json | 7 +++---- server.js | 3 +++ vite.config.ts | 7 +++++++ wrangler.jsonc | 4 ++-- 5 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 server.js diff --git a/deno.lock b/deno.lock index 9c50417..014bc92 100644 --- a/deno.lock +++ b/deno.lock @@ -30,6 +30,7 @@ "jsr:@std/uuid@^1.0.9": "1.1.0", "npm:@babel/core@^7.28.0": "7.29.0", "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0", + "npm:@cloudflare/vite-plugin@^1.31.2": "1.31.2_vite@7.3.2__picomatch@4.0.4_wrangler@4.81.1__unenv@2.0.0-rc.24__workerd@1.20260409.1_unenv@2.0.0-rc.24", "npm:@mjackson/node-fetch-server@0.7": "0.7.0", "npm:@opentelemetry/api@^1.9.0": "1.9.1", "npm:@preact/signals@^2.5.1": "2.9.0_preact@10.29.1", @@ -47,7 +48,7 @@ "npm:rollup@^4.50.0": "4.60.1", "npm:vite@7.3.2": "7.3.2_picomatch@4.0.4", "npm:vite@^7.1.4": "7.3.2_picomatch@4.0.4", - "npm:wrangler@4.81.1": "4.81.1_unenv@2.0.0-rc.24_workerd@1.20260409.1" + "npm:wrangler@^4.81.1": "4.81.1_unenv@2.0.0-rc.24_workerd@1.20260409.1" }, "jsr": { "@deno/esbuild-plugin@1.2.1": { @@ -372,6 +373,17 @@ "workerd" ] }, + "@cloudflare/vite-plugin@1.31.2_vite@7.3.2__picomatch@4.0.4_wrangler@4.81.1__unenv@2.0.0-rc.24__workerd@1.20260409.1_unenv@2.0.0-rc.24": { + "integrity": "sha512-6RyoPhqmpuHPB+Zudt7mOUdGzB1+DQtJtPdAxUajhlS2ZUU0+bCn9Cj4g6Z2EvajBrkBTw1yVLqtt4bsUnp1Ng==", + "dependencies": [ + "@cloudflare/unenv-preset", + "miniflare", + "unenv", + "vite", + "wrangler", + "ws" + ] + }, "@cloudflare/workerd-darwin-64@1.20260409.1": { "integrity": "sha512-h/bkaC0HJL63aqAGnV0oagqpBiTSstabODThkeMSbG8kctl0Jb4jlq1pNHJPmYGazFNtfyagrUZFb6HN22GX7w==", "os": ["darwin"], @@ -1830,8 +1842,9 @@ ], "packageJson": { "dependencies": [ + "npm:@cloudflare/vite-plugin@^1.31.2", "npm:@tailwindcss/vite@^4.2.2", - "npm:wrangler@4.81.1" + "npm:wrangler@^4.81.1" ] } } diff --git a/package.json b/package.json index 83b34db..d27b256 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,8 @@ "deploy": "wrangler deploy" }, "dependencies": { - "@tailwindcss/vite": "^4.2.2" - }, - "devDependencies": { - "wrangler": "4.81.1" + "@cloudflare/vite-plugin": "^1.31.2", + "@tailwindcss/vite": "^4.2.2", + "wrangler": "^4.81.1" } } diff --git a/server.js b/server.js new file mode 100644 index 0000000..915ba56 --- /dev/null +++ b/server.js @@ -0,0 +1,3 @@ +import server from "./_fresh/server/server-entry.js"; + +export default server; diff --git a/vite.config.ts b/vite.config.ts index 0156a71..fbc10c7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,4 +7,11 @@ export default defineConfig({ fresh(), tailwindcss(), ], + build: { + rollupOptions: { + output: { + inlineDynamicImports: true, + }, + }, + }, }); diff --git a/wrangler.jsonc b/wrangler.jsonc index 4c67431..f3f7e6a 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -2,10 +2,10 @@ "name": "vibe-coding", "compatibility_date": "2026-03-29", "compatibility_flags": ["nodejs_compat"], - "main": "./main.ts", + "main": "./server.js", "assets": { "binding": "ASSETS", - "directory": "./assets" + "directory": "./_fresh/client" }, "routes": [ { From 23a97fae064b600058c90f3f8aef746ae3189e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Espinoza?= Date: Mon, 13 Apr 2026 01:50:12 -0400 Subject: [PATCH 15/24] fix: update button class for improved hover effect in DarkMode component --- islands/DarkMode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/islands/DarkMode.tsx b/islands/DarkMode.tsx index 5952d44..4ebc94a 100644 --- a/islands/DarkMode.tsx +++ b/islands/DarkMode.tsx @@ -32,7 +32,7 @@ const DarkMode = () => {