diff --git a/.gitignore b/.gitignore index 5286546..566bf70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,28 @@ -public -resources +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Hugo/Vite output directory +public/ +resources/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.gitmodules b/.gitmodules index c1c6bed..831300d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "content/wiki/adm.wiki"] path = content/wiki/adm.wiki - url = git@git.students.cs.unibo.it:adm/adm.wiki.git -[submodule "themes/website-theme"] - path = themes/website-theme - url = https://git.students.cs.unibo.it/adm/website-theme + url = git@git.students.cs.unibo.it:adm/adm.wiki.git \ No newline at end of file diff --git a/.hugo_build.lock b/.hugo_build.lock deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 0776ce6..7b856e1 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,72 @@ -# ADMStaff website: https://students.cs.unibo.it +# ADMStaff website -To contribute to the website, you can edit the markdown files in the `content` directory. +https://students.cs.unibo.it -Firstly, you need to install [Hugo](https://gohugo.io/getting-started/installing/). -Next, once you have cloned the repo, you need to: +This project uses Vue.js. -## 1. Install submodules +## Content + +The site content lives in [content](content). Markdown files are used directly by the site, while [archetypes](archetypes) contains the Hugo-style templates used to create new content consistently. + +Create a new page from the archetype with: ```bash -git submodule init && git submodule update +pnpm new-content events/my_new_event ``` -## 2. Format the Wiki -Use this command to compile the wiki into hugo format: -> Note: Do not push any changes on the adm-wiki submodule +The command creates `content/events/my_new_event.md` and fills front matter defaults: + +- `title`: derived from the file name. +- `date`: current local timestamp with timezone. +- `author`: `ADMStaff`. + +Any kind of attachment (images, PDFs, etc.) can be placed in `static/img`, and referenced in markdown with `/img/filename.ext`. + +Optional overrides: + ```bash -python3 format_wiki.py +pnpm new-content content/projects/my_tool.md --title "My Tool" --date "2026-04-14T10:00:00+02:00" --author "ADMStaff" ``` -## 3. Compile the Website +## Commands + ```bash -hugo +pnpm install +pnpm dev +pnpm build +pnpm preview +pnpm new-content events/my_new_event +pnpm format ``` -For local hosting +- `pnpm dev`: starts the local development server. +- `pnpm build`: creates the production build and generates OG images. +- `pnpm preview`: previews the generated build locally. +- `pnpm new-content`: creates a new Markdown file in `content/` from `archetypes/default.md`. +- `pnpm format`: formats the project code and markdown files. + +## Wiki + +The wiki is a git submodule in `content/wiki/adm.wiki`. + +To sync it: + ```bash -hugo server -``` \ No newline at end of file +git submodule update --init --recursive +cd content/wiki/adm.wiki +git pull +cd ../../.. +python format_wiki.py +``` + +The `format_wiki.py` script adapts the wiki files to the format used by the site. + +## Deploy + +Deployment starts from the local build: + +```bash +pnpm build +``` + +The build generates the `dist` folder, which contains the static files to publish. diff --git a/archetypes/default.md b/archetypes/default.md index 9856711..49cd31d 100644 --- a/archetypes/default.md +++ b/archetypes/default.md @@ -1,8 +1,9 @@ --- title: '{{ replace .File.ContentBaseName "-" " " | title }}' -date: {{ .Date }} -author: 'ADMStaff' +date: { { .Date } } +author: "ADMStaff" toc: false framed: false # cover: +# link: # per i progetti --- diff --git a/content/about.md b/content/about.md index f0abf3e..0733d4d 100644 --- a/content/about.md +++ b/content/about.md @@ -1,11 +1,8 @@ --- -title: 'Chi siamo' +title: "Chi siamo" toc: false -# cover: 'img/ADMstaff_logo-modern-trasp.png' --- -{{< figure src="/img/ADMstaff_logo-modern.png" title="ADMstaff logo" style="width: 40%;" >}} - ADMStaff è un gruppo di studenti del Dipartimento di Informatica dell'Università di Bologna, che sperimenta e approfondisce sistemi operativi e la gestione di infrastrutture IT. Dal 1994, guidati dal Prof. Renzo Davoli, portiamo avanti una tradizione: **servizi gestiti da studenti, per studenti**. Tutti i servizi che offriamo sono _open source_ e nati dalla passione e dall'impegno dei nostri membri. ## Cosa facciamo @@ -15,20 +12,21 @@ Il nostro obiettivo è sperimentare e mettere in pratica ciò che ci appassiona: L'università ci fornisce uno spazio fisico in via Mura Anteo Zamboni 7, IP pubblici e un dominio dedicato dove possiamo lavorare e sperimentare "senza limiti". In particolare, offriamo: + - **Wiki ADM**: La nostra documentazione tecnica e le guide per utilizzare i nostri servizi. [Visita il Wiki](/wiki/adm.wiki/) -- **Servizi di hosting**: Offriamo hosting web, database e altri servizi per progetti studenteschi e personali. +- **Servizi di hosting**: Offriamo hosting web, database e altri servizi per progetti studenteschi e personali. - **sasso**: Un servizio di VPS per studenti e membri del dipartimento. [Scopri di più su sasso](https://sasso.students.cs.unibo.it) - **Laboratori fra pari**: Labortori aperti agli studenti in cui li guidiamo nell'apprendimenti di strumenti come: Shell, Vim, Git, GitHub, CI/CD. [Tutti i materiali usati sono disponibili qui](https://github.com/cartabinaria/lab) - **Linux Installation Party**: Eventi periodici in cui aiutiamo gli studenti a installare Linux sui loro computer personali. - ## Cosa usiamo per gestire la nostra infrastruttura -Utilizziamo tecnologie open source come Linux, Proxmox, Docker, Ansible, Git/Forgejo, PostgreSQL, Caddy, ZFS, TrueNAS, Netbox. Questi strumenti ci permettono di costruire e mantenere un'infrastruttura solida e scalabile, imparando continuamente nuove competenze. - +Utilizziamo tecnologie open source come Linux, Proxmox, Docker, Ansible, Git/Forgejo, PostgreSQL, Caddy, ZFS, TrueNAS, Netbox. Questi strumenti ci permettono di costruire e mantenere un'infrastruttura solida e scalabile, imparando continuamente nuove competenze. ## Unisciti a noi Cerchiamo studenti curiosi e motivati. Non importa il livello di esperienza: conta la voglia di imparare e mettersi in gioco. Passa a trovarci in laboratorio o scopri i nostri [eventi](/events). Se sei interessato scrivici su Telegram [t.me/admstaff_Chat](https://t.me/admstaff_Chat) + +![ADM 2024](/img/team2024.jpg) diff --git a/content/en/about.md b/content/en/about.md index 5e19f95..c9dde47 100644 --- a/content/en/about.md +++ b/content/en/about.md @@ -1,12 +1,9 @@ --- -title: 'Who are we?' +title: "Who are we?" toc: false # cover: 'img/ADMstaff_logo-modern-trasp.png' --- -{{< figure src="/img/ADMstaff_logo-modern.png" title="ADMstaff logo" style="width: 40%;" >}} - - ADMStaff is a group of students from the Department of Computer Science at the University of Bologna. We experiment with and deepen our knowledge of operating systems and IT infrastructure management. Since 1994, under the guidance of Prof. Renzo Davoli, we have carried on a tradition: **services run by students, for students**. All the services we provide are _open source_ and are driven by the passion and commitment of our members. ## What we do @@ -16,21 +13,21 @@ Our goal is to experiment with and put into practice what we love: system admini The university provides us with a physical space at Via Mura Anteo Zamboni 7, public IPs, and a dedicated domain where we can work and experiment “without limits”. In particular, we provide: + - **ADM Wiki**: Our technical documentation and guides for using our services. [Visit the Wiki](/wiki/adm.wiki/) - **Hosting services**: We offer web hosting, databases, and other services for student and personal projects. - **sasso**: A VPS service for students and department members. [Learn more about sasso](https://sasso.students.cs.unibo.it) - **Peer-to-peer workshops**: Workshops open to students where we help them learn tools such as Shell, Vim, Git, GitHub, and CI/CD. [All the materials used are available here](https://github.com/cartabinaria/lab) - **Linux Installation Party**: Periodic events where we help students install Linux on their personal computers. - ## What we use to run our infrastructure We use open-source technologies such as Linux, Proxmox, Docker, Ansible, Git/Forgejo, PostgreSQL, Caddy, ZFS, TrueNAS, and Netbox. These tools help us build and maintain a solid, scalable infrastructure while continuously learning new skills. - ## Join us We’re looking for curious and motivated students. Your experience level doesn’t matter: what counts is the desire to learn and get involved. Drop by the lab or check out our [events](/events). If you’re interested, write to us on Telegram: [t.me/admstaff_Chat](https://t.me/admstaff_Chat) +![ADM 2024](/img/team2024.jpg) diff --git a/content/events/_index.md b/content/events/_index.md index 8b8e78c..e2b54bc 100644 --- a/content/events/_index.md +++ b/content/events/_index.md @@ -1,8 +1,9 @@ --- -title: 'Laboratori fra pari' +title: "Laboratori fra pari" date: 2021-11-23T18:00:00+02:00 author: "Admstaff" framed: true toc: false --- -Per restare aggiornato entra nel [**gruppo telegram**](https://t.me/admstaff_Chat) \ No newline at end of file + +Per restare aggiornato entra nel [**gruppo telegram**](https://t.me/admstaff_Chat) diff --git a/content/events/cavalieri.md b/content/events/cavalieri.md index 2a159c0..83a9caf 100644 --- a/content/events/cavalieri.md +++ b/content/events/cavalieri.md @@ -1,23 +1,22 @@ --- -title: 'Giacomo Cavalieri @Unibo' +title: "Giacomo Cavalieri @Unibo" date: 2024-05-01T15:36:06+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/cavalieri.png --- -| Date and Time | Location | -| --- | --- | +| Date and Time | Location | +| ---------------------------------------------- | -------------------------------------------------------------------------------------------- | | mercoledì 8 maggio 2024 dalle 18:00 alle 19:30 | Aula Tonelli (sesto piano), Dipartimento di Matematica, Piazza di Porta S. Donato 5, Bologna | Te lo sei perso? Trovi la registrazione qui: https://media.students.cs.unibo.it/gleam.mp4 Titolo del seminario: **"Functional Programming in Gleam: what if best practices were the norm?"** -Abbiamo invitato per tenere un talk Giacomo Cavalieri, ex studente e tutor unibo e ora core team member di Gleam, un linguaggio di programmazione che ha da poco rilasciato la sua versione 1. +Abbiamo invitato per tenere un talk Giacomo Cavalieri, ex studente e tutor unibo e ora core team member di Gleam, un linguaggio di programmazione che ha da poco rilasciato la sua versione 1. Per altre info in più consigliamo: https://gleam.run/ https://github.com/giacomocavalieri - diff --git a/content/events/laboratori_2023.md b/content/events/laboratori_2023.md index 71496f3..63ff00b 100644 --- a/content/events/laboratori_2023.md +++ b/content/events/laboratori_2023.md @@ -7,6 +7,7 @@ draft: false --- Anche quest'anno con grande richiesta riproponiamo laboratori su: + - **Terminale Base**: impariamo a muoverci nel terminale, manipolare file/directory, gestire i permessi... - **Git 1 | comandi base**: impariamo a gestire i nostri progetti con Git, creare repository, fare commit... - **Git 2 | condivisione remota**: carichiamo le nostre repository su GitHub, collaboriamo con altri utenti, gestiamo i conflitti, issue, pull request. Approfondiremo come fare su GitHub tutte le operazioni base che abbiamo imparato a fare da terminale l'incontro precedente. @@ -15,10 +16,11 @@ Le date e luogo di svolgimento le trovate nella locandina sottostante. _**Disclaimer**_ Questi non sono corsi universitari, sono incontri/laboratori organizzati da studenti per studenti per imparare insieme e mettere mano da subito sugli argomenti trattati. + > È quindi fondamentale **portare il proprio PC** per riuscire a seguire gli esercizi proposti. ### Iscrizione richiesta per motivi organizzativi sul [typeform 'CSUnibo in Ascolto!'](https://lr533gb3hpt.typeform.com/to/m5fzNCsW) Per qualsiasi info o domande: [t.me/admstaff_Chat](https://t.me/admstaff_Chat) -![Prossimi laboratori fra pari](/img/ADM-Lab_Git_e_terminale.png) \ No newline at end of file +![Prossimi laboratori fra pari](/img/ADM-Lab_Git_e_terminale.png) diff --git a/content/events/laboratori_2024.md b/content/events/laboratori_2024.md index ada713a..85312e1 100644 --- a/content/events/laboratori_2024.md +++ b/content/events/laboratori_2024.md @@ -1,13 +1,14 @@ --- -title: 'Laboratori 2024' +title: "Laboratori 2024" date: 2024-10-01T09:48:38+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/laboratori-24.png --- Anche questo semestre con grande richiesta riproponiamo laboratori su: + - **Terminale base** _[15/10/2024]_: primi passi sulla shell - **Git 1 | comandi base** _[22/10/2024]_: impariamo a gestire i nostri progetti con Git, creare repository, fare commit... - **Git 2 | condivisione remota** _[05/11/2024]_: carichiamo le nostre repository su GitHub, collaboriamo con altri utenti, gestiamo i conflitti, issue, pull request. Approfondiremo come fare su GitHub tutte le operazioni base che abbiamo imparato a fare da terminale l'incontro precedente. @@ -20,7 +21,7 @@ Anche questo semestre con grande richiesta riproponiamo laboratori su: - variabili - gestione processi - scripting - ... + ... Gli incontri si terranno tutti dalle 17:00 alle 19:00 in Aula Bombelli (Dipartimento di Matematica, piazza Porta S. Donato 5). @@ -29,8 +30,9 @@ Posti disponibili per ogni incontro: 40 _**Disclaimer**_ Questi non sono corsi universitari, sono incontri/laboratori organizzati da studenti per studenti per imparare insieme e mettere mano da subito sugli argomenti trattati. + > È quindi fondamentale **portare il proprio PC** per riuscire a seguire gli esercizi proposti. Per qualsiasi info o domande: [t.me/admstaff_Chat](https://t.me/admstaff_Chat) -![img/laboratori-24-25-2.png](/img/laboratori-24-25-2.png) \ No newline at end of file +![img/laboratori-24-25-2.png](/img/laboratori-24-25-2.png) diff --git a/content/events/laboratori_2025.md b/content/events/laboratori_2025.md index c7a33ac..543bc66 100644 --- a/content/events/laboratori_2025.md +++ b/content/events/laboratori_2025.md @@ -1,14 +1,15 @@ --- -title: 'Laboratori 2025' +title: "Laboratori 2025" date: 2025-04-22T09:48:38+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/laboratori-25.png --- Anche questo semestre con grande richiesta riproponiamo laboratori su: -- **Git 1 | comandi base** _[08/05/2025]__: impariamo a gestire i nostri progetti con Git, creare repository, fare commit... + +- **Git 1 | comandi base** \_[08/05/2025]\_\_: impariamo a gestire i nostri progetti con Git, creare repository, fare commit... - **Git 2 | condivisione remota** _[15/05/2025]_: carichiamo le nostre repository su GitHub, collaboriamo con altri utenti, gestiamo i conflitti, issue, pull request. Approfondiremo come fare su GitHub tutte le operazioni base che abbiamo imparato a fare da terminale l'incontro precedente. - **GitHub | ci/cd** _[22/05/2025]_: impariamo a creare un workflow di CI/CD con GitHub Actions, per automatizzare i test e il deploy del nostro codice. @@ -18,8 +19,9 @@ Posti disponibili per ogni incontro: 40 _**Disclaimer**_ Questi non sono corsi universitari, sono incontri/laboratori organizzati da studenti per studenti per imparare insieme e mettere mano da subito sugli argomenti trattati. + > È quindi fondamentale **portare il proprio PC** per riuscire a seguire gli esercizi proposti. Per qualsiasi info o domande: [t.me/admstaff_Chat](https://t.me/admstaff_Chat) -![img/laboratori-25-vertical.png](/img/laboratori-25-vertical.png) \ No newline at end of file +![img/laboratori-25-vertical.png](/img/laboratori-25-vertical.png) diff --git a/content/events/laboratori_2026.md b/content/events/laboratori_2026.md index ad37d8d..2e10573 100644 --- a/content/events/laboratori_2026.md +++ b/content/events/laboratori_2026.md @@ -1,32 +1,31 @@ --- -title: 'Laboratori a.a. 2025/26' +title: "Laboratori a.a. 2025/26" date: 2025-10-16T09:48:38+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false -cover: img/laboratori-25-26.png +cover: img/laboratori-25-26.jpg --- Anche per l'anno accademico 2025/26 organizziamo i laboratori fra pari: degli incontri gratuiti, aperti a tutti gli studenti. Di seguito il calendario e una breve descrizione degli incontri: - **Terminale 1 — comandi base** (04/11/2025) - - Impariamo a muoverci nel filesystem, creare, spostare, copiare ed eliminare file e cartelle; uso dei comandi più comuni. + - Impariamo a muoverci nel filesystem, creare, spostare, copiare ed eliminare file e cartelle; uso dei comandi più comuni. - **Terminale 2 — redirezioni e pipe** (06/11/2025) - - Redirezioni per salvare l'output su file, concatenazione di comandi con pipe; introduzione a grep, find, xargs e affini. + - Redirezioni per salvare l'output su file, concatenazione di comandi con pipe; introduzione a grep, find, xargs e affini. - **Git 1 — comandi base** (13/11/2025) - - Gestione di progetti con Git: inizializzare repository, commit, branch di base. + - Gestione di progetti con Git: inizializzare repository, commit, branch di base. - **Git 2 — condivisione remota** (20/11/2025) - - Caricamento su GitHub, collaborazione remota e operazioni pratiche su GitHub rilevanti rispetto all'incontro precedente. + - Caricamento su GitHub, collaborazione remota e operazioni pratiche su GitHub rilevanti rispetto all'incontro precedente. - **GitHub 1 — issue, pull request, conflitti** (27/11/2025) - - Gestione di issue e pull request, risoluzione dei conflitti e strumenti di collaborazione. + - Gestione di issue e pull request, risoluzione dei conflitti e strumenti di collaborazione. - **GitHub 2 — CI/CD, Actions, Git LFS** (04/12/2025) - - Creazione di workflow CI/CD con GitHub Actions, test automatici, deploy e uso di Git LFS. - + - Creazione di workflow CI/CD con GitHub Actions, test automatici, deploy e uso di Git LFS. Il primo incontro (Terminale 1) si terrà il 4 novembre 2025 dalle **17:00 alle 19:00** in **Aula Pincherle** (Dipartimento di Matematica, Piazza Porta S. Donato 5, piano 2). diff --git a/content/events/linux_installation_party.md b/content/events/linux_installation_party.md index 4a61d67..52bebac 100644 --- a/content/events/linux_installation_party.md +++ b/content/events/linux_installation_party.md @@ -1,22 +1,24 @@ --- -title: 'Linux Installation Party' +title: "Linux Installation Party" date: 2024-09-20T16:20:31+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/linux-installation-party-2024.png --- + Ti piacerebbe avere una configurazione in dual-boot o provare Linux come macchina virtuale? Vieni al nostro Linux Installation Party, organizzato da ADMStaff! Durante questo evento ti guideremo passo dopo passo nell’installazione di Linux sul tuo PC. Sarà l’occasione perfetta per entrare nel mondo del software libero, scoprire i vantaggi di un sistema operativo open-source, e ottenere supporto personalizzato durante tutto il processo. -| Date and Time | Location | -| --- | --- | -| 24 settembre 2024 dalle ore 17:00 alle ore 18:30 | Il giorno in ADMLab, mura Anteo Zamboni 7, Bologna | +| Date and Time | Location | +| ------------------------------------------------ | -------------------------------------------------- | +| 24 settembre 2024 dalle ore 17:00 alle ore 18:30 | Il giorno in ADMLab, mura Anteo Zamboni 7, Bologna | ## Cosa portare: + - Il tuo computer - Una chiavetta USB vuota - Almeno 30GB di spazio libero sul disco -> Iscrizione: La registrazione è obbligatoria tramite [Typeform](https://lr533gb3hpt.typeform.com/to/m5fzNCsW) oppure scansiona il QR code presente nella locandina. Posti limitati! In caso di molte adesioni saranno organizzati ulteriori incontri. \ No newline at end of file +> Iscrizione: La registrazione è obbligatoria tramite [Typeform](https://lr533gb3hpt.typeform.com/to/m5fzNCsW) oppure scansiona il QR code presente nella locandina. Posti limitati! In caso di molte adesioni saranno organizzati ulteriori incontri. diff --git a/content/events/linux_installation_party_2025.md b/content/events/linux_installation_party_2025.md index 76f3611..3e582f6 100644 --- a/content/events/linux_installation_party_2025.md +++ b/content/events/linux_installation_party_2025.md @@ -1,32 +1,33 @@ --- -title: 'Linux Installation Party' +title: "Linux Installation Party" date: 2025-10-01T16:20:31+02:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/linux-installation-party-2025-2.png --- + Ti piacerebbe avere una configurazione in dual-boot o provare Linux come macchina virtuale? Vieni al nostro Linux Installation Party, organizzato da ADMStaff! Durante questo evento ti guideremo passo dopo passo nell’installazione di Linux sul tuo PC. Sarà l’occasione perfetta per entrare nel mondo del software libero, scoprire i vantaggi di un sistema operativo open-source, e ottenere supporto personalizzato durante tutto il processo. -| Date and Time | Location | -| --- | --- | -|[concluso] 08 ottobre 2025 dalle ore 14:00 fino a chiusura | in ADMLab, mura Anteo Zamboni 7, Bologna | +| Date and Time | Location | +| ------------------------------------------------------------- | ---------------------------------------- | +| [concluso] 08 ottobre 2025 dalle ore 14:00 fino a chiusura | in ADMLab, mura Anteo Zamboni 7, Bologna | | 17 ottobre 2025 dalle 10:00 e dalle ore 14:00 fino a chiusura | in ADMLab, mura Anteo Zamboni 7, Bologna | Per accedere al laboratorio è necessario avere il badge, in caso di difficoltà all'accesso contattateci tramite il nostro gruppo Telegram [t.me/admstaff_Chat](https://t.me/admstaff_Chat). ## Cosa portare: + - Il tuo computer - Una chiavetta USB vuota - Almeno 30GB di spazio libero sul disco -> Iscrizione: La registrazione è obbligatoria tramite [Form](https://forms.office.com/e/HW3dsc8tJL) oppure scansiona il QR code presente nella locandina. Posti limitati! In caso di molte adesioni saranno organizzati ulteriori incontri. -> +> Iscrizione: La registrazione è obbligatoria tramite [Form](https://forms.office.com/e/HW3dsc8tJL) oppure scansiona il QR code presente nella locandina. Posti limitati! In caso di molte adesioni saranno organizzati ulteriori incontri. +> > Per restare aggiornato sull'evento, unisciti al nostro gruppo Telegram [t.me/admstaff_Chat](https://t.me/admstaff_Chat). - Locandine di quest'anno: ![Linux Installation Party 2025 - primo incontro 08/10](img/linux-installation-party-2025-1.png) -![Linux Installation Party 2025 - secondo incontro 17/10](img/linux-installation-party-2025-2.png) \ No newline at end of file +![Linux Installation Party 2025 - secondo incontro 17/10](img/linux-installation-party-2025-2.png) diff --git a/content/events/presentazione_laboratorio.md b/content/events/presentazione_laboratorio.md index 5d1462e..9526eae 100644 --- a/content/events/presentazione_laboratorio.md +++ b/content/events/presentazione_laboratorio.md @@ -7,15 +7,18 @@ toc: false --- ## 29 novembre alle ore 10:00 in Via Ranzani 14, Laboratorio di Informatica, secondo piano. + ### Chi siamo e cosa facciamo. + Oltre a parlare di questo verranno anche introdotte alcuni concetti come: + - Infrastructure as a Code -- Come e' pensata e costruita in questo momento la nostra infrastruttura -- le CTF Attacck/Defense. +- Come e' pensata e costruita in questo momento la nostra infrastruttura +- le CTF Attacck/Defense. Prendete il vostro pc poiche' proveremo a fare 2 esercizi insieme, dato che lo scopo del gruppo appunto non e' fornire un corso universitario, ma a condividere esperienza da studenti per studenti. Proveremo a fixare e debuggare delle macchine, come se fossimo appena stati attaccati da un intruso oppure più semplicemente un collega ha erroneamente malconfigurato il sistema e noi cercheremo di riprostinarlo. -Parleremo anche dei progetti che possiamo fare insieme, ma l'obiettivo finale come sempre e' che voi proponiate e insieme, e a chi interessa, li portiamo avanti. +Parleremo anche dei progetti che possiamo fare insieme, ma l'obiettivo finale come sempre e' che voi proponiate e insieme, e a chi interessa, li portiamo avanti. Per poter venire e' necessario che compiliate il Form, accedendo con la vostra mail istituzionale, mi raccomando di farlo entro Giovedì 25 Novembre 2021, che nel caso fossimo un numero maggiore della capienza del laboratorio Ranzani provvederemo ad un cambio di laboratorio. diff --git a/content/events/stallman.md b/content/events/stallman.md index fbfa629..9a375ef 100644 --- a/content/events/stallman.md +++ b/content/events/stallman.md @@ -1,14 +1,14 @@ --- -title: 'Richard Stallman @Unibo' +title: "Richard Stallman @Unibo" date: 2024-03-28T21:00:25+01:00 -author: 'ADMStaff' +author: "ADMStaff" toc: false framed: false cover: img/stallman.jpg --- -| Date and Time | Location | -| --- | --- | +| Date and Time | Location | +| ------------------------------------------------- | ---------------------------------------------------------------- | | Il giorno 09 aprile 2024 dalle ore 15 alle ore 17 | in AULA D BERTI PICHAT, Viale Carlo Berti Pichat, 6-6/2, Bologna | Richard Stallman terrà un seminario dal titolo: **"Software libero and freedom in the digital society"** @@ -22,20 +22,23 @@ Se te lo sei perso lo abbiamo registrato: http://media.students.cs.unibo.it/rms- > NOTA: per motivi di salute dell'ospite è obbligatorio l'uso della mascherina che copra naso e bocca. ## Abstract: + There are many threats to freedom in the digital society. They include massive surveillance, censorship, digital handcuffs, nonfree software that controls -users, and the War on Sharing. Computers for voting make election results untrustworthy. Other threats come from use of web services. Finally, we have +users, and the War on Sharing. Computers for voting make election results untrustworthy. Other threats come from use of web services. Finally, we have no assured right to make any particular use of the Internet; every activity is precarious, permitted only as long as companies are willing to cooperate with -our doing it. All of these threats originate more or less in the use of nonfree software. That is why free software is the first battle in the liberation of cyberspace. +our doing it. All of these threats originate more or less in the use of nonfree software. That is why free software is the first battle in the liberation of cyberspace. ## Bio: + Richard Matthew Stallman (born March 16, 1953) is an American computer programmer and free-software advocate. He is widely known by his initials, rms. Stallman campaigns passionately for software to be distributed in a manner that grants users the freedom to use, study, distribute, and modify that software. Here’s a brief overview of his life and contributions: + - **Education**: Stallman graduated from Harvard University in 1974 with a degree in physics. -MIT Years: From 1971 to 1984, he worked at the MIT Artificial Intelligence Lab, where he developed system software. Notably, he created the first extensible text editor called Emacs in 1976 and contributed to the AI technique of dependency-directed backtracking (also known as truth maintenance) in 1975. + MIT Years: From 1971 to 1984, he worked at the MIT Artificial Intelligence Lab, where he developed system software. Notably, he created the first extensible text editor called Emacs in 1976 and contributed to the AI technique of dependency-directed backtracking (also known as truth maintenance) in 1975. - **Free Software Movement**: In 1983, Stallman launched the Free Software Movement by announcing the project to develop the GNU operating system, which aimed to consist entirely of free (freedom-respecting) software. He began working on GNU in 1984 after resigning from MIT employment. - **GNU Project and Copyleft**: Stallman established the Free Software Foundation in October 1985. He invented the concept of copyleft, which allows users to modify and redistribute software while preserving its freedom. The GNU General Public License (GPL), co-written by Stallman, implements copyleft and has inspired initiatives like Creative Commons. - **Software Contributions**: Stallman personally developed several widely used software components of the GNU system, including the GNU Compiler Collection, the GNU symbolic debugger (gdb), and GNU Emacs. The GNU/Linux system, which combines GNU software with the Linux kernel developed by Linus Torvalds, powers tens or hundreds of millions of computers worldwide. - **Advocacy and Travel**: Nowadays, Stallman focuses on political advocacy for free software and its ethical principles. He travels extensively, speaking on topics such as “Free Software And Your Freedom,” “Copyright vs Community in the Age of Computer Networks,” and “A Free Digital Society.” - **Inspirations**: Stallman’s call for a free online encyclopedia helped inspire the creation of Wikipedia. His contributions have been recognized with awards, including the MacArthur Foundation Fellowship and the Association for Computing’s Grace Murray Hopper Award. -For further insights, you can explore his book of essays titled “Free Software, Free Society” and his semiautobiography “Free as in Freedom”. + For further insights, you can explore his book of essays titled “Free Software, Free Society” and his semiautobiography “Free as in Freedom”. diff --git a/content/lab.md b/content/lab.md index 64eda88..e5d2f47 100644 --- a/content/lab.md +++ b/content/lab.md @@ -1,21 +1,23 @@ --- -title: 'Laboratorio | ADMstanzetta' +title: "Laboratorio | ADMstanzetta" date: 2023-10-28T00:00:00Z -author: 'ADMStaff' +author: "ADMStaff" draft: false framed: false toc: false -cover: 'img/ADMlab.jpg' +cover: "img/ADMlab.jpg" --- + Da settembre 2023 ci troviamo in via Mura Anteo Zamboni 7, nel piano seminterrato, Aula 02. ## Perché venire in laboratorio? + - Spazi dedicati allo studio - Postazioni con autenticazioneADM di libero accesso - [Connessione ethernet](#come-mi-connetto-con-i-cavi) senza limitazioni di porte - ## Come mi connetto con i cavi? + 1. Collega il cavo ethernet al tuo computer 2. Apri un terminale: `ssh auth@130.136.201.254` 3. Segui le istruzioni da terminale usando le **tue credenziali unibo** @@ -24,4 +26,4 @@ Da settembre 2023 ci troviamo in via Mura Anteo Zamboni 7, nel piano seminterrat 3. Controlla se il tuo mac address è lo stesso di quello proposto 4. Inserisci il numero di ore per cui vuoi essere connesso -> N.B. Se ti disconnetti per più di 10 minuti l'autenticazione è persa \ No newline at end of file +> N.B. Se ti disconnetti per più di 10 minuti l'autenticazione è persa diff --git a/content/media/wallpapers.md b/content/media/wallpapers.md index ddd84ab..e87d1a0 100644 --- a/content/media/wallpapers.md +++ b/content/media/wallpapers.md @@ -1,9 +1,10 @@ --- -title: 'ADMStaff Wallpapers' +title: "ADMStaff Wallpapers" toc: false author: "ADMStaff" date: "2024-04-19" --- + Per scaricarli vai su https://media.students.cs.unibo.it/wallpapers o clicca sullo sfondo che preferisci. [{{< figure src="https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper-dark.png" title="ADMstaff wallpaper dark" style="width: 100%;" >}}](https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper-dark.png) @@ -14,6 +15,6 @@ Per scaricarli vai su https://media.students.cs.unibo.it/wallpapers o clicca sul [{{< figure src="https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper-gray.png" title="ADMstaff wallpaper gray" style="width: 100%;" >}}](https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper-gray.png) -[{{< figure src="https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-dark.png" title="ADMstaff wallpaper login dark" style="width: 100%;" >}}](https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-dark.png) +[{{< figure src="https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-dark.png" title="ADMstaff wallpaper login dark" style="width: 100%;" >}}](https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-dark.png) [{{< figure src="https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-color.png" title="ADMstaff wallpaper login color" style="width: 100%;" >}}](https://media.students.cs.unibo.it/wallpapers/ADMstaff_wallpaper_login-color.png) diff --git a/content/projects/ansible.md b/content/projects/ansible.md deleted file mode 100644 index 3ed0cba..0000000 --- a/content/projects/ansible.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Ansible" -date: 2021-11-23T18:00:00+02:00 -author: "Admstaff" -draft: false -toc: false -cover: 'img/ansible.png' ---- - -Ansible è un software open-source che automatizza la configurazione, la gestione e l'installazione di software su computer. È un software di gestione della configurazione, che funziona su molti sistemi operativi, tra cui i sistemi basati su Unix e quelli basati su Microsoft Windows. Ansible è stato progettato per essere semplice da usare e leggero, e non richiede l'installazione di software client su nodi gestiti. diff --git a/content/projects/dumbo.md b/content/projects/dumbo.md new file mode 100644 index 0000000..a518b21 --- /dev/null +++ b/content/projects/dumbo.md @@ -0,0 +1,15 @@ +--- +title: "Dumbo" +cover: "img/dumbo.svg" +date: 2024-03-16T18:00:00+02:00 +author: "Admstaff" +draft: false +toc: false +link: "https://dumbo.students.cs.unibo.it" +--- + +Dumbo è un servizio che permette di monitorare l'attività delle macchine del dipartimento DISI. Per ogni macchina vengono raccolti dati come l'utilizzo della CPU, della RAM, del disco e della rete, e vengono visualizzati in tempo reale su un'interfaccia web. + +Potete accedere a Dumbo all'indirizzo [https://dumbo.students.cs.unibo.it/](https://dumbo.students.cs.unibo.it/) + +Dumbo è stato sviluppato per essere utilizzato dagli studenti del dipartimento DISI, ma è accessibile a chiunque voglia monitorare le macchine del dipartimento. diff --git a/content/projects/git.md b/content/projects/git.md index 4424e58..5bf3b8b 100644 --- a/content/projects/git.md +++ b/content/projects/git.md @@ -4,7 +4,10 @@ date: 2021-11-23T18:00:00+02:00 author: "Admstaff" draft: false toc: false -cover: 'img/git-forgejo.png' +link: "https://git.students.cs.unibo.it" +cover: "img/git-forgejo.png" --- -Git è un sistema di controllo di versione distribuito, gratuito e open source progettato per gestire tutto, dai piccoli ai grandi progetti con velocità ed efficienza. \ No newline at end of file +Git è un sistema di controllo di versione distribuito, gratuito e open source progettato per gestire tutto, dai piccoli ai grandi progetti con velocità ed efficienza. + +Abbiamo una nostra istanza di GitLab, chiamata Forgejo, dove ospitiamo i nostri progetti e collaboriamo per la gestione dell'infrastruttura e dei servizi. Se sei interessato a contribuire o vuoi saperne di più sui nostri progetti, visita la nostra [pagina git.students](https://git.students.cs.unibo.it). diff --git a/content/projects/linux.md b/content/projects/linux.md deleted file mode 100644 index e1a8d14..0000000 --- a/content/projects/linux.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: 'Linux' -cover: 'img/linux.png' -toc: false ---- - -Linux è un kernel di sistema operativo Unix-like creato da Linus Torvalds. Il kernel Linux è stato rilasciato per la prima volta il 17 settembre 1991 da Linus Torvalds. Linux è stato progettato per essere un sistema operativo open source e gratuito. Il kernel Linux è stato progettato per funzionare su molti tipi di hardware, tra cui computer desktop, server, dispositivi mobili e dispositivi embedded. \ No newline at end of file diff --git a/content/projects/proxmox.md b/content/projects/proxmox.md index c8d3e8e..eefd70d 100644 --- a/content/projects/proxmox.md +++ b/content/projects/proxmox.md @@ -4,7 +4,11 @@ date: 2021-11-23T18:00:00+02:00 author: "Admstaff" draft: false toc: false -cover: 'img/proxmox.png' +cover: "img/proxmox.png" --- -Proxmox è una piattaforma open source di virtualizzazione che permette di gestire macchine virtuali e container. Proxmox VE è basato su Debian GNU/Linux e utilizza il kernel Linux. Proxmox VE è in grado di gestire macchine virtuali e container, storage, reti e cluster di macchine. Proxmox VE include un web interface e un API REST per la gestione. \ No newline at end of file +Proxmox è una piattaforma open source di virtualizzazione che permette di gestire macchine virtuali e container. Proxmox VE è basato su Debian GNU/Linux e utilizza il kernel Linux. Proxmox VE è in grado di gestire macchine virtuali e container, storage, reti e cluster di macchine. Proxmox VE include un web interface e un API REST per la gestione. + +Lo hostiamo sulla nostra infrastruttura e lo utilizziamo per ospitare i nostri servizi. + +Un servizio utile alla gestione di Proxmox è il tool per avere ID consistenti delle macchine virtuali, che è disponibile su [vm.students.cs.unibo.it/](https://vm.students.cs.unibo.it/). diff --git a/content/projects/sasso.md b/content/projects/sasso.md new file mode 100644 index 0000000..db03656 --- /dev/null +++ b/content/projects/sasso.md @@ -0,0 +1,32 @@ +--- +title: "sasso" +date: 2025-11-25T18:00:00+02:00 +author: "Admstaff" +draft: false +toc: false +link: "https://sasso.students.cs.unibo.it" +cover: "https://sasso.students.cs.unibo.it/sasso.png" +--- + +Sasso is a VPS built on top of Proxmox. It allows users to create and manage +virtual machines in a controlled and secure environment, without giving them +direct access to the Proxmox cluster. + +This service should be used when multiple users need to create and manage their +own virtual machines, but they don't have direct access to the Proxmox cluster +where the VMs are hosted. + +Sasso provides resource management for each user through a web interface. +It creates every virtual machine in a separate Proxmox VNet using a VXLAN Zone +to keep the VMs from differente users isolated from each other. + +> [!WARNING] +> At the moment Sasso is in an early stage of development. Expect bugs, missing +> features and breaking changes. + +This service was developed to be used by [ADMStaff](https://students.cs.unibo.it). + +Please refer to the [Wiki](https://github.com/samuelemusiani/sasso/wiki) for more +information about the architecture, how to deploy and how to use Sasso. + +The source code is available on [GitHub](https://github.com/samuelemusiani/sasso). diff --git a/content/projects/wifi.md b/content/projects/wifi.md new file mode 100644 index 0000000..9952522 --- /dev/null +++ b/content/projects/wifi.md @@ -0,0 +1,11 @@ +--- +title: "Wifi" +date: 2025-04-16T10:27:34+02:00 +author: "ADMStaff" +toc: false +# framed: false +cover: "/img/wifi-pass.png" +link: "https://auth.lab.students.cs.unibo.it" +--- + +In ADM Lab è presente una rete Wi-Fi dedicata agli studenti, che consente di accedere a Internet e alle risorse del laboratorio. Per connettersi alla rete Wi-Fi, è necessario conoscere le credenziali per connettersi all'Access Point. Una volta connessi si aprirà il captive portal, dove potete registarvi e creare le vostre credenziali ADM. Queste possono essere usate per accedere sì alla rete, ma anche a tutti i servizi che abbiamo realizzato e richiedono un'autenticazione, come [sasso](projects/sasso). diff --git a/hugo.toml b/hugo.toml deleted file mode 100644 index 3758eeb..0000000 --- a/hugo.toml +++ /dev/null @@ -1,87 +0,0 @@ -baseURL = 'https://students.cs.unibo.it/' -languageCode = 'it-it' -title = 'ADMStaff' -theme = 'website-theme' - -# Default language -defaultContentLanguage = "it" - -[params] - # if you set this to 0, only submenu trigger will be visible - showMenuItems = 5 - - # dir name of your blog content (default is `content/posts`). - # the list of set content will show up on your index page (baseurl). - # contentTypeName = "events" - - # Show table of contents at the top of your posts (defaults to false) - # Alternatively, add this param to post front matter for specific posts - toc = true - - [params.logo] - logoText = "ADMStaff" - logoHomeLink = "/" - - -[languages] - [languages.it] - languageCode = "it-it" - languageName = "Italiano" - weight = 1 - contentDir = "content" - - [[languages.it.menu.main]] - identifier = "about" - name = "About Us" - url = "/about" - - [[languages.it.menu.main]] - identifier = "wiki" - name = "Wiki" - url = "/wiki/adm.wiki" - - [[languages.it.menu.main]] - identifier = "lab" - name = "Laboratorio" - url = "/lab" - - [[languages.it.menu.main]] - identifier = "events" - name = "Eventi" - url = "/events" - - [[languages.it.menu.main]] - identifier = "media" - name = "Media" - url = "/media" - - [languages.en] - languageCode = "en-us" - languageName = "English" - weight = 2 - contentDir = "content/en" - - [[languages.en.menu.main]] - identifier = "about" - name = "About Us" - url = "/en/about" - - [[languages.en.menu.main]] - identifier = "wiki" - name = "Wiki" - url = "/wiki/adm.wiki" - - [[languages.en.menu.main]] - identifier = "lab" - name = "Laboratory" - url = "/lab" - - [[languages.en.menu.main]] - identifier = "events" - name = "Events" - url = "/events" - - [[languages.en.menu.main]] - identifier = "media" - name = "Media" - url = "/media" \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..d68321d --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + + + ADMStaff + + +
+ + + diff --git a/layouts/events/list.html b/layouts/events/list.html deleted file mode 100644 index 993c15c..0000000 --- a/layouts/events/list.html +++ /dev/null @@ -1,63 +0,0 @@ -{{ define "main" }} -{{ if .Content }} -
-

{{ .Title }}

- {{ .Content }} -
-{{ end }} -
- {{ range .Pages }} -
-

{{ .Title | markdownify }}

- - - {{ if .Params.tags }} - - {{ end }} - - {{ if .Params.Cover }} - {{ partial "postcover.html" . }} - {{ end }} - -
- {{ with .Description }} - {{ . | markdownify }} - {{ else }} - {{ if .Truncated }} - {{ .Summary }} - {{ end }} - {{ end }} -
- {{ if not .Params.hideReadMore }} -
- {{ $.Site.Params.ReadMore | default "Read more" }} - → -
- {{ end }} -
- {{ end }} - {{ partial "pagination.html" . }} -
-{{ end }} \ No newline at end of file diff --git a/layouts/index.html b/layouts/index.html deleted file mode 100644 index 94a84b2..0000000 --- a/layouts/index.html +++ /dev/null @@ -1,53 +0,0 @@ -{{ define "main" }} -
-

ADMstaff nasce come gruppo che fornisce servizi da studenti per studenti.

- Il nostro obiettivo è sperimentare e fare pratica su ciò che ci appassiona e ci - incuriosisce.
Tutto - ciò che stuzzica la curiosità è alla nostra portata

-

-
- -
-

Ultimi Eventi

-
- {{ $events := site.GetPage "/events" }} - {{ range first 3 $events.Pages.ByDate.Reverse }} -
- -

{{ .Title | markdownify }}

- {{ if .Params.Cover }} - {{ .Title }} - {{ end }} -
- {{ .Summary | truncate 100 }} -
-
-
- {{ end }} -
-
-

I nostri strumenti

-
- {{ $projects := site.GetPage "/projects" }} - {{ range $projects.Pages.ByTitle }} -
- -

{{ .Title | markdownify }}

- {{ if .Params.Cover }} - {{ .Title }} - {{ end }} -
- {{ .Summary | truncate 100 }} -
- {{ if .Params.tags }} -
- {{ end }} - -
- {{ end }} -
-{{ end }} diff --git a/layouts/wiki/list.html b/layouts/wiki/list.html deleted file mode 100644 index de775b4..0000000 --- a/layouts/wiki/list.html +++ /dev/null @@ -1,63 +0,0 @@ -{{ define "main" }} -{{ if .Content }} -
- {{ .Content }} -
-{{ end }} -
- {{ range .Pages.ByTitle }} -
-

{{ .Title | markdownify }}

- - - {{ if .Params.tags }} - - {{ end }} - - {{ if .Params.Cover }} - {{ partial "postcover.html" . }} - {{ end }} - -
- {{ with .Description }} - {{ . | markdownify }} - {{ else }} - {{ if .Truncated }} - {{ .Summary | truncate 100 }} - {{ end }} - {{ end }} -
- -
- {{ end }} - {{ partial "pagination.html" . }} -
-{{ end }} \ No newline at end of file diff --git a/og_base.png b/og_base.png new file mode 100644 index 0000000..68cbc42 --- /dev/null +++ b/og_base.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:082d861f6af28e58afd4a05588d20550dff2a807dafbbb03f38c150077e61a5a +size 16526 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..95131ba --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2490 @@ +{ + "name": "admstaff-website", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "admstaff-website", + "version": "1.0.0", + "dependencies": { + "marked": "^12.0.0", + "vue": "^3.5.25", + "vue-router": "^4.4.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.2", + "autoprefixer": "^10.4.20", + "daisyui": "^4.12.14", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "vite": "^7.3.1" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", + "integrity": "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.4.tgz", + "integrity": "sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-rc.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.28.tgz", + "integrity": "sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/shared": "3.5.28", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.28.tgz", + "integrity": "sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.28.tgz", + "integrity": "sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/compiler-core": "3.5.28", + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.28.tgz", + "integrity": "sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.28.tgz", + "integrity": "sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.28.tgz", + "integrity": "sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.28.tgz", + "integrity": "sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.28", + "@vue/runtime-core": "3.5.28", + "@vue/shared": "3.5.28", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.28.tgz", + "integrity": "sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28" + }, + "peerDependencies": { + "vue": "3.5.28" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.28.tgz", + "integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==", + "license": "MIT" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.24", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", + "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001766", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001769", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/css-selector-tokenizer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/culori": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/daisyui": { + "version": "4.12.24", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.24.tgz", + "integrity": "sha512-JYg9fhQHOfXyLadrBrEqCDM6D5dWCSSiM6eTNCRrBRzx/VlOCrLS8eDfIw9RVvs64v2mJdLooKXY8EwQzoszAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-selector-tokenizer": "^0.8", + "culori": "^3", + "picocolors": "^1", + "postcss-js": "^4" + }, + "engines": { + "node": ">=16.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/daisyui" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "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" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/marked": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz", + "integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-sfc": "3.5.28", + "@vue/runtime-dom": "3.5.28", + "@vue/server-renderer": "3.5.28", + "@vue/shared": "3.5.28" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..850ac7e --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "admstaff-website", + "private": true, + "version": "2.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "pnpm generate-og && vite build", + "preview": "vite preview", + "generate-og": "node scripts/generate-og-images.js", + "new-content": "node scripts/new-content.js", + "format": "prettier --write \"{src,content,layouts,scripts,archetypes}/**/*.{js,vue,css,md,html,json}\" \"*.{js,json,md,html,toml}\"" + }, + "dependencies": { + "@vueuse/head": "^2.0.0", + "vue": "^3.5.25", + "vue-i18n": "^11.2.8", + "vue-router": "^4.4.0" + }, + "devDependencies": { + "@iconify/vue": "^5.0.0", + "@napi-rs/canvas": "^0.1.92", + "@vitejs/plugin-vue": "^6.0.2", + "autoprefixer": "^10.4.20", + "daisyui": "^4.12.14", + "marked": "^12.0.0", + "postcss": "^8.4.49", + "prettier": "^3.8.2", + "tailwindcss": "^3.4.17", + "vite": "^7.3.1" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..1b6c9d5 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1752 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@vueuse/head': + specifier: ^2.0.0 + version: 2.0.0(vue@3.5.28) + vue: + specifier: ^3.5.25 + version: 3.5.28 + vue-i18n: + specifier: ^11.2.8 + version: 11.2.8(vue@3.5.28) + vue-router: + specifier: ^4.4.0 + version: 4.6.4(vue@3.5.28) + devDependencies: + '@iconify/vue': + specifier: ^5.0.0 + version: 5.0.0(vue@3.5.28) + '@napi-rs/canvas': + specifier: ^0.1.92 + version: 0.1.92 + '@vitejs/plugin-vue': + specifier: ^6.0.2 + version: 6.0.4(vite@7.3.1(jiti@1.21.7))(vue@3.5.28) + autoprefixer: + specifier: ^10.4.20 + version: 10.4.24(postcss@8.5.6) + daisyui: + specifier: ^4.12.14 + version: 4.12.24(postcss@8.5.6) + marked: + specifier: ^12.0.0 + version: 12.0.2 + postcss: + specifier: ^8.4.49 + version: 8.5.6 + prettier: + specifier: ^3.8.2 + version: 3.8.2 + tailwindcss: + specifier: ^3.4.17 + version: 3.4.19 + vite: + specifier: ^7.3.1 + version: 7.3.1(jiti@1.21.7) + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/vue@5.0.0': + resolution: {integrity: sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==} + peerDependencies: + vue: '>=3' + + '@intlify/core-base@11.2.8': + resolution: {integrity: sha512-nBq6Y1tVkjIUsLsdOjDSJj4AsjvD0UG3zsg9Fyc+OivwlA/oMHSKooUy9tpKj0HqZ+NWFifweHavdljlBLTwdA==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@11.2.8': + resolution: {integrity: sha512-A5n33doOjmHsBtCN421386cG1tWp5rpOjOYPNsnpjIJbQ4POF0QY2ezhZR9kr0boKwaHjbOifvyQvHj2UTrDFQ==} + engines: {node: '>= 16'} + + '@intlify/shared@11.2.8': + resolution: {integrity: sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==} + engines: {node: '>= 16'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/canvas-android-arm64@0.1.92': + resolution: {integrity: sha512-rDOtq53ujfOuevD5taxAuIFALuf1QsQWZe1yS/N4MtT+tNiDBEdjufvQRPWZ11FubL2uwgP8ApYU3YOaNu1ZsQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/canvas-darwin-arm64@0.1.92': + resolution: {integrity: sha512-4PT6GRGCr7yMRehp42x0LJb1V0IEy1cDZDDayv7eKbFUIGbPFkV7CRC9Bee5MPkjg1EB4ZPXXUyy3gjQm7mR8Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/canvas-darwin-x64@0.1.92': + resolution: {integrity: sha512-5e/3ZapP7CqPtDcZPtmowCsjoyQwuNMMD7c0GKPtZQ8pgQhLkeq/3fmk0HqNSD1i227FyJN/9pDrhw/UMTkaWA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.92': + resolution: {integrity: sha512-j6KaLL9iir68lwpzzY+aBGag1PZp3+gJE2mQ3ar4VJVmyLRVOh+1qsdNK1gfWoAVy5w6U7OEYFrLzN2vOFUSng==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/canvas-linux-arm64-gnu@0.1.92': + resolution: {integrity: sha512-s3NlnJMHOSotUYVoTCoC1OcomaChFdKmZg0VsHFeIkeHbwX0uPHP4eCX1irjSfMykyvsGHTQDfBAtGYuqxCxhQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/canvas-linux-arm64-musl@0.1.92': + resolution: {integrity: sha512-xV0GQnukYq5qY+ebkAwHjnP2OrSGBxS3vSi1zQNQj0bkXU6Ou+Tw7JjCM7pZcQ28MUyEBS1yKfo7rc7ip2IPFQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.92': + resolution: {integrity: sha512-+GKvIFbQ74eB/TopEdH6XIXcvOGcuKvCITLGXy7WLJAyNp3Kdn1ncjxg91ihatBaPR+t63QOE99yHuIWn3UQ9w==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@napi-rs/canvas-linux-x64-gnu@0.1.92': + resolution: {integrity: sha512-tFd6MwbEhZ1g64iVY2asV+dOJC+GT3Yd6UH4G3Hp0/VHQ6qikB+nvXEULskFYZ0+wFqlGPtXjG1Jmv7sJy+3Ww==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/canvas-linux-x64-musl@0.1.92': + resolution: {integrity: sha512-uSuqeSveB/ZGd72VfNbHCSXO9sArpZTvznMVsb42nqPP7gBGEH6NJQ0+hmF+w24unEmxBhPYakP/Wiosm16KkA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/canvas-win32-arm64-msvc@0.1.92': + resolution: {integrity: sha512-20SK5AU/OUNz9ZuoAPj5ekWai45EIBDh/XsdrVZ8le/pJVlhjFU3olbumSQUXRFn7lBRS+qwM8kA//uLaDx6iQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/canvas-win32-x64-msvc@0.1.92': + resolution: {integrity: sha512-KEhyZLzq1MXCNlXybz4k25MJmHFp+uK1SIb8yJB0xfrQjz5aogAMhyseSzewo+XxAq3OAOdyKvfHGNzT3w1RPg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/canvas@0.1.92': + resolution: {integrity: sha512-q7ZaUCJkEU5BeOdE7fBx1XWRd2T5Ady65nxq4brMf5L4cE1VV/ACq5w9Z5b/IVJs8CwSSIwc30nlthH0gFo4Ig==} + engines: {node: '>= 10'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@rolldown/pluginutils@1.0.0-rc.2': + resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + + '@rollup/rollup-android-arm-eabi@4.57.1': + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.57.1': + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.57.1': + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.57.1': + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.57.1': + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.57.1': + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.57.1': + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.57.1': + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.57.1': + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.57.1': + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.57.1': + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.57.1': + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.57.1': + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.57.1': + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@unhead/dom@1.11.20': + resolution: {integrity: sha512-jgfGYdOH+xHJF/j8gudjsYu3oIjFyXhCWcgKaw3vQnT616gSqyqnGQGOItL+BQtQZACKNISwIfx5PuOtztMKLA==} + + '@unhead/schema@1.11.20': + resolution: {integrity: sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==} + + '@unhead/shared@1.11.20': + resolution: {integrity: sha512-1MOrBkGgkUXS+sOKz/DBh4U20DNoITlJwpmvSInxEUNhghSNb56S0RnaHRq0iHkhrO/cDgz2zvfdlRpoPLGI3w==} + + '@unhead/ssr@1.11.20': + resolution: {integrity: sha512-j6ehzmdWGAvv0TEZyLE3WBnG1ULnsbKQcLqBDh3fvKS6b3xutcVZB7mjvrVE7ckSZt6WwOtG0ED3NJDS7IjzBA==} + + '@unhead/vue@1.11.20': + resolution: {integrity: sha512-sqQaLbwqY9TvLEGeq8Fd7+F2TIuV3nZ5ihVISHjWpAM3y7DwNWRU7NmT9+yYT+2/jw1Vjwdkv5/HvDnvCLrgmg==} + peerDependencies: + vue: '>=2.7 || >=3' + + '@vitejs/plugin-vue@6.0.4': + resolution: {integrity: sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vue: ^3.2.25 + + '@vue/compiler-core@3.5.28': + resolution: {integrity: sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==} + + '@vue/compiler-dom@3.5.28': + resolution: {integrity: sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==} + + '@vue/compiler-sfc@3.5.28': + resolution: {integrity: sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==} + + '@vue/compiler-ssr@3.5.28': + resolution: {integrity: sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/reactivity@3.5.28': + resolution: {integrity: sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==} + + '@vue/runtime-core@3.5.28': + resolution: {integrity: sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==} + + '@vue/runtime-dom@3.5.28': + resolution: {integrity: sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==} + + '@vue/server-renderer@3.5.28': + resolution: {integrity: sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==} + peerDependencies: + vue: 3.5.28 + + '@vue/shared@3.5.28': + resolution: {integrity: sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==} + + '@vueuse/head@2.0.0': + resolution: {integrity: sha512-ykdOxTGs95xjD4WXE4na/umxZea2Itl0GWBILas+O4oqS7eXIods38INvk3XkJKjqMdWPcpCyLX/DioLQxU1KA==} + peerDependencies: + vue: '>=2.7 || >=3' + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + autoprefixer@10.4.24: + resolution: {integrity: sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + hasBin: true + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + caniuse-lite@1.0.30001769: + resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + css-selector-tokenizer@0.8.0: + resolution: {integrity: sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + culori@3.3.0: + resolution: {integrity: sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + daisyui@4.12.24: + resolution: {integrity: sha512-JYg9fhQHOfXyLadrBrEqCDM6D5dWCSSiM6eTNCRrBRzx/VlOCrLS8eDfIw9RVvs64v2mJdLooKXY8EwQzoszAA==} + engines: {node: '>=16.9.0'} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + electron-to-chromium@1.5.286: + resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastparse@1.1.2: + resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + marked@12.0.2: + resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==} + engines: {node: '>= 18'} + hasBin: true + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + packrup@0.1.2: + resolution: {integrity: sha512-ZcKU7zrr5GlonoS9cxxrb5HVswGnyj6jQvwFBa6p5VFw7G71VAHcUKL5wyZSU/ECtPM/9gacWxy2KFQKt1gMNA==} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.8.2: + resolution: {integrity: sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==} + engines: {node: '>=14'} + hasBin: true + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwindcss@3.4.19: + resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + unhead@1.11.20: + resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vue-i18n@11.2.8: + resolution: {integrity: sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + + vue-router@4.6.4: + resolution: {integrity: sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==} + peerDependencies: + vue: ^3.5.0 + + vue@3.5.28: + resolution: {integrity: sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + zhead@2.2.4: + resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@iconify/types@2.0.0': {} + + '@iconify/vue@5.0.0(vue@3.5.28)': + dependencies: + '@iconify/types': 2.0.0 + vue: 3.5.28 + + '@intlify/core-base@11.2.8': + dependencies: + '@intlify/message-compiler': 11.2.8 + '@intlify/shared': 11.2.8 + + '@intlify/message-compiler@11.2.8': + dependencies: + '@intlify/shared': 11.2.8 + source-map-js: 1.2.1 + + '@intlify/shared@11.2.8': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/canvas-android-arm64@0.1.92': + optional: true + + '@napi-rs/canvas-darwin-arm64@0.1.92': + optional: true + + '@napi-rs/canvas-darwin-x64@0.1.92': + optional: true + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.92': + optional: true + + '@napi-rs/canvas-linux-arm64-gnu@0.1.92': + optional: true + + '@napi-rs/canvas-linux-arm64-musl@0.1.92': + optional: true + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.92': + optional: true + + '@napi-rs/canvas-linux-x64-gnu@0.1.92': + optional: true + + '@napi-rs/canvas-linux-x64-musl@0.1.92': + optional: true + + '@napi-rs/canvas-win32-arm64-msvc@0.1.92': + optional: true + + '@napi-rs/canvas-win32-x64-msvc@0.1.92': + optional: true + + '@napi-rs/canvas@0.1.92': + optionalDependencies: + '@napi-rs/canvas-android-arm64': 0.1.92 + '@napi-rs/canvas-darwin-arm64': 0.1.92 + '@napi-rs/canvas-darwin-x64': 0.1.92 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.92 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.92 + '@napi-rs/canvas-linux-arm64-musl': 0.1.92 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.92 + '@napi-rs/canvas-linux-x64-gnu': 0.1.92 + '@napi-rs/canvas-linux-x64-musl': 0.1.92 + '@napi-rs/canvas-win32-arm64-msvc': 0.1.92 + '@napi-rs/canvas-win32-x64-msvc': 0.1.92 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@rolldown/pluginutils@1.0.0-rc.2': {} + + '@rollup/rollup-android-arm-eabi@4.57.1': + optional: true + + '@rollup/rollup-android-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-x64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.57.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.57.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.57.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.57.1': + optional: true + + '@types/estree@1.0.8': {} + + '@unhead/dom@1.11.20': + dependencies: + '@unhead/schema': 1.11.20 + '@unhead/shared': 1.11.20 + + '@unhead/schema@1.11.20': + dependencies: + hookable: 5.5.3 + zhead: 2.2.4 + + '@unhead/shared@1.11.20': + dependencies: + '@unhead/schema': 1.11.20 + packrup: 0.1.2 + + '@unhead/ssr@1.11.20': + dependencies: + '@unhead/schema': 1.11.20 + '@unhead/shared': 1.11.20 + + '@unhead/vue@1.11.20(vue@3.5.28)': + dependencies: + '@unhead/schema': 1.11.20 + '@unhead/shared': 1.11.20 + hookable: 5.5.3 + unhead: 1.11.20 + vue: 3.5.28 + + '@vitejs/plugin-vue@6.0.4(vite@7.3.1(jiti@1.21.7))(vue@3.5.28)': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.2 + vite: 7.3.1(jiti@1.21.7) + vue: 3.5.28 + + '@vue/compiler-core@3.5.28': + dependencies: + '@babel/parser': 7.29.0 + '@vue/shared': 3.5.28 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.28': + dependencies: + '@vue/compiler-core': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/compiler-sfc@3.5.28': + dependencies: + '@babel/parser': 7.29.0 + '@vue/compiler-core': 3.5.28 + '@vue/compiler-dom': 3.5.28 + '@vue/compiler-ssr': 3.5.28 + '@vue/shared': 3.5.28 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.28': + dependencies: + '@vue/compiler-dom': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/devtools-api@6.6.4': {} + + '@vue/reactivity@3.5.28': + dependencies: + '@vue/shared': 3.5.28 + + '@vue/runtime-core@3.5.28': + dependencies: + '@vue/reactivity': 3.5.28 + '@vue/shared': 3.5.28 + + '@vue/runtime-dom@3.5.28': + dependencies: + '@vue/reactivity': 3.5.28 + '@vue/runtime-core': 3.5.28 + '@vue/shared': 3.5.28 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.28(vue@3.5.28)': + dependencies: + '@vue/compiler-ssr': 3.5.28 + '@vue/shared': 3.5.28 + vue: 3.5.28 + + '@vue/shared@3.5.28': {} + + '@vueuse/head@2.0.0(vue@3.5.28)': + dependencies: + '@unhead/dom': 1.11.20 + '@unhead/schema': 1.11.20 + '@unhead/ssr': 1.11.20 + '@unhead/vue': 1.11.20(vue@3.5.28) + vue: 3.5.28 + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + autoprefixer@10.4.24(postcss@8.5.6): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001769 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + baseline-browser-mapping@2.9.19: {} + + binary-extensions@2.3.0: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001769 + electron-to-chromium: 1.5.286 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + camelcase-css@2.0.1: {} + + caniuse-lite@1.0.30001769: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + commander@4.1.1: {} + + css-selector-tokenizer@0.8.0: + dependencies: + cssesc: 3.0.0 + fastparse: 1.1.2 + + cssesc@3.0.0: {} + + csstype@3.2.3: {} + + culori@3.3.0: {} + + daisyui@4.12.24(postcss@8.5.6): + dependencies: + css-selector-tokenizer: 0.8.0 + culori: 3.3.0 + picocolors: 1.1.1 + postcss-js: 4.1.0(postcss@8.5.6) + transitivePeerDependencies: + - postcss + + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + + electron-to-chromium@1.5.286: {} + + entities@7.0.1: {} + + esbuild@0.27.3: + 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 + + escalade@3.2.0: {} + + estree-walker@2.0.2: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastparse@1.1.2: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + fraction.js@5.3.4: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hookable@5.5.3: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + jiti@1.21.7: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + marked@12.0.2: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.11: {} + + node-releases@2.0.27: {} + + normalize-path@3.0.0: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + packrup@0.1.2: {} + + path-parse@1.0.7: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pify@2.3.0: {} + + pirates@4.0.7: {} + + postcss-import@15.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.11 + + postcss-js@4.1.0(postcss@8.5.6): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.6 + + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 1.21.7 + postcss: 8.5.6 + + postcss-nested@6.2.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.8.2: {} + + queue-microtask@1.2.3: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + rollup@4.57.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + source-map-js@1.2.1: {} + + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwindcss@3.4.19: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-import: 15.1.0(postcss@8.5.6) + postcss-js: 4.1.0(postcss@8.5.6) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6) + postcss-nested: 6.2.0(postcss@8.5.6) + postcss-selector-parser: 6.1.2 + resolve: 1.22.11 + sucrase: 3.35.1 + transitivePeerDependencies: + - tsx + - yaml + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-interface-checker@0.1.13: {} + + unhead@1.11.20: + dependencies: + '@unhead/dom': 1.11.20 + '@unhead/schema': 1.11.20 + '@unhead/shared': 1.11.20 + hookable: 5.5.3 + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: {} + + vite@7.3.1(jiti@1.21.7): + dependencies: + esbuild: 0.27.3 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.57.1 + tinyglobby: 0.2.15 + optionalDependencies: + fsevents: 2.3.3 + jiti: 1.21.7 + + vue-i18n@11.2.8(vue@3.5.28): + dependencies: + '@intlify/core-base': 11.2.8 + '@intlify/shared': 11.2.8 + '@vue/devtools-api': 6.6.4 + vue: 3.5.28 + + vue-router@4.6.4(vue@3.5.28): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.28 + + vue@3.5.28: + dependencies: + '@vue/compiler-dom': 3.5.28 + '@vue/compiler-sfc': 3.5.28 + '@vue/runtime-dom': 3.5.28 + '@vue/server-renderer': 3.5.28(vue@3.5.28) + '@vue/shared': 3.5.28 + + zhead@2.2.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..141cffc --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +ignoredBuiltDependencies: + - canvas diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2aa7205 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/public/img/laboratori-25-26.png b/public/img/laboratori-25-26.png deleted file mode 100644 index 25fc6a9..0000000 --- a/public/img/laboratori-25-26.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:16018f10548ade07b005c82d1ccf2752b299d945f910dd8272c74e05a7976d4d -size 1456471 diff --git a/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.content b/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.content deleted file mode 100644 index 3db360f..0000000 --- a/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.content +++ /dev/null @@ -1,1096 +0,0 @@ -@charset "UTF-8"; -body.light-theme, :root { - /* light theme color */ - --background: #fff; - --background-secondary: #eaeaea; - --header: #fafafa; - --color: #222; - --color-secondary: #999; - --border-color: #dcdcdc; - --adm-color: #618375; - /* variables for js, must be the same as these in @custom-media queries */ - --phoneWidth: (max-width: 684px); - --tabletWidth: (max-width: 900px); } - -body.dark-theme { - /* dark theme colors */ - --background: #292a2d; - --background-secondary: #3b3d42; - --header: #252627; - --color: #a9a9b3; - --color-secondary: #73747b; - --border-color: #4a4b50; - --adm-color: #618375; } - -@media (prefers-color-scheme: light) { - body:not(.dark-theme) { - /* light theme color */ - --background: #fff; - --background-secondary: #eaeaea; - --header: #fafafa; - --color: #222; - --color-secondary: #999; - --border-color: #dcdcdc; } } - -@media (prefers-color-scheme: dark) { - body:not(.light-theme) { - /* dark theme colors */ - --background: #292a2d; - --background-secondary: #3b3d42; - --header: #252627; - --color: #a9a9b3; - --color-secondary: #73747b; - --border-color: #4a4b50; } } - -/* MEDIA QUERIES */ -/* HOW TO USE */ -/*@media ($phone) {*/ -/*margin-top: 0;*/ -/*}*/ -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 400; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-Regular.woff2") format("woff2"); - font-display: swap; } - -@font-face { - font-family: 'Inter'; - font-style: italic; - font-weight: 400; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-Italic.woff2") format("woff2"); - font-display: swap; } - -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 600; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-Medium.woff2") format("woff2"); - font-display: swap; } - -@font-face { - font-family: 'Inter'; - font-style: italic; - font-weight: 600; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-MediumItalic.woff2") format("woff2"); - font-display: swap; } - -@font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 800; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-Bold.woff2") format("woff2"); - font-display: swap; } - -@font-face { - font-family: 'Inter'; - font-style: italic; - font-weight: 800; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - src: url("../fonts/Inter-BoldItalic.woff2") format("woff2"); - font-display: swap; } - -.button-container { - display: table; - margin-left: auto; - margin-right: auto; } - -button, -.button, -a.button { - position: relative; - display: flex; - align-items: center; - justify-content: center; - padding: 8px 18px; - margin-bottom: 5px; - background: var(--background-secondary); - text-decoration: none; - text-align: center; - font-weight: 500; - border-radius: 8px; - border: 1px solid transparent; - appearance: none; - cursor: pointer; - outline: none; - color: #618375; - /* variants */ - /* sizes */ } - button.outline, - .button.outline, - a.button.outline { - background: transparent; - border-color: var(--background-secondary); - box-shadow: none; - padding: 8px 18px; } - button.outline :hover, - .button.outline :hover, - a.button.outline :hover { - transform: none; - box-shadow: none; } - button.primary, - .button.primary, - a.button.primary { - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); } - button.primary:hover, - .button.primary:hover, - a.button.primary:hover { - box-shadow: 0 2px 6px rgba(50, 50, 93, 0.21), 0 1px 3px rgba(0, 0, 0, 0.08); } - button.link, - .button.link, - a.button.link { - background: none; - font-size: 1rem; } - button.small, - .button.small, - a.button.small { - font-size: .8rem; } - button.wide, - .button.wide, - a.button.wide { - min-width: 200px; - padding: 14px 24px; } - -a.read-more, -a.read-more:hover, -a.read-more:active { - display: inline-flex; - background: none; - box-shadow: none; - padding: 5; - margin: 20px 0; - font-weight: bold; - background-color: #61837556; } - -.code-toolbar { - margin-bottom: 20px; } - .code-toolbar .toolbar-item a { - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 3px 8px; - margin-bottom: 5px; - background: var(--background-secondary); - text-decoration: none; - text-align: center; - font-size: 13px; - font-weight: 500; - border-radius: 8px; - border: 1px solid transparent; - appearance: none; - cursor: pointer; - outline: none; } - -.header { - background: var(--header); - display: flex; - align-items: center; - justify-content: center; - position: relative; - padding: 20px; } - .header__right { - display: flex; - flex-direction: row; - align-items: center; } - @media (max-width: 684px) { - .header__right { - flex-direction: row-reverse; } } - .header__inner { - display: flex; - align-items: center; - justify-content: space-between; - margin: 0 auto; - width: 760px; - max-width: 100%; } - -.theme-toggle { - display: flex; - align-items: center; - justify-content: center; - line-height: 1; - cursor: pointer; } - -.theme-toggler { - fill: currentColor; } - -.logo { - display: flex; - align-items: center; - flex: 0 0 auto; - text-decoration: none; - font-weight: bold; } - .logo img { - height: 44px; } - .logo__mark { - display: inline-flex; - align-items: center; - margin-right: 5px; } - .logo__mark .greater-icon { - width: 0.95rem; - height: 100%; } - .logo__mark .greater-icon path { - stroke: currentColor; - stroke-width: 8px; } - .logo__text { - font-size: 1.125rem; } - .logo__cursor { - display: inline-block; - width: 10px; - height: 1rem; - background: #618375; - margin-left: 5px; - border-radius: 1px; - animation: cursor 1s infinite; } - -@keyframes cursor { - 0% { - opacity: 0; } - 50% { - opacity: 1; } - 100% { - opacity: 0; } } - -.menu { - --color: rgba(0, 0, 0, .12); - --shadow: 0 8px 20px var(--color); - border-right: 1px solid; - margin-right: 18px; - padding-right: 24px; - font-weight: 500; } - @media (max-width: 684px) { - .menu { - position: absolute; - background: var(--header); - box-shadow: var(--shadow); - margin: 0; - padding: 5px; - list-style: none; - border-radius: 5px; - z-index: 99; - border: none; - top: 50px; - right: 10px; } } - .menu a { - text-decoration: none; } - .menu__inner { - display: flex; - align-items: center; - justify-content: flex-end; - flex-wrap: wrap; - list-style: none; - margin: 0; - padding: 0; } - @media (max-width: 684px) { - .menu__inner--desktop { - display: none; } } - .menu__inner--mobile { - display: none; } - @media (max-width: 684px) { - .menu__inner--mobile { - display: block; } } - .menu__inner li { - text-align: left; - flex: 0 0 auto; } - .menu__inner li:not(:first-of-type) { - margin-left: 20px; } - @media (max-width: 684px) { - .menu__inner { - flex-direction: column; - align-items: flex-start; - padding: 0; } - .menu__inner li { - margin-left: 0 !important; - padding: 10px; } } - .menu__sub-inner { - position: relative; - list-style: none; - padding: 0; - margin: 0; } - .menu__sub-inner:not(:only-child) { - margin-left: 20px; } - .menu__sub-inner-more { - position: absolute; - background: var(--header); - box-shadow: var(--shadow); - margin: 0; - padding: 5px; - list-style: none; - border-radius: 5px; - z-index: 99; - top: 35px; - left: 0; } - .menu__sub-inner-more-trigger { - display: inline-flex; - align-items: center; - user-select: none; - cursor: pointer; } - .menu__sub-inner-more-trigger-icon { - display: inline-flex; - align-items: center; - margin-left: 3px; - transform: rotate(90deg); - line-height: 1; } - .menu__sub-inner-more-trigger-icon .greater-icon { - width: 0.95rem; - height: 100%; } - .menu__sub-inner-more-trigger-icon .greater-icon path { - stroke: currentColor; - stroke-width: 5px; } - .menu__inner .menu__sub-inner-more li { - margin-left: 0; - white-space: nowrap; } - .menu__inner .menu__sub-inner-more li:hover { - background: rgba(0, 0, 0, 0.05); - border-radius: 3px; - cursor: pointer; } - .menu__sub-inner-more li a { - width: 100%; - display: inline-block; - padding: 10px; } - .menu-trigger { - width: 24px; - height: 24px; - fill: currentColor; - margin-left: 10px; - cursor: pointer; } - -html { - box-sizing: border-box; } - -*, -*:before, -*:after { - box-sizing: inherit; } - -body { - margin: 0; - padding: 0; - font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Roboto", "Segoe UI", Helvetica, Arial, sans-serif; - font-size: 1rem; - font-weight: 500; - font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; - line-height: 1.54; - background-color: var(--background); - color: var(--color); - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -webkit-overflow-scrolling: touch; - -webkit-text-size-adjust: 100%; } - @media (max-width: 684px) { - body { - font-size: 1rem; } } -h1, h2, h3, h4, h5, h6 { - line-height: 1.3; } - -h1 { - font-size: 2.625rem; } - -h2 { - font-size: 1.625rem; } - -h3 { - font-size: 1.375rem; } - -h4 { - font-size: 1.125rem; } - -@media (max-width: 684px) { - h1 { - font-size: 2rem; } - h2 { - font-size: 1.4rem; } - h3 { - font-size: 1.15rem; } - h4 { - font-size: 1.125rem; } } - -a { - color: inherit; } - -img { - display: block; - max-width: 100%; } - img.left { - margin-right: auto; } - img.center { - margin-left: auto; - margin-right: auto; } - img.right { - margin-left: auto; } - -figure { - display: table; - max-width: 100%; - margin: 25px 0; } - figure.left { - margin-right: auto; } - figure.center { - margin-left: auto; - margin-right: auto; } - figure.right { - margin-left: auto; } - figure figcaption { - font-size: .9rem; - margin-top: 5px; - opacity: .8; } - figure figcaption.left { - text-align: left; } - figure figcaption.center { - text-align: center; } - figure figcaption.right { - text-align: right; } - -code, kbd { - font-family: Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace; - background: var(--background-secondary); - padding: 1px 6px; - margin: 0 2px; - border-radius: 5px; - font-size: .9em; - font-weight: normal; - font-feature-settings: normal; } - code code, code kbd, kbd code, kbd kbd { - background: transparent; - padding: 0; - margin: 0; } - -pre { - font-feature-settings: normal; - background: #212020; - padding: 20px; - border-radius: 8px; - font-size: .9rem; - overflow: auto; } - @media (max-width: 684px) { - pre { - white-space: pre-wrap; - word-wrap: break-word; } } - pre code { - font-feature-settings: normal; - background: none !important; - color: #ccc; - margin: 0; - padding: 0; - font-size: inherit; } - -blockquote { - border-left: 2px solid; - margin: 40px; - padding: 10px 20px; } - @media (max-width: 684px) { - blockquote { - margin: 10px; - padding: 10px; } } - blockquote:before { - content: '”'; - font-family: Georgia, serif; - font-size: 3.875rem; - position: absolute; - left: -40px; - top: -20px; } - blockquote p:first-of-type { - margin-top: 0; } - blockquote p:last-of-type { - margin-bottom: 0; } - -/* Fix for gist integration */ -table:not(.js-file-line-container) { - table-layout: fixed; - border-collapse: collapse; - width: 100%; - margin: 40px 0; - border-radius: 5px; } - -/* Fix for gist integration */ -table, th, td:not(.js-line-number) { - border: 1px solid; - padding: 10px; } - -th { - background: var(--background-secondary); } - -ul, ol { - margin-left: 40px; - padding: 0; } - @media (max-width: 684px) { - ul, ol { - margin-left: 20px; } } -ol ol { - list-style-type: lower-alpha; } - -.container { - display: flex; - flex-direction: column; - justify-content: center; } - -.content { - display: flex; - flex-direction: column; - flex: 1 auto; - align-items: center; - justify-content: center; - margin: 50px 0; } - @media (max-width: 684px) { - .content { - margin-top: 0; } } -hr { - width: 100%; - border: none; - background: var(--border-color); - height: 1px; } - -.hidden { - display: none; } - -.framed { - padding: 50px; - margin: 0 -50px 40px; - border-radius: 10px; - border: 1px solid var(--border-color); - width: 100%; - max-width: 860px; } - @media (max-width: 900px) { - .framed { - width: auto; - max-width: 680px; - margin: 20px 20px 40px; - padding: 30px; } } -blockquote.twitter-tweet { - background: rgba(44, 124, 186, 0.1); - border: none; - padding: 30px; - color: inherit; - font-size: inherit; - line-height: inherit; - border-radius: 8px; } - -.h-anchor { - margin-left: 1px; - color: var(--color-secondary); - text-decoration: none; - visibility: hidden; - opacity: 0; - transition: visibility 0s linear 0.1s, opacity 0.1s linear; } - -h1:hover a, -h2:hover a, -h3:hover a, -h4:hover a { - visibility: visible; - opacity: 1; - transition-delay: 0s; } - -.framed .h-anchor { - visibility: hidden; } - -.post { - width: 100%; - max-width: 800px; - text-align: left; - padding: 20px; - margin: 20px auto; } - @media (max-width: 900px) { - .post { - max-width: 660px; } } - .post:not(:last-of-type) { - border-bottom: 1px solid var(--border-color); } - .post-meta { - font-size: 1rem; - margin-bottom: 10px; } - @media (max-width: 684px) { - .post-meta { - font-size: .85rem; } } - .post-title { - font-size: 2.625rem; - margin: 0 0 20px; } - @media (max-width: 684px) { - .post-title { - font-size: 2rem; } } - .post-title a { - color: #618375; - text-decoration: none; } - .post-tags { - display: block; - margin-bottom: 20px; - font-size: 1rem; - opacity: .5; } - .post-tags a { - text-decoration: none; } - .post-content { - margin-top: 30px; } - .post-cover { - margin: 40px -50px; - width: 860px; - max-width: 860px; } - .post-cover img { - margin: 0 auto; - border-radius: 8px; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); } - @media (max-width: 900px) { - .post-cover { - margin: 20px 0; - width: 100%; } } -.post--regulation h1 { - justify-content: center; } - -.post--regulation h2 { - justify-content: center; - margin-bottom: 10px; } - .post--regulation h2 + h2 { - margin-top: -10px; - margin-bottom: 20px; } - -.pagination { - margin-top: 50px; } - .pagination__title { - display: flex; - text-align: center; - position: relative; - margin: 100px 0 20px; } - .pagination__title-h { - text-align: center; - margin: 0 auto; - padding: 5px 10px; - background: var(--background); - color: var(--color-secondary); - font-size: .8rem; - text-transform: uppercase; - text-decoration: none; - letter-spacing: .1em; - z-index: 1; } - .pagination__title hr { - position: absolute; - left: 0; - right: 0; - width: 100%; - margin-top: 15px; - z-index: 0; } - .pagination__buttons { - display: flex; - align-items: center; - justify-content: center; } - .pagination__buttons a { - text-decoration: none; - font-weight: bold; } - -.button { - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - background: var(--background-secondary); - font-size: 1rem; - font-weight: 500; - border-radius: 8px; - max-width: 40%; - padding: 0; - cursor: pointer; - appearance: none; } - .button + .button { - margin-left: 10px; } - .button a { - display: flex; - padding: 8px 16px; - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; } - .button__text { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; } - .button.next .button__icon { - margin-left: 8px; } - .button.previous .button__icon { - margin-right: 8px; } - -.footer { - padding: 40px 20px; - flex-grow: 0; - color: var(--color-secondary); } - .footer__inner { - display: flex; - align-items: center; - justify-content: space-between; - margin: 0 auto; - width: 760px; - max-width: 100%; } - @media (max-width: 900px) { - .footer__inner { - flex-direction: column; } } - .footer a { - color: inherit; } - .footer .copyright { - display: flex; - flex-direction: row; - align-items: center; - font-size: 1rem; } - .footer .copyright--user { - margin: auto; - text-align: center; } - .footer .copyright > *:first-child:not(:only-child) { - border-right: 1px solid; - padding-right: 10px; - margin-right: 10px; } - @media (max-width: 900px) { - .footer .copyright > *:first-child:not(:only-child) { - border: none; - padding: 0; - margin: 0; } } - @media (max-width: 900px) { - .footer .copyright { - flex-direction: column; - margin-top: 10px; } } -.terms { - width: 100%; - max-width: 800px; - text-align: left; - padding: 20px; - margin: 0 auto; } - .terms__list { - padding: 0; - padding-left: 20px; - margin: 0; } - .terms__list a { - text-decoration: none; } - .terms__term { - margin-bottom: 15px; } - .terms__term-count { - background: var(--background-secondary); - font-size: 12px; - margin-left: 5px; - padding: 2px 10px; - border-radius: 5px; - text-decoration: none; } - -.archive { - width: 100%; - max-width: 800px; - text-align: left; - padding: 20px; - margin: 0 auto; } - .archive__group-month { - display: flex; - align-items: flex-start; - padding: 10px 0; } - @media (max-width: 684px) { - .archive__group-month { - flex-direction: column; } } - .archive__group-month:not(:last-of-type) { - border-bottom: 1px solid var(--border-color); } - .archive__group-year { - margin-top: 40px; } - @media (max-width: 684px) { - .archive__group-year { - margin-top: 20px; } } - .archive__group-year:not(:last-of-type) { - border-bottom: 1px solid var(--border-color); } - .archive__group-year-header { - margin: 10px 0; } - .archive__group-month-header { - margin: 25px 0; - width: 200px; - opacity: .5; } - @media (max-width: 684px) { - .archive__group-month-header { - margin: 10px 0 0; } } - .archive__group-posts { - width: 100%; } - .archive__post { - padding: 20px 0; } - .archive__post:not(:last-of-type) { - border-bottom: 1px solid var(--border-color); } - .archive__post-title { - margin: 5px 0; } - .archive__post-title a { - display: block; - text-decoration: none; } - -/* PrismJS 1.15.0 -https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+actionscript+apacheconf+applescript+c+csharp+bash+cpp+coffeescript+ruby+csp+css-extras+diff+django+docker+elixir+elm+markup-templating+erlang+fsharp+flow+git+go+graphql+less+handlebars+haskell+http+java+json+kotlin+latex+markdown+makefile+objectivec+ocaml+perl+php+php-extras+sql+processing+scss+python+jsx+typescript+reason+textile+rust+sass+stylus+scheme+pug+swift+yaml+haml+toml+twig+tsx+vim+visual-basic+wasm&plugins=line-numbers+toolbar+jsonp-highlight+command-line+copy-to-clipboard */ -/** - * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML - * Based on https://github.com/chriskempson/tomorrow-theme - * @author Rose Pritchard - */ -code[class*="language-"], -pre[class*="language-"] { - background: none; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - /* line-height: 1.5; */ - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; } - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; } - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #212020 !important; - color: inherit !important; - border-radius: 8px; } - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; - white-space: normal; } - -.token.comment, -.token.block-comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: rgba(255, 255, 255, 0.4); } - -.token.punctuation { - color: #a9a9b3; } - -.token.tag, -.token.attr-name, -.token.namespace, -.token.deleted { - color: #e2777a; } - -.token.function-name { - color: #6196cc; } - -.token.boolean, -.token.number, -.token.function { - color: #f08d49; } - -.token.property, -.token.class-name, -.token.constant, -.token.symbol { - color: #f8c555; } - -.token.selector, -.token.important, -.token.atrule, -.token.keyword, -.token.builtin { - color: #cc99cd; } - -.token.string, -.token.char, -.token.attr-value, -.token.regex, -.token.variable { - color: #7ec699; } - -.token.operator, -.token.entity, -.token.url { - color: #67cdcc; } - -.token.important, -.token.bold { - font-weight: bold; } - -.token.italic { - font-style: italic; } - -.token.entity { - cursor: help; } - -.token.inserted { - color: green; } - -pre[class*="language-"].line-numbers { - position: relative; - padding-left: 3.8em; - counter-reset: linenumber; } - -pre[class*="language-"].line-numbers > code { - position: relative; - white-space: inherit; } - -.line-numbers .line-numbers-rows { - position: absolute; - pointer-events: none; - top: 0; - font-size: 100%; - left: -3.8em; - width: 3em; - /* works for line-numbers below 1000 lines */ - letter-spacing: -1px; - border-right: 1px solid #999; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; } - -.line-numbers-rows > span { - pointer-events: none; - display: block; - counter-increment: linenumber; } - -.line-numbers-rows > span:before { - content: counter(linenumber); - color: #999; - display: block; - padding-right: 0.8em; - text-align: right; } - -div.code-toolbar { - position: relative; } - -div.code-toolbar > .toolbar { - position: absolute; - top: .3em; - right: .2em; - transition: opacity 0.3s ease-in-out; - opacity: 0; } - -div.code-toolbar:hover > .toolbar { - opacity: 1; } - -div.code-toolbar > .toolbar .toolbar-item { - display: inline-block; } - -div.code-toolbar > .toolbar a { - cursor: pointer; } - -div.code-toolbar > .toolbar button { - background: none; - border: 0; - color: inherit; - font: inherit; - line-height: normal; - overflow: visible; - padding: 0; - -webkit-user-select: none; - /* for button */ - -moz-user-select: none; - -ms-user-select: none; } - -div.code-toolbar > .toolbar a, -div.code-toolbar > .toolbar button, -div.code-toolbar > .toolbar span { - color: #bbb; - font-size: .8em; - padding: 0 .5em; - background: #f5f2f0; - background: rgba(224, 224, 224, 0.2); - box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); - border-radius: .5em; } - -div.code-toolbar > .toolbar a:hover, -div.code-toolbar > .toolbar a:focus, -div.code-toolbar > .toolbar button:hover, -div.code-toolbar > .toolbar button:focus, -div.code-toolbar > .toolbar span:hover, -div.code-toolbar > .toolbar span:focus { - color: inherit; - text-decoration: none; } - -.command-line-prompt { - border-right: 1px solid #999; - display: block; - float: left; - font-size: 100%; - letter-spacing: -1px; - margin-right: 1em; - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; } - -.command-line-prompt > span:before { - color: #999; - content: ' '; - display: block; - padding-right: 0.8em; } - -.command-line-prompt > span[data-user]:before { - content: "[" attr(data-user) "@" attr(data-host) "] $"; } - -.command-line-prompt > span[data-user="root"]:before { - content: "[" attr(data-user) "@" attr(data-host) "] #"; } - -.command-line-prompt > span[data-prompt]:before { - content: attr(data-prompt); } - -.collapsable-code { - position: relative; - width: 100%; - margin: 40px 0; } - .collapsable-code input[type="checkbox"] { - position: absolute; - visibility: hidden; } - .collapsable-code input[type="checkbox"]:checked ~ pre, - .collapsable-code input[type="checkbox"]:checked ~ .code-toolbar pre { - height: 0; - padding: 0; - border-top: none; } - .collapsable-code input[type="checkbox"]:checked ~ .code-toolbar { - padding: 0; - border-top: none; } - .collapsable-code input[type="checkbox"]:checked ~ .code-toolbar .toolbar { - display: none; } - .collapsable-code input[type="checkbox"]:checked ~ label { - border-radius: 10px; } - .collapsable-code input[type="checkbox"]:checked ~ label .collapsable-code__toggle:after { - content: attr(data-label-expand); } - .collapsable-code label { - position: relative; - display: flex; - justify-content: space-between; - background: var(--background-secondary); - padding: 10px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - min-width: 30px; - min-height: 30px; - margin: 0; - cursor: pointer; } - .collapsable-code__title { - flex: 1; - color: var(--color); - padding: 3px 10px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; } - .collapsable-code__language { - background: var(--background); - color: var(--color); - border-radius: 10px; - padding: 3px 10px; } - .collapsable-code__toggle { - color: var(--color); - font-size: 16px; - padding: 3px 10px; } - .collapsable-code__toggle:after { - content: attr(data-label-collapse); } - .collapsable-code pre { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; } - .collapsable-code pre::first-line { - line-height: 0; } - .collapsable-code code::first-line { - line-height: 0; } - .collapsable-code .code-toolbar { - margin: 0; } diff --git a/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.json b/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.json deleted file mode 100644 index 28c014b..0000000 --- a/resources/_gen/assets/scss/css/style.scss_f120a3f402b106f64b18d498afd3d82e.json +++ /dev/null @@ -1 +0,0 @@ -{"Target":"css/style.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/scripts/generate-og-images.js b/scripts/generate-og-images.js new file mode 100644 index 0000000..bbc9297 --- /dev/null +++ b/scripts/generate-og-images.js @@ -0,0 +1,180 @@ +import { createCanvas, loadImage, GlobalFonts } from "@napi-rs/canvas"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Registra il font JetBrains Mono +const fontPath = path.join( + __dirname, + "../static/fonts/JetBrainsMono-Medium.ttf", +); +GlobalFonts.registerFromPath(fontPath, "JetBrains Mono"); + +// Configurazione (come in Hugo) +const config = { + x: 141, + y: 300, + fontSize: 55, + color: "#ffffff", + lineSpacing: 1.2, + maxWidth: 1080, // larghezza massima per il testo + basePngPath: path.join(__dirname, "../og_base.png"), +}; + +/** + * Genera un'immagine OpenGraph con il titolo sovrapposto + * @param {string} title - Il titolo da scrivere + * @param {string} outputPath - Percorso dove salvare l'immagine + */ +export async function generateOGImage(title, outputPath) { + try { + // Carica l'immagine base + const baseImage = await loadImage(config.basePngPath); + + // Crea canvas con le stesse dimensioni dell'immagine base + const canvas = createCanvas(baseImage.width, baseImage.height); + const ctx = canvas.getContext("2d"); + + // Disegna l'immagine base + ctx.drawImage(baseImage, 0, 0); + + // Configura il testo + ctx.font = `${config.fontSize}px "JetBrains Mono"`; + ctx.fillStyle = config.color; + ctx.textBaseline = "top"; + + // Gestisci il text wrapping + const lines = wrapText(ctx, title, config.maxWidth); + + // Disegna ogni linea + lines.forEach((line, index) => { + const y = config.y + index * config.fontSize * config.lineSpacing; + ctx.fillText(line, config.x, y); + }); + + // Salva l'immagine + const dir = path.dirname(outputPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + const buffer = canvas.toBuffer("image/png"); + fs.writeFileSync(outputPath, buffer); + + console.log(`✓ Generated OG image: ${outputPath}`); + return outputPath; + } catch (error) { + console.error(`✗ Error generating OG image for "${title}":`, error); + throw error; + } +} + +/** + * Divide il testo in più righe se necessario + * @param {CanvasRenderingContext2D} ctx + * @param {string} text + * @param {number} maxWidth + * @returns {string[]} + */ +function wrapText(ctx, text, maxWidth) { + const words = text.split(" "); + const lines = []; + let currentLine = words[0]; + + for (let i = 1; i < words.length; i++) { + const word = words[i]; + const width = ctx.measureText(currentLine + " " + word).width; + + if (width < maxWidth) { + currentLine += " " + word; + } else { + lines.push(currentLine); + currentLine = word; + } + } + lines.push(currentLine); + + return lines; +} + +/** + * Genera immagini OG per tutti i contenuti markdown + */ +export async function generateAllOGImages() { + const contentDir = path.join(__dirname, "../content"); + const publicDir = path.join(__dirname, "../public/og"); + + // Leggi tutti i file markdown + const files = getAllMarkdownFiles(contentDir); + + console.log(`\nGenerating OpenGraph images for ${files.length} files...\n`); + + for (const file of files) { + const content = fs.readFileSync(file, "utf-8"); + const title = extractTitle(content); + + if (title) { + const relativePath = path.relative(contentDir, file); + const slug = relativePath.replace(/\.md$/, "").replace(/\\/g, "/"); + const outputPath = path.join(publicDir, `${slug}.png`); + + await generateOGImage(title, outputPath); + } + } + + console.log(`\nAll OpenGraph images generated!\n`); +} + +/** + * Trova tutti i file markdown ricorsivamente + * @param {string} dir + * @returns {string[]} + */ +function getAllMarkdownFiles(dir, fileList = []) { + const files = fs.readdirSync(dir); + + files.forEach((file) => { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + getAllMarkdownFiles(filePath, fileList); + } else if (file.endsWith(".md") && !file.startsWith("_")) { + fileList.push(filePath); + } + }); + + return fileList; +} + +/** + * Estrae il titolo dal frontmatter o dal primo heading + * @param {string} content + * @returns {string|null} + */ +function extractTitle(content) { + // Cerca nel frontmatter + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (frontmatterMatch) { + const titleMatch = frontmatterMatch[1].match(/title:\s*['"](.*?)['"]/); + if (titleMatch) return titleMatch[1]; + } + + // Cerca nel primo heading + const headingMatch = content.match(/^#\s+(.+)$/m); + if (headingMatch) return headingMatch[1]; + + return null; +} + +// Esegui lo script se chiamato direttamente +if (import.meta.url.startsWith("file:")) { + const modulePath = fileURLToPath(import.meta.url); + const scriptPath = process.argv[1]; + if (modulePath === scriptPath) { + generateAllOGImages().catch(console.error); + } +} diff --git a/scripts/new-content.js b/scripts/new-content.js new file mode 100644 index 0000000..a8a7db7 --- /dev/null +++ b/scripts/new-content.js @@ -0,0 +1,185 @@ +import fs from "node:fs/promises"; +import path from "node:path"; + +function printUsage() { + console.log( + "Usage: pnpm new-content [--title ] [--date <date>] [--author <author>] [--force]", + ); + console.log("Examples:"); + console.log(" pnpm new-content events/new-event"); + console.log( + ' pnpm new-content content/projects/new-tool.md --title "New Tool"', + ); +} + +function parseArgs(argv) { + const args = argv.slice(2); + + if (args.length === 0 || args.includes("--help") || args.includes("-h")) { + printUsage(); + process.exit(0); + } + + const options = { + target: null, + title: null, + date: null, + author: null, + force: false, + }; + + let i = 0; + while (i < args.length) { + const current = args[i]; + + if (!current.startsWith("--") && options.target === null) { + options.target = current; + i += 1; + continue; + } + + if (current === "--force") { + options.force = true; + i += 1; + continue; + } + + if ( + current === "--title" || + current === "--date" || + current === "--author" + ) { + const value = args[i + 1]; + if (!value || value.startsWith("--")) { + throw new Error(`Missing value for ${current}`); + } + + if (current === "--title") options.title = value; + if (current === "--date") options.date = value; + if (current === "--author") options.author = value; + i += 2; + continue; + } + + throw new Error(`Unknown argument: ${current}`); + } + + if (!options.target) { + throw new Error("Missing target path"); + } + + return options; +} + +function toLocalIsoWithTimezone(date = new Date()) { + const pad = (n) => String(n).padStart(2, "0"); + + const year = date.getFullYear(); + const month = pad(date.getMonth() + 1); + const day = pad(date.getDate()); + const hours = pad(date.getHours()); + const minutes = pad(date.getMinutes()); + const seconds = pad(date.getSeconds()); + + const tzMinutes = -date.getTimezoneOffset(); + const sign = tzMinutes >= 0 ? "+" : "-"; + const tzAbs = Math.abs(tzMinutes); + const tzHours = pad(Math.floor(tzAbs / 60)); + const tzMins = pad(tzAbs % 60); + + return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${sign}${tzHours}:${tzMins}`; +} + +function slugToTitle(filePath) { + const slug = path.basename(filePath, ".md"); + return slug + .replace(/[-_]+/g, " ") + .replace(/\s+/g, " ") + .trim() + .replace(/\b\w/g, (ch) => ch.toUpperCase()); +} + +function escapeYamlString(value) { + return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); +} + +function resolveTargetPath(targetArg, contentRoot) { + let normalized = targetArg.replace(/\\/g, "/").replace(/^\.\//, ""); + + if (normalized.startsWith("content/")) { + normalized = normalized.slice("content/".length); + } + + if (!normalized || normalized.endsWith("/")) { + throw new Error( + "Target must be a markdown file path, for example: events/my-event.md", + ); + } + + if (!normalized.toLowerCase().endsWith(".md")) { + normalized = `${normalized}.md`; + } + + const absolute = path.resolve(contentRoot, normalized); + const contentPrefix = contentRoot.endsWith(path.sep) + ? contentRoot + : `${contentRoot}${path.sep}`; + + if (absolute !== contentRoot && !absolute.startsWith(contentPrefix)) { + throw new Error("Target path must stay inside content/"); + } + + return absolute; +} + +async function main() { + const { target, title, date, author, force } = parseArgs(process.argv); + + const repoRoot = process.cwd(); + const contentRoot = path.resolve(repoRoot, "content"); + const archetypePath = path.resolve(repoRoot, "archetypes", "default.md"); + const targetPath = resolveTargetPath(target, contentRoot); + + const resolvedTitle = title ?? slugToTitle(targetPath); + const resolvedDate = date ?? toLocalIsoWithTimezone(new Date()); + const resolvedAuthor = author ?? "ADMStaff"; + + const [template, existing] = await Promise.all([ + fs.readFile(archetypePath, "utf8"), + fs + .access(targetPath) + .then(() => true) + .catch(() => false), + ]); + + if (existing && !force) { + throw new Error( + `File already exists: ${path.relative(repoRoot, targetPath)} (use --force to overwrite)`, + ); + } + + let output = template; + output = output.replace( + /^title:\s*.*$/m, + `title: "${escapeYamlString(resolvedTitle)}"`, + ); + output = output.replace(/^date:\s*.*$/m, `date: ${resolvedDate}`); + output = output.replace( + /^author:\s*.*$/m, + `author: "${escapeYamlString(resolvedAuthor)}"`, + ); + + if (!output.endsWith("\n")) { + output += "\n"; + } + + await fs.mkdir(path.dirname(targetPath), { recursive: true }); + await fs.writeFile(targetPath, output, "utf8"); + + console.log(`Created: ${path.relative(repoRoot, targetPath)}`); +} + +main().catch((error) => { + console.error(`Error: ${error.message}`); + process.exit(1); +}); diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..a783efe --- /dev/null +++ b/src/App.vue @@ -0,0 +1,18 @@ +<template> + <div + data-theme="admtheme" + class="min-h-screen bg-base-100 text-base-content font-mono" + > + <Header /> + <main class="container mx-auto px-4 py-8"> + <RouterView /> + </main> + <Footer /> + </div> +</template> + +<script setup> +import { RouterView } from "vue-router"; +import Header from "./components/Header.vue"; +import Footer from "./components/Footer.vue"; +</script> diff --git a/src/assets/ADMstaff_logo-favicon.png b/src/assets/ADMstaff_logo-favicon.png new file mode 100644 index 0000000..62d1f29 --- /dev/null +++ b/src/assets/ADMstaff_logo-favicon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9fcca88b8e37cdcffe88b51e53075d52549978c1f009839f36674b09129e104 +size 9331 diff --git a/static/img/ADMstaff_logo-modern-light.png b/src/assets/ADMstaff_logo-modern-light.png similarity index 100% rename from static/img/ADMstaff_logo-modern-light.png rename to src/assets/ADMstaff_logo-modern-light.png diff --git a/static/img/ADMstaff_logo-modern-trasp.png b/src/assets/ADMstaff_logo-modern-trasp.png similarity index 100% rename from static/img/ADMstaff_logo-modern-trasp.png rename to src/assets/ADMstaff_logo-modern-trasp.png diff --git a/src/components/BlinkingLogo.vue b/src/components/BlinkingLogo.vue new file mode 100644 index 0000000..54d8b9a --- /dev/null +++ b/src/components/BlinkingLogo.vue @@ -0,0 +1,20 @@ +<template> + <div class="flex items-center justify-center"> + <img :src="src" :alt="alt" :class="imgClass" class="max-w-full h-auto" /> + <span class="blinking-cursor text-4xl text-primary ml-2"></span> + </div> +</template> + +<script setup> +defineProps({ + src: { + type: String, + default: "/img/ADMstaff_logo-modern.png", + }, + alt: { + type: String, + default: "ADMstaff logo", + }, + imgClass: String, +}); +</script> diff --git a/src/components/Footer.vue b/src/components/Footer.vue new file mode 100644 index 0000000..5b13acc --- /dev/null +++ b/src/components/Footer.vue @@ -0,0 +1,14 @@ +<template> + <footer class="bg-neutral border-t border-base-300 mt-16 py-6"> + <div class="container mx-auto px-4 text-center text-sm text-secondary"> + <p>© {{ new Date().getFullYear() }} {{ $t("footer.copyright") }}</p> + <p class="mt-2">{{ $t("footer.tagline") }}</p> + </div> + </footer> +</template> + +<script setup> +import { useI18n } from "vue-i18n"; + +const { t } = useI18n(); +</script> diff --git a/src/components/Header.vue b/src/components/Header.vue new file mode 100644 index 0000000..b6aaa18 --- /dev/null +++ b/src/components/Header.vue @@ -0,0 +1,138 @@ +<template> + <header class="bg-neutral border-b border-base-300"> + <nav class="container mx-auto px-4"> + <div class="navbar min-h-16 px-0"> + <div class="navbar-start"> + <RouterLink + to="/" + class="group inline-flex shrink-0 items-center font-bold no-underline" + > + <span class="mr-1 inline-flex items-center"> + <svg + xmlns="http://www.w3.org/2000/svg" + class="h-3.5 w-3.5 text-base-content/70" + viewBox="0 0 44 44" + > + <path + fill="none" + class="stroke-current stroke-[6]" + d="M15 8l14.729 14.382L15 35.367" + /> + </svg> + </span> + <span + class="inline text-lg text-base-content/70 transition-colors group-hover:text-primary" + >ADMStaff</span + > + <span class="blinking-cursor ml-1"></span> + </RouterLink> + </div> + + <div class="navbar-center hidden lg:flex"> + <ul class="menu menu-horizontal px-1 gap-1"> + <li v-for="link in links" :key="link.path"> + <RouterLink + :to="link.path" + class="text-base-content hover:text-primary" + > + {{ $t(link.nameKey) }} + </RouterLink> + </li> + </ul> + </div> + + <div class="navbar-end gap-2"> + <div class="join hidden lg:flex"> + <button + v-for="lang in languages" + :key="`desktop-${lang.code}`" + @click="setLocale(lang.code)" + :class="languageBtnClass(lang.code)" + > + {{ lang.label }} + </button> + </div> + + <div class="dropdown dropdown-end lg:hidden"> + <label + tabindex="0" + class="btn btn-ghost btn-square" + aria-label="Open navigation menu" + > + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + class="h-5 w-5 stroke-current" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + d="M4 6h16M4 12h16M4 18h16" + /> + </svg> + </label> + <ul + tabindex="0" + class="menu menu-sm dropdown-content mt-3 z-[1] w-56 rounded-box border border-base-300 bg-base-100 p-2 shadow" + > + <li v-for="link in links" :key="`mobile-${link.path}`"> + <RouterLink :to="link.path">{{ $t(link.nameKey) }}</RouterLink> + </li> + <li class="menu-title"><span>Language</span></li> + <li> + <div class="join justify-start"> + <button + v-for="lang in languages" + :key="`mobile-${lang.code}`" + @click="setLocale(lang.code)" + :class="languageBtnClass(lang.code, true)" + > + {{ lang.label }} + </button> + </div> + </li> + </ul> + </div> + </div> + </div> + </nav> + </header> +</template> + +<script setup> +import { RouterLink } from "vue-router"; +import { useI18n } from "vue-i18n"; + +const { locale } = useI18n(); + +const links = [ + { path: "/about", nameKey: "nav.about" }, + { path: "/wiki", nameKey: "nav.wiki" }, + { path: "/events", nameKey: "nav.events" }, + { path: "/projects", nameKey: "nav.projects" }, + { path: "/media", nameKey: "nav.media" }, + { path: "/lab", nameKey: "nav.lab" }, +]; + +const languages = [ + { code: "it", label: "IT" }, + { code: "en", label: "EN" }, +]; + +function languageBtnClass(code, isMobile = false) { + if (locale.value === code) { + return "btn btn-sm join-item btn-primary text-white"; + } + + return isMobile + ? "btn btn-sm join-item btn-ghost" + : "btn btn-sm join-item btn-ghost text-base-content hover:text-primary"; +} + +function setLocale(lang) { + locale.value = lang; + localStorage.setItem("locale", lang); +} +</script> diff --git a/src/components/Layout.vue b/src/components/Layout.vue new file mode 100644 index 0000000..e9b067a --- /dev/null +++ b/src/components/Layout.vue @@ -0,0 +1,81 @@ +<template> + <div class="min-h-screen bg-base-100"> + <!-- Header --> + <header class="border-b border-base-300 bg-neutral"> + <nav class="container mx-auto px-4 py-4"> + <div class="flex justify-between items-center"> + <router-link + to="/" + class="text-2xl font-bold text-primary hover:opacity-80" + > + ADMStaff<span class="blinking-cursor">_</span> + </router-link> + + <div class="flex gap-6"> + <router-link + to="/about" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + About + </router-link> + <router-link + to="/wiki" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + Wiki + </router-link> + <router-link + to="/events" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + Events + </router-link> + <router-link + to="/projects" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + Projects + </router-link> + <router-link + to="/media" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + Media + </router-link> + <router-link + to="/lab" + class="hover:text-primary transition-colors" + active-class="text-primary font-semibold" + > + Lab + </router-link> + </div> + </div> + </nav> + </header> + + <!-- Main Content --> + <main class="container mx-auto px-4 py-8"> + <slot /> + </main> + + <!-- Footer --> + <footer class="border-t border-base-300 bg-neutral mt-16"> + <div + class="container mx-auto px-4 py-6 text-center text-sm text-secondary" + > + <p>© {{ new Date().getFullYear() }} ADMStaff</p> + <p class="mt-2">Services run by students, for students since 1994</p> + </div> + </footer> + </div> +</template> + +<script setup> +import { RouterLink } from "vue-router"; +</script> diff --git a/src/composables/useContent.js b/src/composables/useContent.js new file mode 100644 index 0000000..5eac56a --- /dev/null +++ b/src/composables/useContent.js @@ -0,0 +1,179 @@ +import { ref, onMounted, watch } from "vue"; +import { parseMarkdown } from "../utils/markdownParser.js"; +import { useI18n } from "vue-i18n"; + +/** + * Composable per caricare contenuti markdown dalla directory content/ + * Usa import.meta.glob di Vite per importare i file direttamente + */ + +// Importa tutti i file markdown dalla directory content (più specifico) +const contentFiles = import.meta.glob( + ["/content/**/*.md", "!**/node_modules/**", "!**/public/**"], + { query: "?raw", import: "default", eager: false }, +); + +export function useContent(path) { + const { locale } = useI18n(); + const content = ref(null); + const loading = ref(true); + const error = ref(null); + + const loadContent = async () => { + try { + loading.value = true; + error.value = null; + + const candidates = + locale.value === "en" + ? [`/content/en/${path}.md`, `/content/${path}.md`] + : [`/content/${path}.md`]; + + const resolvedPath = candidates.find( + (candidate) => !!contentFiles[candidate], + ); + + if (!resolvedPath) { + throw new Error(`File not found (tried): ${candidates.join(", ")}`); + } + + const rawContent = await contentFiles[resolvedPath](); + content.value = parseMarkdown(rawContent); + loading.value = false; + } catch (e) { + console.error("Error loading content:", e); + error.value = e; + loading.value = false; + } + }; + + onMounted(loadContent); + watch(locale, loadContent); + + return { content, loading, error, reload: loadContent }; +} + +/** + * Composable per caricare lista di contenuti (es. tutti gli eventi) + */ +export function useContentList(pattern) { + const { locale } = useI18n(); + const items = ref([]); + const loading = ref(true); + const error = ref(null); + + const loadList = async () => { + try { + loading.value = true; + error.value = null; + + // console.log("=== DEBUG useContentList ==="); + // console.log("Pattern received:", pattern); + // console.log("All available content files:", Object.keys(contentFiles)); + + let basePath = pattern; + if (basePath.startsWith("/content/")) { + basePath = basePath.slice("/content/".length); + } + basePath = basePath.replace(/^\/+|\/+$/g, ""); + + const defaultDir = `/content/${basePath}`; + const localizedDir = + locale.value === "en" ? `/content/en/${basePath}` : defaultDir; + + // console.log("Search path:", localizedDir); + + const filesInDir = (dir) => + Object.entries(contentFiles).filter(([fullPath]) => { + const pathDir = fullPath.substring(0, fullPath.lastIndexOf("/")); + const matches = pathDir === dir && !fullPath.endsWith("_index.md"); + // if (matches) console.log("✓ Matched file:", fullPath); + return matches; + }); + + const localizedEntries = filesInDir(localizedDir); + let matchingFiles = localizedEntries; + + if (locale.value === "en") { + const fallbackEntries = filesInDir(defaultDir); + const localizedSlugs = new Set( + localizedEntries.map(([fullPath]) => + fullPath.split("/").pop().replace(".md", ""), + ), + ); + + const fallbackOnlyEntries = fallbackEntries.filter(([fullPath]) => { + const slug = fullPath.split("/").pop().replace(".md", ""); + return !localizedSlugs.has(slug); + }); + + matchingFiles = [...localizedEntries, ...fallbackOnlyEntries]; + } + + // console.log("Total matching files:", matchingFiles.length); + + const contents = await Promise.all( + matchingFiles.map(async ([fullPath, loader]) => { + try { + // console.log("Loading file:", fullPath); + const raw = await loader(); + const parsed = parseMarkdown(raw); + // console.log("Parsed:", { + // title: parsed.frontmatter.title, + // date: parsed.frontmatter.date, + // }); + + // Estrai slug dal path + const pathParts = fullPath.split("/"); + const fileName = pathParts[pathParts.length - 1].replace(".md", ""); + + return { + path: fullPath, + slug: fileName, + ...parsed, + }; + } catch (e) { + console.error(`Error loading ${fullPath}:`, e); + return null; + } + }), + ); + + // Filtra i null e ordina per data + const validContents = contents.filter((c) => c !== null); + // console.log( + // "Valid contents:", + // validContents.length, + // validContents.map((c) => ({ + // title: c.frontmatter.title, + // date: c.frontmatter.date, + // })), + // ); + + items.value = validContents.sort((a, b) => { + // Ordina dal più recente al meno recente + if (a.frontmatter?.date && b.frontmatter?.date) { + const dateA = new Date(a.frontmatter.date); + const dateB = new Date(b.frontmatter.date); + return dateB - dateA; // Ordine decrescente (più recente prima) + } + // Se manca la data, metti alla fine + if (!a.frontmatter?.date) return 1; + if (!b.frontmatter?.date) return -1; + return 0; + }); + + // console.log("Final items:", items.value.length); + loading.value = false; + } catch (e) { + console.error("Error loading content list:", e); + error.value = e; + loading.value = false; + } + }; + + onMounted(loadList); + watch(locale, loadList); + + return { items, loading, error, reload: loadList }; +} diff --git a/src/composables/useMeta.js b/src/composables/useMeta.js new file mode 100644 index 0000000..ac96c01 --- /dev/null +++ b/src/composables/useMeta.js @@ -0,0 +1,64 @@ +import { useHead } from "@vueuse/head"; +import { computed } from "vue"; + +/** + * Composable per gestire i meta tag OpenGraph + * @param {Object} options - Opzioni per i meta tag + * @param {string} options.title - Titolo della pagina + * @param {string} options.description - Descrizione della pagina + * @param {string} options.image - Path relativo dell'immagine OG (es: 'events/cavalieri') + * @param {string} options.url - URL completo della pagina + * @param {string} [options.type='website'] - Tipo di contenuto OG + */ +export function useMeta(options) { + const { + title, + description = "ADMStaff - gruppo di studenti di Informatica dell'Università di Bologna", + image, + url, + type = "website", + } = options; + + // Genera il percorso completo dell'immagine OG + const ogImageUrl = computed(() => { + if (!image) return null; + + // Se è già un URL completo, usalo così com'è + if (image.startsWith("http")) return image; + + // Altrimenti costruisci il path dall'immagine generata + const baseUrl = window.location.origin; + const imagePath = image.startsWith("/") ? image : `/og/${image}.png`; + return `${baseUrl}${imagePath}`; + }); + + // Configura i meta tag + useHead({ + title: computed(() => `${title} | ADMStaff`), + meta: [ + // Description + { name: "description", content: description }, + + // OpenGraph + { property: "og:title", content: computed(() => `${title} | ADMStaff`) }, + { property: "og:description", content: description }, + { property: "og:type", content: type }, + { property: "og:url", content: url }, + ...(ogImageUrl.value + ? [ + { property: "og:image", content: ogImageUrl.value }, + { property: "og:image:width", content: "1200" }, + { property: "og:image:height", content: "630" }, + ] + : []), + + // Twitter Card + { name: "twitter:card", content: "summary_large_image" }, + { name: "twitter:title", content: computed(() => `${title} | ADMStaff`) }, + { name: "twitter:description", content: description }, + ...(ogImageUrl.value + ? [{ name: "twitter:image", content: ogImageUrl.value }] + : []), + ], + }); +} diff --git a/src/i18n/index.js b/src/i18n/index.js new file mode 100644 index 0000000..ddc5bcf --- /dev/null +++ b/src/i18n/index.js @@ -0,0 +1,15 @@ +import { createI18n } from "vue-i18n"; +import it from "./locales/it.json"; +import en from "./locales/en.json"; + +const i18n = createI18n({ + legacy: false, + locale: localStorage.getItem("locale") || "it", + fallbackLocale: "it", + messages: { + it, + en, + }, +}); + +export default i18n; diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json new file mode 100644 index 0000000..1aa757a --- /dev/null +++ b/src/i18n/locales/en.json @@ -0,0 +1,15 @@ +{ + "nav": { + "home": "Home", + "about": "About", + "projects": "Projects", + "events": "Events", + "wiki": "Wiki", + "media": "Media", + "lab": "Lab" + }, + "footer": { + "copyright": "ADMStaff", + "tagline": "Services run by students, for students since 1994" + } +} diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json new file mode 100644 index 0000000..6132fbd --- /dev/null +++ b/src/i18n/locales/it.json @@ -0,0 +1,15 @@ +{ + "nav": { + "home": "Home", + "about": "Chi Siamo", + "projects": "Progetti", + "events": "Eventi", + "wiki": "Wiki", + "media": "Media", + "lab": "Laboratorio" + }, + "footer": { + "copyright": "ADMStaff", + "tagline": "Servizi da studenti, per studenti dal 1994" + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..29c6460 --- /dev/null +++ b/src/main.js @@ -0,0 +1,36 @@ +import { createApp } from "vue"; +import { createRouter, createWebHistory } from "vue-router"; +import { createHead } from "@vueuse/head"; +import App from "./App.vue"; +import i18n from "./i18n"; +import "./style.css"; + +// Views +import HomeView from "./views/HomeView.vue"; +import AboutView from "./views/AboutView.vue"; + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { path: "/", component: HomeView }, + { path: "/about", component: AboutView }, + { path: "/wiki", component: () => import("./views/WikiView.vue") }, + { path: "/wiki/:slug", component: () => import("./views/WikiView.vue") }, + { path: "/events", component: () => import("./views/EventsView.vue") }, + { + path: "/events/:slug", + component: () => import("./views/EventDetailView.vue"), + }, + { path: "/projects", component: () => import("./views/ProjectsView.vue") }, + { + path: "/projects/:slug", + component: () => import("./views/ProjectDetailView.vue"), + }, + { path: "/media", component: () => import("./views/MediaView.vue") }, + { path: "/lab", component: () => import("./views/LabView.vue") }, + ], +}); + +const head = createHead(); + +createApp(App).use(router).use(i18n).use(head).mount("#app"); diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..1605f74 --- /dev/null +++ b/src/style.css @@ -0,0 +1,203 @@ +@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"); + +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + /* Semantic tokens backed by DaisyUI theme colors */ + --adm-color-primary: oklch(var(--p)); + --adm-color-primary-contrast: oklch(var(--pc)); + --adm-color-surface: oklch(var(--b1)); + --adm-color-surface-muted: oklch(var(--b2)); + --adm-color-border: oklch(var(--b3)); + --adm-color-text: oklch(var(--bc)); + --adm-color-text-muted: oklch(var(--bc) / 0.72); + --adm-color-neutral: oklch(var(--n)); +} + +html { + box-sizing: border-box; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + margin: 0; + padding: 0; + font-family: "JetBrains Mono", monospace; + font-size: 1rem; + font-weight: 400; + font-feature-settings: "liga", "tnum", "case", "calt", "zero", "ss01", "locl"; + line-height: 1.54; + background-color: var(--adm-color-surface); + color: var(--adm-color-text); + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -webkit-overflow-scrolling: touch; + -webkit-text-size-adjust: 100%; +} + +/* Cursore lampeggiante stile block */ +.blinking-cursor { + display: inline-block; + width: 0.625em; + height: 1em; + background: var(--adm-color-primary); + margin-left: 0.3em; + border-radius: 1px; + animation: cursor 1s infinite; + vertical-align: baseline; + transform: translateY(0.05em); +} + +@keyframes cursor { + 0% { + opacity: 0; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +/* Stile per markdown content */ +.markdown-content { + line-height: 1.7; +} + +/* Nascondi frontmatter se mai dovesse apparire */ +.markdown-content pre:first-child:has(code) { + display: none; +} + +.markdown-content h1, +.markdown-content h2, +.markdown-content h3 { + color: var(--adm-color-primary); + margin: 1.5rem 0 1rem; + font-weight: bold; +} + +.markdown-content h1 { + font-size: 2.25rem; +} + +.markdown-content h2 { + font-size: 1.875rem; +} + +.markdown-content h3 { + font-size: 1.5rem; +} + +.markdown-content p { + margin: 1rem 0; +} + +.markdown-content a { + color: var(--adm-color-primary); + text-decoration: underline; +} + +.markdown-content a:hover { + opacity: 0.8; +} + +.markdown-content ul, +.markdown-content ol { + margin: 1rem 0; + padding-left: 2rem; +} + +.markdown-content ul { + list-style: disc; +} + +.markdown-content ol { + list-style: decimal; +} + +.markdown-content li { + margin: 0.5rem 0; +} + +.markdown-content code { + background: var(--adm-color-surface-muted); + padding: 0.2rem 0.4rem; + border-radius: 3px; + font-family: "JetBrains Mono", monospace; +} + +.markdown-content pre { + background: var(--adm-color-surface-muted); + padding: 1rem; + border-radius: 5px; + overflow-x: auto; + margin: 1rem 0; +} + +.markdown-content pre code { + background: transparent; + padding: 0; +} + +.markdown-content img { + max-width: 100%; + height: auto; + border-radius: 5px; + margin: 1.5rem auto; + display: block; +} + +.markdown-content table { + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; +} + +.markdown-content table th, +.markdown-content table td { + border: 1px solid var(--adm-color-border); + padding: 0.75rem; + text-align: left; +} + +.markdown-content table th { + background: var(--adm-color-surface-muted); + color: var(--adm-color-primary); + font-weight: bold; +} + +.markdown-content table tr:hover { + background: var(--adm-color-neutral); +} + +.markdown-content blockquote { + border-left: 4px solid var(--adm-color-primary); + padding-left: 1rem; + margin: 1.5rem 0; + color: var(--adm-color-text-muted); + font-style: italic; +} + +.markdown-content hr { + border: none; + border-top: 1px solid var(--adm-color-border); + margin: 2rem 0; +} + +/* Utility per line-clamp */ +.line-clamp-3 { + display: -webkit-box; + line-clamp: 3; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} diff --git a/src/utils/assetPath.js b/src/utils/assetPath.js new file mode 100644 index 0000000..e723ada --- /dev/null +++ b/src/utils/assetPath.js @@ -0,0 +1,11 @@ +export function resolveAssetPath(url) { + if (!url) { + return ""; + } + + if (/^(?:[a-z][a-z0-9+.-]*:|\/|#)/i.test(url)) { + return url; + } + + return `/${url}`; +} diff --git a/src/utils/markdownParser.js b/src/utils/markdownParser.js new file mode 100644 index 0000000..83e99c3 --- /dev/null +++ b/src/utils/markdownParser.js @@ -0,0 +1,151 @@ +import { marked } from "marked"; + +// Configura marked per un output più pulito +marked.setOptions({ + breaks: true, + gfm: true, + headerIds: true, + mangle: false, +}); + +/** + * Parser YAML semplice per il frontmatter + * Supporta stringhe (con o senza quotes), numeri, booleani, date + */ +function parseYAMLFrontmatter(yamlContent) { + const frontmatter = {}; + const lines = yamlContent.split("\n"); + + for (const line of lines) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + + const colonIndex = trimmed.indexOf(":"); + if (colonIndex === -1) continue; + + const key = trimmed.substring(0, colonIndex).trim(); + let value = trimmed.substring(colonIndex + 1).trim(); + + // Rimuovi quotes singole o doppie + if ( + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")) + ) { + value = value.substring(1, value.length - 1); + } + + // Converti booleani + if (value === "true") value = true; + else if (value === "false") value = false; + // Non tentare mai di convertire a numero se la stringa contiene caratteri non numerici + else if (/^-?\d+\.?\d*$/.test(value)) value = Number(value); + + if (key === "cover") { + // console.log("Cover value parsed:", value, "type:", typeof value); + } + + frontmatter[key] = value; + } + + return frontmatter; +} + +/** + * Parser markdown che gestisce il frontmatter YAML come Hugo + * e converte gli shortcode Hugo in HTML + */ +export function parseMarkdown(content) { + try { + // Normalizza i line endings a \n + const normalizedContent = content + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .trim(); + + let frontmatter = {}; + let markdown = normalizedContent; + + // Estrai frontmatter se presente + if (normalizedContent.startsWith("---")) { + const endIndex = normalizedContent.indexOf("\n---", 3); + if (endIndex !== -1) { + const yamlContent = normalizedContent.substring(3, endIndex).trim(); + frontmatter = parseYAMLFrontmatter(yamlContent); + markdown = normalizedContent.substring(endIndex + 4).trim(); + } + } + + // Processa shortcode Hugo prima di convertire in HTML + const processedMarkdown = processHugoShortcodes(markdown); + const html = marked(processedMarkdown); + + return { + frontmatter, + body: markdown, + html, + }; + } catch (error) { + console.error("Error parsing markdown:", error); + // Fallback: rimuovi frontmatter manualmente + const cleanContent = content + .replace(/^---\r?\n[\s\S]*?\n---\r?\n/, "") + .trim(); + return { + frontmatter: {}, + body: cleanContent, + html: marked(cleanContent), + }; + } +} + +/** + * Processa gli shortcode Hugo e li converte in HTML/markdown compatibile + */ +function processHugoShortcodes(content) { + // Gestisci figure dentro link markdown: [{{< figure ... >}}](url) + content = content.replace( + /\[\{\{<\s*figure\s+src="([^"]+)"(?:\s+title="([^"]+)")?(?:\s+style="([^"]+)")?\s*>\}\}\]\(([^)]+)\)/g, + (match, src, title, style, linkUrl) => { + const styleAttr = style ? ` style="${style}"` : ""; + const altText = title || ""; + return `<a href="${linkUrl}" target="_blank"><img src="${src}" alt="${altText}"${styleAttr} class="mx-auto" /></a>`; + }, + ); + + // Gestisci figure standalone: {{< figure src="/img/..." title="..." style="..." >}} + content = content.replace( + /\{\{<\s*figure\s+src="([^"]+)"(?:\s+title="([^"]+)")?(?:\s+style="([^"]+)")?\s*>\}\}/g, + (match, src, title, style) => { + const styleAttr = style ? ` style="${style}"` : ""; + const altText = title || ""; + const caption = title ? `\n\n*${title}*` : ""; + return `<img src="${src}" alt="${altText}"${styleAttr} class="mx-auto" />${caption}`; + }, + ); + + return content; +} + +export async function loadMarkdownFile(path) { + try { + const response = await fetch(path); + if (!response.ok) { + throw new Error(`Failed to load ${path}`); + } + const text = await response.text(); + return parseMarkdown(text); + } catch (error) { + console.error("Error loading markdown:", error); + return null; + } +} + +export async function loadMarkdownFiles(paths) { + const results = await Promise.all( + paths.map(async (path) => { + const data = await loadMarkdownFile(path); + return { path, data }; + }), + ); + return results.filter((r) => r.data !== null); +} diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue new file mode 100644 index 0000000..25484d1 --- /dev/null +++ b/src/views/AboutView.vue @@ -0,0 +1,28 @@ +<template> + <div class="mx-auto flex flex-col md:flex-row gap-8 items-start"> + <img + src="/img/ADMstaff_logo-modern.png" + alt="ADMstaff logo" + class="md:w-96 md:sticky md:top-4 rounded-2xl" + /> + + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Error loading content</span> + </div> + + <div v-else class="markdown-content" v-html="content?.html"></div> + </div> +</template> + +<script setup> +import { useContent } from "../composables/useContent.js"; + +// Carica il file about.md dalla directory content/ +const { content, loading, error } = useContent("about"); +</script> diff --git a/src/views/EventDetailView.vue b/src/views/EventDetailView.vue new file mode 100644 index 0000000..65d78e6 --- /dev/null +++ b/src/views/EventDetailView.vue @@ -0,0 +1,100 @@ +<template> + <div class="max-w-4xl mx-auto"> + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Event not found</span> + <div class="mt-4"> + <RouterLink to="/events" class="text-primary hover:underline"> + ← Back to Events + </RouterLink> + </div> + </div> + + <article v-else> + <div class="mb-8"> + <RouterLink + to="/events" + class="text-primary hover:underline mb-4 inline-block" + > + ← Back to Events + </RouterLink> + + <img + v-if="content?.frontmatter.cover" + :src="resolveCover(content.frontmatter.cover)" + :alt="content.frontmatter.title" + class="w-full h-auto object-contain rounded-lg mb-6" + /> + + <h1 class="text-4xl font-bold text-primary mb-2"> + {{ content?.frontmatter.title }}<span class="blinking-cursor"></span> + </h1> + + <div class="flex gap-4 text-secondary mb-6"> + <span + v-if="content?.frontmatter.date" + class="flex items-center gap-1" + > + <Icon icon="mdi:calendar" class="w-4 h-4" /> + {{ + new Date(content.frontmatter.date).toLocaleDateString("it-IT", { + year: "numeric", + month: "long", + day: "numeric", + }) + }} + </span> + <span + v-if="content?.frontmatter.author" + class="flex items-center gap-1" + > + <Icon icon="mdi:account-edit" class="w-4 h-4" /> + {{ content.frontmatter.author }} + </span> + </div> + </div> + + <div class="markdown-content" v-html="content?.html"></div> + </article> + </div> +</template> + +<script setup> +import { RouterLink, useRoute } from "vue-router"; +import { useContent } from "../composables/useContent.js"; +import { useMeta } from "../composables/useMeta.js"; +import { computed, watch } from "vue"; +import { Icon } from "@iconify/vue"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +const route = useRoute(); +const slug = computed(() => route.params.slug); + +const resolveCover = (cover) => resolveAssetPath(cover); + +// Carica l'evento specifico basandosi sullo slug nella URL +const { content, loading, error } = useContent(`events/${slug.value}`); + +// Configura meta tag OpenGraph quando il contenuto è caricato +watch( + () => content.value, + (newContent) => { + if (newContent?.frontmatter) { + useMeta({ + title: newContent.frontmatter.title, + description: + newContent.frontmatter.description || newContent.frontmatter.title, + image: `events/${slug.value}`, + url: window.location.href, + type: "article", + }); + } + }, + { immediate: true }, +); +</script> diff --git a/src/views/EventsView.vue b/src/views/EventsView.vue new file mode 100644 index 0000000..1defe4a --- /dev/null +++ b/src/views/EventsView.vue @@ -0,0 +1,180 @@ +<template> + <div class="min-h-screen bg-base-100 text-base-content"> + <div class="container mx-auto px-4 py-8"> + <!-- Header --> + <div class="mb-12"> + <h1 class="text-5xl font-bold text-primary mb-4"> + Eventi<span class="blinking-cursor"></span> + </h1> + <p class="text-xl text-secondary"> + Workshop, talk e incontri della nostra community + </p> + </div> + + <!-- Loading State --> + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <!-- Error State --> + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Error loading events</span> + </div> + + <!-- Eventi in stile blog --> + <div v-else class="space-y-8"> + <!-- Evento in evidenza (primo) --> + <article + v-if="items.length > 0" + class="bg-base-200 rounded-lg overflow-hidden border border-base-300 hover:border-primary transition-all" + > + <RouterLink :to="`/events/${items[0].slug}`"> + <div class="grid md:grid-cols-2 gap-6"> + <img + v-if="items[0].frontmatter.cover" + :src="resolveCover(items[0].frontmatter.cover)" + :alt="items[0].frontmatter.title" + class="w-full h-full object-cover" + /> + <div + :class=" + items[0].frontmatter.cover ? 'p-8' : 'p-8 md:col-span-2' + " + class="flex flex-col justify-center" + > + <div + class="uppercase text-xs text-primary font-bold mb-2 flex items-center gap-1" + > + <Icon icon="mdi:pin" class="w-4 h-4" /> In Evidenza + </div> + <h2 + class="text-3xl font-bold mb-4 text-primary hover:text-base-content transition" + > + {{ items[0].frontmatter.title }} + </h2> + <div class="flex gap-4 text-sm text-secondary mb-4"> + <span + v-if="items[0].frontmatter.date" + class="flex items-center gap-1" + > + <Icon icon="mdi:calendar" class="w-4 h-4" /> + {{ formatDate(items[0].frontmatter.date) }} + </span> + <span + v-if="items[0].frontmatter.location" + class="flex items-center gap-1" + > + <Icon icon="mdi:map-marker" class="w-4 h-4" /> + {{ items[0].frontmatter.location }} + </span> + </div> + <div + class="text-base-content markdown-content line-clamp-3" + v-html="items[0].html" + ></div> + <div class="mt-4 text-primary font-bold hover:underline"> + Leggi di più → + </div> + </div> + </div> + </RouterLink> + </article> + + <!-- Altri eventi --> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> + <article + v-for="event in items.slice(1)" + :key="event.path" + class="bg-base-200 rounded-lg overflow-hidden border border-base-300 hover:border-primary transition-all group" + > + <RouterLink :to="`/events/${event.slug}`" class="block"> + <div + v-if="event.frontmatter.cover" + class="relative overflow-hidden h-48" + > + <img + :src="resolveCover(event.frontmatter.cover)" + :alt="event.frontmatter.title" + class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" + /> + </div> + <div class="p-6"> + <h2 + class="text-xl font-bold mb-2 text-primary group-hover:text-base-content transition" + > + {{ event.frontmatter.title }} + </h2> + <div class="flex flex-col gap-1 text-xs text-secondary mb-3"> + <span + v-if="event.frontmatter.date" + class="flex items-center gap-1" + > + <Icon icon="mdi:calendar" class="w-3 h-3" /> + {{ formatDate(event.frontmatter.date) }} + </span> + <span + v-if="event.frontmatter.location" + class="flex items-center gap-1" + > + <Icon icon="mdi:map-marker" class="w-3 h-3" /> + {{ event.frontmatter.location }} + </span> + </div> + <div + class="text-sm text-base-content markdown-content line-clamp-3" + v-html="event.html" + ></div> + </div> + </RouterLink> + </article> + </div> + + <!-- Empty State --> + <div v-if="items.length === 0" class="text-center py-20"> + <Icon + icon="mdi:calendar-blank" + class="w-16 h-16 mx-auto mb-4 text-secondary" + /> + <h3 class="text-2xl font-bold text-base-content mb-2"> + Nessun evento trovato + </h3> + <p class="text-secondary"> + Torna più tardi per vedere i prossimi eventi! + </p> + </div> + </div> + </div> + </div> +</template> + +<script setup> +import { RouterLink } from "vue-router"; +import { useContentList } from "../composables/useContent.js"; +import { Icon } from "@iconify/vue"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +// Carica tutti gli eventi dalla directory content/events/ +const { items, loading, error } = useContentList("/content/events/"); + +const resolveCover = (cover) => resolveAssetPath(cover); + +// Formatta la data +function formatDate(date) { + return new Date(date).toLocaleDateString("it-IT", { + day: "numeric", + month: "long", + year: "numeric", + }); +} +</script> + +<style scoped> +.line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} +</style> diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..616f711 --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,148 @@ +<template> + <div> + <!-- About Section con cursore --> + <div + class="flex flex-col md:flex-row md:items-center md:mx-[5%] mb-12 md:my-12 md:gap-5" + > + <img + src="@/assets/ADMstaff_logo-modern-trasp.png" + alt="ADMStaff Logo" + class="md:w-1/3" + /> + <h4 id="about-text" class="md:text-xl"> + ADMstaff nasce come gruppo che fornisce servizi da studenti per + studenti.<br /><br /> + Il nostro obiettivo è sperimentare e fare pratica su ciò che ci + appassiona e ci incuriosisce. <br />Tutto ciò che stuzzica la curiosità + è alla nostra portata<span class="blinking-cursor"></span> + </h4> + </div> + + <br /> + + <!-- Ultimi Eventi --> + <h1 class="mx-[5%] my-4 text-3xl font-bold text-primary md:my-8"> + Ultimi Eventi + </h1> + <div v-if="eventsLoading" class="text-center py-8"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + <div + v-else + class="mx-[5%] grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3" + > + <div + v-for="event in latestEvents" + :key="event.path" + class="overflow-hidden rounded-[20px] border border-transparent bg-base-200 p-2 transition-all duration-300 ease-in-out hover:-translate-y-1 hover:border-primary hover:shadow-[0_5px_15px_rgba(0,0,0,0.2)]" + > + <RouterLink + :to="`/events/${event.slug}`" + class="block text-inherit no-underline" + > + <img + v-if="event.frontmatter.cover" + :src="resolveCover(event.frontmatter.cover)" + :alt="event.frontmatter.title" + class="mb-4 w-full rounded-[10px]" + /> + <h2 class="mb-4 text-primary font-bold"> + {{ event.frontmatter.title }} + </h2> + <div + class="text-base-content" + v-html="truncate(event.html, 100)" + ></div> + </RouterLink> + </div> + </div> + + <br /> + + <!-- I nostri progetti --> + <h1 class="mx-[5%] my-4 text-3xl font-bold text-primary md:my-8"> + I nostri progetti + </h1> + <div v-if="projectsLoading" class="text-center py-8"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + <div + v-else + class="mx-[5%] grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4 md:gap-5" + > + <div + v-for="project in projects" + :key="project.path" + class="overflow-hidden rounded-[20px] border border-transparent bg-base-200 p-2 transition-all duration-300 ease-in-out hover:-translate-y-1 hover:border-primary hover:shadow-[0_5px_15px_rgba(0,0,0,0.2)]" + > + <RouterLink + :to="`/projects/${project.slug}`" + class="block text-inherit no-underline" + > + <div + v-if="project.frontmatter.cover" + class="mb-4 aspect-[16/9] w-full overflow-hidden rounded-[10px] flex items-center justify-center" + > + <img + :src="resolveCover(project.frontmatter.cover)" + :alt="project.frontmatter.title" + class="block h-auto w-full max-h-full object-contain object-center my-auto" + /> + </div> + <h2 class="mb-4 text-primary font-bold"> + {{ project.frontmatter.title }} + </h2> + <div + class="text-base-content" + v-html="truncate(project.html, 100)" + ></div> + </RouterLink> + </div> + </div> + </div> +</template> + +<script setup> +import { RouterLink } from "vue-router"; +import { useContentList } from "../composables/useContent.js"; +import { computed, onMounted, nextTick } from "vue"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +// Carica eventi e progetti +const { items: allEvents, loading: eventsLoading } = + useContentList("/content/events/"); +const { items: projects, loading: projectsLoading } = + useContentList("/content/projects/"); + +// Prendi solo gli ultimi 3 eventi +const latestEvents = computed(() => { + return allEvents.value.slice(0, 3); +}); + +// Funzione per troncare HTML mantenendo la formattazione +function truncate(html, length) { + if (!html) return ""; + const div = document.createElement("div"); + div.innerHTML = html; + const text = div.textContent || div.innerText || ""; + + if (text.length <= length) { + return html; + } + + // Tronca il testo e trova l'ultimo spazio + const truncated = text.substring(0, length); + const lastSpace = truncated.lastIndexOf(" "); + const finalText = + lastSpace > 0 ? truncated.substring(0, lastSpace) : truncated; + + // Restituisci HTML semplice + return `<p>${finalText}...</p>`; +} + +const resolveCover = (cover) => resolveAssetPath(cover); +</script> diff --git a/src/views/LabView.vue b/src/views/LabView.vue new file mode 100644 index 0000000..4a355f9 --- /dev/null +++ b/src/views/LabView.vue @@ -0,0 +1,38 @@ +<template> + <div class="max-w-6xl mx-auto"> + <h1 class="text-4xl text-primary mb-8"> + Lab<span class="blinking-cursor"></span> + </h1> + + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Error loading content</span> + </div> + + <div v-else class="flex flex-col md:flex-row gap-8"> + <div class="flex-1 markdown-content" v-html="content?.html"></div> + + <img + v-if="content?.frontmatter.cover" + :src="resolveCover(content.frontmatter.cover)" + :alt="content.frontmatter.title" + class="md:w-1/3 w-full h-auto object-contain rounded-lg" + /> + </div> + </div> +</template> + +<script setup> +import { useContent } from "../composables/useContent.js"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +// Carica il file lab.md dalla directory content/ +const { content, loading, error } = useContent("lab"); + +const resolveCover = (cover) => resolveAssetPath(cover); +</script> diff --git a/src/views/MediaView.vue b/src/views/MediaView.vue new file mode 100644 index 0000000..4ff8a5e --- /dev/null +++ b/src/views/MediaView.vue @@ -0,0 +1,26 @@ +<template> + <div class="max-w-4xl mx-auto"> + <h1 class="text-4xl text-primary mb-8"> + Media<span class="blinking-cursor"></span> + </h1> + + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Error loading content</span> + </div> + + <div v-else class="markdown-content" v-html="content?.html"></div> + </div> +</template> + +<script setup> +import { useContent } from "../composables/useContent.js"; + +// Carica il file wallpapers.md dalla directory content/media/ +const { content, loading, error } = useContent("media/wallpapers"); +</script> diff --git a/src/views/ProjectDetailView.vue b/src/views/ProjectDetailView.vue new file mode 100644 index 0000000..8aa440c --- /dev/null +++ b/src/views/ProjectDetailView.vue @@ -0,0 +1,57 @@ +<template> + <div class="max-w-4xl mx-auto"> + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <div v-else-if="error" class="text-center py-12"> + <span class="text-red-500">Project not found</span> + <div class="mt-4"> + <RouterLink to="/projects" class="text-primary hover:underline"> + ← Back to Projects + </RouterLink> + </div> + </div> + + <article v-else> + <div class="mb-8"> + <RouterLink + to="/projects" + class="text-primary hover:underline mb-4 inline-block" + > + ← Back to Projects + </RouterLink> + + <img + v-if="content?.frontmatter.cover" + :src="resolveCover(content.frontmatter.cover)" + :alt="content.frontmatter.title" + class="w-full h-auto max-h-[55vh] md:max-h-[65vh] rounded-lg object-contain mx-auto mb-6" + /> + + <h1 class="text-4xl font-bold text-primary mb-6"> + {{ content?.frontmatter.title }}<span class="blinking-cursor"></span> + </h1> + </div> + + <div class="markdown-content" v-html="content?.html"></div> + </article> + </div> +</template> + +<script setup> +import { RouterLink, useRoute } from "vue-router"; +import { useContent } from "../composables/useContent.js"; +import { computed } from "vue"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +const route = useRoute(); +const slug = computed(() => route.params.slug); + +const resolveCover = (cover) => resolveAssetPath(cover); + +// Carica il progetto specifico basandosi sullo slug nella URL +const { content, loading, error } = useContent(`projects/${slug.value}`); +</script> diff --git a/src/views/ProjectsView.vue b/src/views/ProjectsView.vue new file mode 100644 index 0000000..a2a9472 --- /dev/null +++ b/src/views/ProjectsView.vue @@ -0,0 +1,285 @@ +<template> + <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12"> + <section class="mb-10 lg:mb-14 max-w-3xl"> + <p class="text-xs uppercase tracking-[0.3em] text-secondary mb-3"> + Selected work + </p> + <h1 + class="text-4xl sm:text-5xl font-bold text-primary mb-4 leading-tight" + > + Projects<span class="blinking-cursor"></span> + </h1> + </section> + + <div v-if="loading" class="space-y-8"> + <div class="grid gap-6 lg:grid-cols-[1.25fr_0.75fr]"> + <div + class="animate-pulse rounded-3xl border border-base-300 bg-base-200/70 p-6 lg:p-8 min-h-[22rem]" + > + <div class="h-4 w-24 rounded bg-base-300 mb-6"></div> + <div class="h-10 w-3/4 rounded bg-base-300 mb-4"></div> + <div class="h-4 w-full rounded bg-base-300 mb-3"></div> + <div class="h-4 w-5/6 rounded bg-base-300 mb-8"></div> + <div class="mt-auto h-56 rounded-2xl bg-base-300"></div> + </div> + <div class="space-y-4"> + <div + v-for="index in 3" + :key="index" + class="animate-pulse rounded-3xl border border-base-300 bg-base-200/70 p-4" + > + <div class="aspect-[16/9] rounded-2xl bg-base-300 mb-4"></div> + <div class="h-5 w-2/3 rounded bg-base-300 mb-3"></div> + <div class="h-4 w-full rounded bg-base-300 mb-2"></div> + <div class="h-4 w-5/6 rounded bg-base-300"></div> + </div> + </div> + </div> + </div> + + <div v-else-if="error" class="text-center py-12"> + <div + class="max-w-md mx-auto rounded-3xl border border-base-300 bg-base-200 p-8" + > + <span class="text-red-500 block mb-4">Error loading projects</span> + <p class="text-base-content/75 mb-6"> + Non riesco a caricare l’elenco in questo momento. + </p> + <button + type="button" + class="inline-flex items-center justify-center rounded-full border border-primary px-5 py-2 text-primary hover:bg-primary hover:text-primary-content transition-colors" + @click="reload" + > + Riprova + </button> + </div> + </div> + + <div v-else class="space-y-8 lg:space-y-10"> + <article + v-if="featuredProject" + class="group overflow-hidden rounded-[2rem] border border-base-300 bg-base-200/80 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:border-primary/40" + > + <div class="grid lg:grid-cols-[1.2fr_0.8fr] min-h-[20rem]"> + <div + class="order-2 lg:order-1 p-6 sm:p-8 lg:p-10 flex flex-col justify-between gap-6" + > + <div> + <p + class="text-xs uppercase tracking-[0.28em] text-secondary mb-4" + > + Featured project + </p> + <h2 + class="text-3xl sm:text-4xl font-bold text-primary mb-4 leading-tight group-hover:text-base-content transition-colors" + > + {{ featuredProject.frontmatter.title }} + </h2> + <div + class="max-w-2xl text-base-content/80 leading-relaxed line-clamp-4" + v-html="getExcerpt(featuredProject.html, 220)" + ></div> + </div> + + <div class="flex flex-wrap items-center gap-3 text-sm"> + <RouterLink + :to="`/projects/${featuredProject.slug}`" + class="inline-flex items-center rounded-full border border-primary/50 px-4 py-2 text-primary hover:bg-primary hover:text-primary-content transition-colors" + > + Read more → + </RouterLink> + <a + v-if="featuredServiceLink" + :href="featuredServiceLink" + :target="isExternalLink(featuredServiceLink) ? '_blank' : null" + :rel=" + isExternalLink(featuredServiceLink) + ? 'noopener noreferrer' + : null + " + class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-4 py-2 text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors" + > + Vai al servizio + </a> + </div> + </div> + + <div class="order-1 lg:order-2 bg-base-300/30"> + <div + v-if="featuredProject.frontmatter.cover" + class="flex h-full min-h-[12rem] lg:min-h-[20rem] items-center justify-center overflow-hidden p-6 sm:p-8" + > + <img + :src="resolveCover(featuredProject.frontmatter.cover)" + :alt="featuredProject.frontmatter.title" + class="h-auto max-h-[10rem] w-full max-w-[20rem] object-contain transition-transform duration-500 group-hover:scale-[1.03]" + /> + </div> + <div + v-else + class="flex h-full min-h-[12rem] lg:min-h-[20rem] items-center justify-center p-8 text-secondary" + > + No cover available + </div> + </div> + </div> + </article> + + <div + v-if="items.length > 1" + class="grid gap-5 md:grid-cols-2 xl:grid-cols-3" + > + <article + v-for="project in items.slice(1)" + :key="project.path" + class="group overflow-hidden rounded-[1.75rem] border border-base-300 bg-base-200/70 transition-all duration-300 hover:-translate-y-1 hover:border-primary/40 hover:shadow-lg" + > + <div class="aspect-[16/10] overflow-hidden bg-base-300/30 p-4"> + <img + v-if="project.frontmatter.cover" + :src="resolveCover(project.frontmatter.cover)" + :alt="project.frontmatter.title" + class="h-full w-full object-contain transition-transform duration-500 group-hover:scale-[1.03]" + /> + <div + v-else + class="flex h-full items-center justify-center text-secondary" + > + No cover available + </div> + </div> + + <div class="p-5 sm:p-6"> + <h2 + class="text-xl sm:text-2xl font-bold text-primary mb-3 leading-snug group-hover:text-base-content transition-colors" + > + {{ project.frontmatter.title }} + </h2> + <div + class="text-base-content/75 line-clamp-3" + v-html="getExcerpt(project.html, 140)" + ></div> + <div class="mt-5 flex flex-wrap items-center gap-2 text-sm"> + <RouterLink + :to="`/projects/${project.slug}`" + class="inline-flex items-center rounded-full border border-primary/50 px-3 py-1.5 font-medium text-primary hover:bg-primary hover:text-primary-content transition-colors" + > + Read more + </RouterLink> + <a + v-if="getProjectLink(project)" + :href="getProjectLink(project)" + :target=" + isExternalLink(getProjectLink(project)) ? '_blank' : null + " + :rel=" + isExternalLink(getProjectLink(project)) + ? 'noopener noreferrer' + : null + " + class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-3 py-1.5 font-medium text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors" + > + Vai al servizio + </a> + </div> + </div> + </article> + </div> + + <div + v-else-if="items.length === 1" + class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary" + > + Solo un progetto disponibile per ora. + </div> + + <div + v-else + class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary" + > + Nessun progetto trovato. + </div> + </div> + </div> +</template> + +<script setup> +import { computed } from "vue"; +import { RouterLink } from "vue-router"; +import { useContentList } from "../composables/useContent.js"; +import { resolveAssetPath } from "../utils/assetPath.js"; + +// Carica tutti i progetti dalla directory content/projects/ +const { items, loading, error, reload } = useContentList("/content/projects/"); + +const resolveCover = (cover) => resolveAssetPath(cover); + +const featuredProject = computed(() => items.value[0] ?? null); +const featuredServiceLink = computed(() => + getProjectLink(featuredProject.value), +); + +function getExcerpt(html, length) { + if (!html) return ""; + + const div = document.createElement("div"); + div.innerHTML = html; + const text = (div.textContent || div.innerText || "") + .replace(/\s+/g, " ") + .trim(); + + if (text.length <= length) { + return `<p>${text}</p>`; + } + + const shortened = text.substring(0, length); + const lastSpace = shortened.lastIndexOf(" "); + const finalText = + lastSpace > 0 ? shortened.substring(0, lastSpace) : shortened; + + return `<p>${finalText}...</p>`; +} + +function getProjectLink(project) { + if (!project) return ""; + + const frontmatter = project.frontmatter || {}; + const explicitLink = + frontmatter.serviceUrl || + frontmatter.service_url || + frontmatter.url || + frontmatter.link || + frontmatter.website || + frontmatter.external; + + if (typeof explicitLink === "string" && explicitLink.trim()) { + return explicitLink.trim(); + } + + const html = project.html || ""; + const firstHref = html.match(/href="([^"]+)"/i); + return firstHref?.[1] || ""; +} + +function isExternalLink(link) { + return /^https?:\/\//i.test(link || ""); +} +</script> + +<style scoped> +.line-clamp-3 { + display: -webkit-box; + line-clamp: 3; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.line-clamp-4 { + display: -webkit-box; + line-clamp: 4; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + overflow: hidden; +} +</style> diff --git a/src/views/WikiView.vue b/src/views/WikiView.vue new file mode 100644 index 0000000..178d291 --- /dev/null +++ b/src/views/WikiView.vue @@ -0,0 +1,608 @@ +<template> + <div class="min-h-screen bg-base-100 text-base-content"> + <div class="container mx-auto px-4 py-8"> + <div class="mb-4 md:hidden"> + <button + class="btn h-auto w-full justify-between border-base-300 bg-base-200 px-4 py-3 text-left normal-case shadow-sm hover:bg-base-300" + type="button" + @click="toggleMobileSidebar" + :aria-expanded="isMobileSidebarOpen" + aria-controls="wiki-sidebar-panel" + > + <span class="flex flex-col items-start"> + <span class="text-sm font-semibold text-base-content" + >Sommario e Indice pagina</span + > + <span class="text-xs text-base-content/70">{{ + mobileSidebarSummary + }}</span> + </span> + <svg + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 24 24" + fill="none" + class="h-4 w-4 text-base-content/70 transition-transform" + :class="{ 'rotate-180': isMobileSidebarOpen }" + > + <path + d="M6 9l6 6 6-6" + stroke="currentColor" + stroke-width="2" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + </button> + </div> + + <div class="grid grid-cols-1 gap-6 md:grid-cols-12 md:gap-8"> + <div + v-if="isMobileSidebarOpen" + class="fixed inset-0 z-40 bg-black/40 md:hidden" + @click="closeMobileSidebar" + ></div> + + <!-- Sidebar con navigazione pagine wiki --> + <aside + id="wiki-sidebar-panel" + :class="sidebarPanelClasses" + aria-label="Wiki sidebar" + > + <div class="mb-4 flex items-center justify-between md:hidden"> + <span + class="text-sm font-semibold uppercase tracking-wide text-primary" + >Wiki menu</span + > + <button + class="btn btn-xs btn-ghost" + type="button" + @click="closeMobileSidebar" + > + X + </button> + </div> + <nav class="rounded-lg"> + <!-- Lista pagine dalla sidebar --> + <div class="space-y-2 text-sm"> + <div v-for="(item, index) in sidebarItems" :key="index"> + <!-- Heading di sezione --> + <h3 + v-if="item.type === 'heading'" + class="text-xs font-bold text-secondary uppercase mt-4 mb-2" + > + {{ item.text }} + </h3> + <!-- Link a pagina --> + <a + v-else-if="item.type === 'link'" + :href="item.isExternal ? item.url : '#'" + :target="item.isExternal ? '_blank' : null" + :rel="item.isExternal ? 'noopener noreferrer' : null" + @click="onSidebarLinkClick($event, item)" + class="block min-h-11 rounded-lg px-3 py-2.5 transition hover:bg-base-300/20 md:min-h-0 md:py-1" + :class="{ + 'bg-base-300/20 text-primary font-bold': + !item.isExternal && currentPage === item.slug, + }" + :title="item.text" + > + {{ item.text + }}<span + v-if="item.isExternal" + class="ml-1 text-base-content/60" + >↗</span + > + </a> + <!-- TOC (Table of Contents) - Outline minimal terminal style --> + <nav + v-if="currentPage === item.slug && outline.length > 0" + class="mt-2" + > + <ul + class="space-y-0 text-xs font-mono leading-snug border-l border-base-300 pl-2" + > + <li v-for="heading in outline" :key="heading.id"> + <a + :href="`#${heading.id}`" + @click.prevent="scrollToHeading(heading.id)" + class="block rounded-md py-1.5 pr-2 transition hover:text-base-content" + :style="{ + paddingLeft: `${(heading.level - 1) * 0.5}rem`, + }" + :class="{ + 'text-primary bg-base-300/20': + activeHeading === heading.id, + 'text-base-content/60': activeHeading !== heading.id, + }" + :title="heading.text" + > + {{ heading.text }} + </a> + </li> + </ul> + </nav> + </div> + </div> + </nav> + </aside> + + <!-- Contenuto principale --> + <main class="md:col-span-8 lg:col-span-9 xl:col-span-10"> + <div v-if="loading" class="text-center py-12"> + <span class="text-primary" + >Loading<span class="blinking-cursor"></span + ></span> + </div> + + <article + v-else + class="bg-base-200 rounded-lg border border-base-300 p-4 sm:p-6 lg:p-8" + > + <h1 + class="mb-5 text-2xl font-bold text-primary sm:text-3xl lg:mb-6 lg:text-4xl" + > + {{ pageTitle }}<span class="blinking-cursor"></span> + </h1> + <div + class="markdown-content prose prose-invert max-w-none text-sm md:text-base" + v-html="pageContent" + ></div> + </article> + </main> + </div> + </div> + <button + class="btn btn-circle btn-secondary fixed bottom-4 right-4 z-30 text-3xl font-bold sm:bottom-6 sm:right-6" + :class="{ hidden: !showScrollTopButton }" + @click="scrollToTop" + > + ↑ + </button> + </div> +</template> + +<script setup> +import { ref, computed, onMounted, onUnmounted, watch } from "vue"; +import { marked } from "marked"; +import { useRoute, useRouter } from "vue-router"; + +const route = useRoute(); +const router = useRouter(); + +const MOBILE_BREAKPOINT_QUERY = "(max-width: 767px)"; +const MOBILE_HEADING_THRESHOLD = 84; +const DESKTOP_HEADING_THRESHOLD = 100; +const WIKI_CONTENT_BASE_PATH = "/content/wiki/adm.wiki"; +const WIKI_SIDEBAR_PATH = `${WIKI_CONTENT_BASE_PATH}/_Sidebar.md?raw`; + +const loading = ref(true); +const pageContent = ref(""); +const pageTitle = ref("Wiki ADM"); +const currentPage = ref("home"); +const sidebarItems = ref([]); +const outline = ref([]); +const activeHeading = ref(""); +const showScrollTopButton = ref(false); +const isMobileSidebarOpen = ref(false); + +const sidebarPageCount = computed( + () => + sidebarItems.value.filter( + (item) => item.type === "link" && !item.isExternal, + ).length, +); + +const mobileSidebarSummary = computed(() => { + const pages = sidebarPageCount.value; + const sections = outline.value.length; + return `${pages} pagine · ${sections} sezioni`; +}); + +const sidebarPanelClasses = computed(() => [ + "md:col-span-4 lg:col-span-3 xl:col-span-2 md:sticky md:top-4 md:self-start", + "fixed left-4 right-4 top-4 z-50 max-h-[calc(100vh-2rem)] overflow-y-auto rounded-lg border border-base-300 bg-base-100/95 p-4 shadow-lg backdrop-blur transition-transform duration-200 ease-out md:static md:z-auto md:max-h-none md:overflow-visible md:rounded-none md:border-0 md:bg-transparent md:p-0 md:shadow-none md:backdrop-blur-none", + isMobileSidebarOpen.value + ? "translate-x-0" + : "-translate-x-[110%] md:translate-x-0", +]); + +function toHeadingId(text) { + return text.toLowerCase().replace(/[^\w]+/g, "-"); +} + +function toWikiSlug(value) { + return value.replace(/^\.\//, "").replace(/\/$/, "").toLowerCase(); +} + +function toTitleCaseSlug(value) { + return value + .split("-") + .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) + .join("-"); +} + +function buildPossibleWikiPaths(slug) { + return [ + `${WIKI_CONTENT_BASE_PATH}/${slug}.md`, + `${WIKI_CONTENT_BASE_PATH}/${slug.charAt(0).toUpperCase() + slug.slice(1)}.md`, + `${WIKI_CONTENT_BASE_PATH}/${toTitleCaseSlug(slug)}.md`, + ]; +} + +function parseSidebarLine(line) { + if (line.includes("<!-- NOT INCLUDE -->") || line.includes("<!--")) { + return null; + } + + if (line.startsWith("###") || line.startsWith("- ###")) { + return { + type: "heading", + text: line + .replace(/^-\s*/, "") + .replace(/^###\s*/, "") + .trim(), + }; + } + + if (line.includes("](")) { + const match = line.match(/\[([^\]]+)\]\(([^)]+)\)/); + if (!match) return null; + + const text = match[1]; + const url = match[2]; + const isExternal = /^https?:\/\//i.test(url); + + return { + type: "link", + text, + slug: toWikiSlug(url), + isExternal, + url, + }; + } + + if (line.includes("[[")) { + const match = line.match(/\[\[([^\]]+)\]\]/); + if (!match) return null; + + return { + type: "link", + text: match[1], + slug: toWikiSlug(match[1]), + isExternal: false, + url: "#", + }; + } + + return null; +} + +function createMarkdownRenderer() { + const renderer = new marked.Renderer(); + + renderer.heading = function (text, level) { + const id = toHeadingId(text); + return `<h${level} id="${id}" href="#${id}" >${text}</h${level}>`; + }; + + renderer.image = function (href, title, text) { + let src = href; + if (!href.startsWith("http") && !href.startsWith("/")) { + src = `${WIKI_CONTENT_BASE_PATH}/${href}`; + } + const titleAttr = title ? ` title="${title}"` : ""; + return `<img src="${src}" alt="${text}"${titleAttr} class="max-w-full h-auto" />`; + }; + + renderer.code = function (code, language) { + const lang = language || "text"; + const escapedCode = code.replace(/</g, "<").replace(/>/g, ">"); + return `<div class="code-block-wrapper"> + <div class="code-block-header"> + <span class="code-block-lang">${lang}</span> + <button class="code-block-copy" onclick="copyCodeToClipboard(this)" title="Copy code"> + <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> + <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect> + <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path> + </svg> + </button> + </div> + <pre><code class="language-${lang}">${escapedCode}</code></pre> + </div>`; + }; + + return renderer; +} + +function copyCodeToClipboard(button) { + const wrapper = button?.closest(".code-block-wrapper"); + const codeElement = wrapper?.querySelector("code"); + if (!codeElement) return; + + navigator.clipboard + .writeText(codeElement.textContent) + .then(() => { + const originalHTML = button.innerHTML; + button.innerHTML = + '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>'; + button.style.color = "var(--adm-primary)"; + + setTimeout(() => { + button.innerHTML = originalHTML; + button.style.color = ""; + }, 2000); + }) + .catch((err) => { + console.error("Failed to copy:", err); + }); +} + +function isMobileViewport() { + return window.matchMedia(MOBILE_BREAKPOINT_QUERY).matches; +} + +function closeMobileSidebar() { + isMobileSidebarOpen.value = false; +} + +function toggleMobileSidebar() { + isMobileSidebarOpen.value = !isMobileSidebarOpen.value; +} + +function updateBodyScrollLock() { + if (!isMobileViewport()) { + document.body.classList.remove("overflow-hidden"); + return; + } + + document.body.classList.toggle("overflow-hidden", isMobileSidebarOpen.value); +} + +function scrollToTop() { + window.scrollTo({ top: 0, behavior: "smooth" }); + showScrollTopButton.value = false; +} + +function onSidebarLinkClick(event, item) { + if (item.isExternal) return; + event.preventDefault(); + closeMobileSidebar(); + loadPage(item.slug); +} + +// Carica il contenuto della sidebar +async function loadSidebar() { + try { + const sidebarModule = await import(WIKI_SIDEBAR_PATH); + const sidebarContent = sidebarModule.default; + const lines = sidebarContent.split("\n").filter((line) => line.trim()); + sidebarItems.value = lines.map(parseSidebarLine).filter(Boolean); + } catch (error) { + console.error("Error loading sidebar:", error); + } +} + +// Carica una pagina wiki +async function loadPage(slug) { + const normalizedSlug = toWikiSlug(slug); + loading.value = true; + currentPage.value = normalizedSlug; + + // Aggiorna URL senza ricaricare + router.push(`/wiki/${normalizedSlug}`); + + try { + const possiblePaths = buildPossibleWikiPaths(normalizedSlug); + let content = null; + + for (const path of possiblePaths) { + try { + const module = await import(/* @vite-ignore */ path + "?raw"); + content = module.default; + break; + } catch (err) { + // Continua a provare + } + } + + if (!content) { + throw new Error(`Page not found: ${normalizedSlug}`); + } + // Estrai titolo + const titleMatch = content.match(/^#\s+(.+)$/m); + pageTitle.value = titleMatch?.[1] || normalizedSlug.replace(/-/g, " "); + + // Rimuovi solo il primo H1 iniziale (se presente) + const contentWithoutMainTitle = content.replace(/^\s*#\s+.+(?:\r?\n)+/, ""); + + const renderer = createMarkdownRenderer(); + pageContent.value = marked(contentWithoutMainTitle, { renderer }); + extractOutline(contentWithoutMainTitle); + } catch (error) { + console.error("Error loading page:", error); + pageContent.value = `<p class="text-red-500">Page not found: ${normalizedSlug}</p>`; + pageTitle.value = "Error"; + outline.value = []; + } finally { + loading.value = false; + } +} + +// Estrai i capitoli (headings) per l'outline +function extractOutline(markdown) { + const headings = []; + const lines = markdown.split("\n"); + + for (const line of lines) { + const match = line.match(/^(#{1,5})\s+(.+)$/); + if (match) { + const level = match[1].length; + const text = match[2]; + const id = toHeadingId(text); + + headings.push({ level, text, id }); + } + } + + outline.value = headings; +} + +// Scroll a un heading +function scrollToHeading(id) { + activeHeading.value = id; + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: "smooth", block: "start" }); + closeMobileSidebar(); + } +} + +// Rileva heading attivo durante lo scroll +function handleScroll() { + const scrollTop = window.scrollY || document.documentElement.scrollTop; + showScrollTopButton.value = scrollTop > 300; + + if (outline.value.length === 0) { + activeHeading.value = ""; + return; + } + + const threshold = isMobileViewport() + ? MOBILE_HEADING_THRESHOLD + : DESKTOP_HEADING_THRESHOLD; + + for (const heading of outline.value) { + const element = document.getElementById(heading.id); + if (element) { + const rect = element.getBoundingClientRect(); + if (rect.top <= threshold && rect.bottom >= threshold) { + activeHeading.value = heading.id; + break; + } + } + } +} + +onMounted(async () => { + window.copyCodeToClipboard = copyCodeToClipboard; + + await loadSidebar(); + + // Carica la pagina dall'URL o Home come default + const slug = route.params.slug || "home"; + await loadPage(slug); + + window.addEventListener("scroll", handleScroll); + window.addEventListener("resize", updateBodyScrollLock); + handleScroll(); + updateBodyScrollLock(); +}); + +onUnmounted(() => { + window.removeEventListener("scroll", handleScroll); + window.removeEventListener("resize", updateBodyScrollLock); + document.body.classList.remove("overflow-hidden"); + delete window.copyCodeToClipboard; +}); + +watch( + () => route.params.slug, + async (slug) => { + const normalizedSlug = typeof slug === "string" ? slug : "home"; + if (normalizedSlug !== currentPage.value) { + await loadPage(normalizedSlug); + } + closeMobileSidebar(); + }, +); + +watch(isMobileSidebarOpen, () => { + updateBodyScrollLock(); +}); +</script> + +<style scoped> +.prose :deep(h2), +.prose :deep(h3), +.prose :deep(h4) { + scroll-margin-top: 4rem; +} + +@media (min-width: 768px) { + .prose :deep(h2), + .prose :deep(h3), + .prose :deep(h4) { + scroll-margin-top: 5rem; + } +} + +/* Code blocks styling */ +.markdown-content :deep(.code-block-wrapper) { + margin: 1.5rem 0; + border: 1px solid var(--adm-border); + border-radius: 8px; + overflow: hidden; + background: rgba(0, 0, 0, 0.3); +} + +.markdown-content :deep(.code-block-header) { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5rem 1rem; + background: rgba(0, 0, 0, 0.2); + border-bottom: 1px solid var(--adm-border); + font-size: 0.75rem; +} + +.markdown-content :deep(.code-block-lang) { + color: var(--adm-text-secondary); + font-family: "JetBrains Mono", monospace; + text-transform: uppercase; + font-weight: 600; + letter-spacing: 0.05em; +} + +.markdown-content :deep(.code-block-copy) { + background: transparent; + border: none; + color: var(--adm-text-secondary); + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + border-radius: 4px; + transition: all 0.2s; +} + +.markdown-content :deep(.code-block-copy:hover) { + color: var(--adm-primary); + background: rgba(97, 131, 117, 0.1); +} + +.markdown-content :deep(.code-block-wrapper pre) { + margin: 0; + padding: 1rem; + overflow-x: auto; + background: transparent; +} + +.markdown-content :deep(.code-block-wrapper code) { + font-family: "JetBrains Mono", monospace; + font-size: 0.875rem; + line-height: 1.6; + color: #e0e0e0; +} + +@media (max-width: 767px) { + .markdown-content :deep(.code-block-header) { + padding: 0.5rem 0.75rem; + } + + .markdown-content :deep(table) { + display: block; + overflow-x: auto; + white-space: nowrap; + } +} +</style> diff --git a/static/fonts/AUTHORS.txt b/static/fonts/AUTHORS.txt new file mode 100644 index 0000000..8814941 --- /dev/null +++ b/static/fonts/AUTHORS.txt @@ -0,0 +1,10 @@ +# This is the official list of project authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS.txt file. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization <email address> + +JetBrains <> +Philipp Nurullin <philipp.nurullin@jetbrains.com> +Konstantin Bulenkov <kb@jetbrains.com> diff --git a/static/fonts/JetBrainsMono-Medium.ttf b/static/fonts/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000..9767115 Binary files /dev/null and b/static/fonts/JetBrainsMono-Medium.ttf differ diff --git a/static/fonts/OFL.txt b/static/fonts/OFL.txt new file mode 100644 index 0000000..8bee414 --- /dev/null +++ b/static/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Bold.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Bold.ttf new file mode 100644 index 0000000..8c93043 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Bold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-BoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-BoldItalic.ttf new file mode 100644 index 0000000..1ddf216 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-BoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-ExtraBold.ttf b/static/fonts/fonts/ttf/JetBrainsMono-ExtraBold.ttf new file mode 100644 index 0000000..435d7a7 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-ExtraBold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-ExtraBoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-ExtraBoldItalic.ttf new file mode 100644 index 0000000..79e616e Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-ExtraBoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-ExtraLight.ttf b/static/fonts/fonts/ttf/JetBrainsMono-ExtraLight.ttf new file mode 100644 index 0000000..c131cbf Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-ExtraLight.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-ExtraLightItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-ExtraLightItalic.ttf new file mode 100644 index 0000000..a768985 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-ExtraLightItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Italic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Italic.ttf new file mode 100644 index 0000000..ccc9d6a Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Italic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Light.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Light.ttf new file mode 100644 index 0000000..15f15a2 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Light.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-LightItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-LightItalic.ttf new file mode 100644 index 0000000..506208f Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-LightItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Medium.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000..9767115 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Medium.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-MediumItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-MediumItalic.ttf new file mode 100644 index 0000000..415a9e3 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-MediumItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Regular.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000..dff66cc Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Regular.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-SemiBold.ttf b/static/fonts/fonts/ttf/JetBrainsMono-SemiBold.ttf new file mode 100644 index 0000000..a70e69b Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-SemiBold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-SemiBoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-SemiBoldItalic.ttf new file mode 100644 index 0000000..968602e Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-SemiBoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-Thin.ttf b/static/fonts/fonts/ttf/JetBrainsMono-Thin.ttf new file mode 100644 index 0000000..7dbe2ac Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-Thin.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMono-ThinItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMono-ThinItalic.ttf new file mode 100644 index 0000000..c6ad6c2 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMono-ThinItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Bold.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Bold.ttf new file mode 100644 index 0000000..f78f84f Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Bold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-BoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-BoldItalic.ttf new file mode 100644 index 0000000..9fb8c83 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-BoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBold.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBold.ttf new file mode 100644 index 0000000..fe5be6a Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBoldItalic.ttf new file mode 100644 index 0000000..59fc980 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraBoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLight.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLight.ttf new file mode 100644 index 0000000..6da7b75 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLight.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLightItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLightItalic.ttf new file mode 100644 index 0000000..5733efc Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-ExtraLightItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Italic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Italic.ttf new file mode 100644 index 0000000..4e9c380 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Italic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Light.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Light.ttf new file mode 100644 index 0000000..0b79b0c Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Light.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-LightItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-LightItalic.ttf new file mode 100644 index 0000000..b5e0842 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-LightItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Medium.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Medium.ttf new file mode 100644 index 0000000..1454372 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Medium.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-MediumItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-MediumItalic.ttf new file mode 100644 index 0000000..8d63c6c Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-MediumItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Regular.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Regular.ttf new file mode 100644 index 0000000..70d2ec9 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Regular.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBold.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBold.ttf new file mode 100644 index 0000000..ce60a88 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBold.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBoldItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBoldItalic.ttf new file mode 100644 index 0000000..3b3f8f6 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-SemiBoldItalic.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-Thin.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-Thin.ttf new file mode 100644 index 0000000..bea837e Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-Thin.ttf differ diff --git a/static/fonts/fonts/ttf/JetBrainsMonoNL-ThinItalic.ttf b/static/fonts/fonts/ttf/JetBrainsMonoNL-ThinItalic.ttf new file mode 100644 index 0000000..f0bfed7 Binary files /dev/null and b/static/fonts/fonts/ttf/JetBrainsMonoNL-ThinItalic.ttf differ diff --git a/static/fonts/fonts/variable/JetBrainsMono-Italic[wght].ttf b/static/fonts/fonts/variable/JetBrainsMono-Italic[wght].ttf new file mode 100644 index 0000000..5414835 Binary files /dev/null and b/static/fonts/fonts/variable/JetBrainsMono-Italic[wght].ttf differ diff --git a/static/fonts/fonts/variable/JetBrainsMono[wght].ttf b/static/fonts/fonts/variable/JetBrainsMono[wght].ttf new file mode 100644 index 0000000..b60e77f Binary files /dev/null and b/static/fonts/fonts/variable/JetBrainsMono[wght].ttf differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Bold.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Bold.woff2 new file mode 100644 index 0000000..4917f43 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Bold.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-BoldItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-BoldItalic.woff2 new file mode 100644 index 0000000..536d3f7 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-BoldItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBold.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBold.woff2 new file mode 100644 index 0000000..8f88c54 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBold.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 new file mode 100644 index 0000000..d1478ba Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLight.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLight.woff2 new file mode 100644 index 0000000..b97239f Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLight.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLightItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLightItalic.woff2 new file mode 100644 index 0000000..be01aac Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-ExtraLightItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Italic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Italic.woff2 new file mode 100644 index 0000000..d60c270 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Italic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Light.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Light.woff2 new file mode 100644 index 0000000..6538498 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Light.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-LightItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-LightItalic.woff2 new file mode 100644 index 0000000..66ca3d2 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-LightItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Medium.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Medium.woff2 new file mode 100644 index 0000000..669d04c Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Medium.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-MediumItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-MediumItalic.woff2 new file mode 100644 index 0000000..80cfd15 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-MediumItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Regular.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 0000000..40da427 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Regular.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-SemiBold.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-SemiBold.woff2 new file mode 100644 index 0000000..5ead7b0 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-SemiBold.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-SemiBoldItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-SemiBoldItalic.woff2 new file mode 100644 index 0000000..c5dd294 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-SemiBoldItalic.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-Thin.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-Thin.woff2 new file mode 100644 index 0000000..17270e4 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-Thin.woff2 differ diff --git a/static/fonts/fonts/webfonts/JetBrainsMono-ThinItalic.woff2 b/static/fonts/fonts/webfonts/JetBrainsMono-ThinItalic.woff2 new file mode 100644 index 0000000..a643215 Binary files /dev/null and b/static/fonts/fonts/webfonts/JetBrainsMono-ThinItalic.woff2 differ diff --git a/static/img/dumbo.svg b/static/img/dumbo.svg new file mode 100644 index 0000000..f4b71d8 --- /dev/null +++ b/static/img/dumbo.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" fill="rgb(99 102 241)" class="h-1/5 w-1/5"><path d="M246.5 34.7C226.8 37.4 211.6 48 203.1 65c-2.3 4.5-4.8 10.7-5.7 13.6-.8 3-1.6 5.4-1.7 5.4-.1 0-2.7-.7-5.7-1.5-7.2-1.9-18.7-1.9-26.4.1-7.4 1.9-17.9 7.3-22.3 11.4-1.8 1.7-3.6 3-4.1 3-.4 0-1.5-1.5-2.4-3.3-2.7-5.6-12.6-17.2-18.6-21.7-10.5-7.9-20-11-33.7-11-14.6 0-27.4 4.2-46.1 15.3-14.8 8.7-16.1 9.4-24 11.3-8.7 2.1-9.6 2.8-8.2 6 1.4 3.1 4 4.7 13.5 8.5 21.3 8.4 30.7 15.7 47.5 36.9 5.5 6.9 11.7 14 13.9 15.8 3.8 3.3 3.8 3.4 2.4 6.2-.8 1.6-1.9 4.6-2.3 6.6-.7 3.6-.9 3.8-5.5 3.9-6.6.3-13.5 4.1-16 8.8-5.6 10.7-1.6 29.8 7.3 35.1 3.5 2 13 2.1 19.6.1 4.2-1.3 5.4-1.3 9.1 0 5.5 1.9 14.6 1.9 20.6.1 4-1.2 5.4-1.2 9.4 0 2.5.8 5.6 1.4 6.8 1.4 2.8 0 3.4 2.7 2.8 11.3-.5 5.7-.3 6.4 2.2 8.7 2.5 2.3 3.4 2.5 12.8 2.5 8.4 0 11.1-.4 14.9-2.2 10.1-4.6 11.9-10.1 7.3-21.5-2.7-6.5-2.5-7.3 1.6-8.3 2.1-.5 3.2.1 6.6 3.7 3.6 4 4 5 4.6 11.4.9 9.4 2.6 10.8 12.2 10.2 9.1-.6 16.8-4.2 22.9-10.8 6.4-6.8 6.4-9 .3-16.3-10.2-11.9-12.2-13.8-17.7-16.6-5.4-2.6-5.8-3-4.5-4.7 1.3-1.8 1.5-1.8 5-.1 5.6 2.6 16.6 3.9 24 2.7 11-1.7 20.4-6.8 32.5-17.5 8.9-7.8 13.1-9.9 18.6-9 6.4.9 8.4-1.5 8.4-10 0-3.6-.6-8.1-1.4-10-2.3-5.4-7.2-7.1-10.3-3.5-1 1.1-2.8 2-4.1 2-3.5 0-8.8 2.5-18.7 8.9-4.9 3.2-10.7 6.4-12.9 6.9-3.7 1.1-3.8 1-3-1.1.4-1.2.8-4.3.8-6.9.1-4.3.4-4.8 3.4-6.3 4.7-2.2 13.5-10.7 17.8-17.2 5.3-7.9 7.8-15 11.3-31.2 4.7-22.1 10.4-32 22.8-39.4 6.1-3.6 6.6-5.6 2.3-8.7-9.8-7-31.6-11.3-46.5-9.3zm31 5.3c6.6 2.1 16.5 6.5 16.5 7.5 0 .2-2.7 1.8-6.1 3.6-3.3 1.8-8 5.4-10.4 8.1-7.3 8.2-9.4 13.5-15.4 40.3-3.6 15.9-11.5 28.5-23.1 37-4.2 3.1-5.2 3.4-6.9 2.4-1.5-1-2.1-2.9-2.6-8.3-.4-3.9-1.7-10.3-3-14.1-2-6.1-2.2-7.7-1.2-11.8.8-3.7.7-7.7-.7-18.7-1.1-8.4-1.5-15.6-1.1-18.2 2.9-16.9 18.8-26.5 42.8-25.6 9.8.3 11.6-.7 3-1.8-18.9-2.3-38.1 4.5-44.8 16-4.6 7.8-5.1 13.5-3 30.9 1 8.5 1.5 16.2 1.1 17.3-.6 1.6-.9 1.4-2.6-1.4-2.8-4.6-11.6-12.7-16.7-15.4-2.3-1.3-4.3-2.7-4.3-3.1 0-2.3 7.4-19.3 10.3-23.9 7.2-11.2 18.8-19.1 32.8-22.3 9-2.1 26.2-1.3 35.4 1.5zM95.9 66.5c14.3 3.8 23.9 11.7 35.1 28.9 9.3 14.2 14.8 21.6 16.1 21.6 1.7 0 .9-1.9-3.6-8.9-2.5-3.8-4.5-7.4-4.5-7.9 0-1.6 13-10 19-12.3 7.8-3.1 24.4-3.8 32.6-1.4 7.5 2.1 13.6 5.6 19.8 11.4 9.7 9.1 13.7 17.5 15.6 32.4.9 7.5 1.4 9 4 11.6 1.7 1.6 3 3.7 3 4.6 0 2.5-2.8 8.5-4 8.5-1.8 0-6.4-2.6-8.3-4.8-1.7-1.9-1.7-2.1 1.3-5 4.5-4.5 3.9-12.4-1.2-18-4.5-4.8-9.8-1-9.8 7 0 12.8 10.5 23.8 22.6 23.8 5.6 0 11.4-2.5 21.9-9.2 9.9-6.4 17-8.6 15.9-5.1-.4 1 .3.4 1.4-1.3 2.8-4.4 4.1-4.9 6.4-2.7 2.1 2.2 3.5 11.3 2.4 15.8-1 3.8-4.5 3-7.5-1.7-2.8-4.4-4-4.3-1.8.1 1.3 2.7 1.4 3.1.1 3.1-3 0-10 4.5-18.3 11.6-4.8 4.1-11.9 9.1-16.1 11.1-7.4 3.7-7.7 3.8-19 3.8-11.1 0-11.7-.1-19.1-3.6-4.1-2-9.5-5.5-11.9-7.8-4.7-4.4-6.9-4.8-2.9-.5l2.4 2.6-2.5-.7c-4.3-1.3-12-4.7-12-5.4.1-.3 1.5-1.5 3.2-2.6 5-3.2 4.4-4.5-.8-1.9-2.7 1.4-6.5 2.4-8.8 2.4-3 0-3.7.3-2.6 1 .8.5 2.9 1 4.7 1 2.8 0 3.3.5 4.9 4.7 2.5 6.7 4.2 9.2 7.7 10.9 3.7 2 7.4 1.1 8.9-2.1 1.3-2.9 2.1-3.1 3.8-1 1.1 1.3.8 2.1-2 5-6 6.2-11.6 5.7-19.5-1.6-2.5-2.3-4.2-3.4-3.9-2.4.6 1.6.3 1.7-3 1.1-8.7-1.6-18-7.7-21.2-13.7-1.6-3.2-1.9-11.5-.4-12.4 1.3-.8 1.3-2.5-.1-2.5-.6 0-1.5 1.2-2.1 2.8-.9 2.3-2.3 3.1-8.7 5.1-9.1 2.9-23 3.9-29.8 2.1-12.7-3.1-20.4-9.3-35.8-28.5-15.5-19.4-25.9-27.9-42-34-11.5-4.4-11.4-4.4-7.9-4.4 4.4-.1 8-1.5 24.4-9.1 24-11.2 34.8-13.6 48.1-10.6 18.1 4 29.6 15.7 37.5 37.9 5.9 16.5 16.9 35.8 19.5 34.2.5-.4-.9-2.9-3-5.8-5.4-7.2-7.3-11.3-12-26-5.1-16.1-9.1-23.7-16.2-30.8C105.6 76.6 91.3 71.3 77 72.3c-10.7.8-19.2 3.7-38.5 13.5-15.5 7.8-17.6 8.6-24 9-5.4.3-7.3.1-8.3-1-1-1.3-.1-1.7 5.7-2.7 7.6-1.4 15-4.6 25.6-11.1 9.5-5.8 20.5-10.8 29-13 8.5-2.3 22-2.5 29.4-.5zm124.6 63.9c2.7 4 2.8 8.7.5 12.5-2.2 3.5-3.9 3.7-2.1.3 1.5-2.9 1.4-5.2-.4-5.2-.8 0-1.5-.7-1.5-1.5s.5-1.5 1.1-1.5c.8 0 .7-.5-.2-1.6-.8-1-2.1-1.3-3.6-.9-2.1.5-2.2.4-1.1-2 1.5-3.3 5.2-3.3 7.3-.1zm-123 36.2c3.9 1.5 7.5 1.9 16.5 1.9 11.1-.1 14.9-.9 24.1-4.9 1.2-.5 1.8.3 2.8 3.4 2.5 8.5 14 17 25 18.6 2.5.3 5.6 1.5 6.8 2.7 1.2 1.1 4.5 2.7 7.2 3.7l5 1.7-3.2 3.1c-3.2 3.1-13.6 10.2-14.8 10.2-.4 0-1.9-2-3.3-4.3-2.5-4.4-13.9-15.7-15.7-15.7-1.8 0-.9 1.6 2.1 3.8 7.1 5.3 19 27.1 19 34.8 0 2.6-.1 2.6-1.8 1.1-2.7-2.5-5.7-2.1-7 .8-1.1 2.4-1.3 2.5-3.4 1.1-2-1.2-2.8-1.3-5.5-.1-1.7.7-3.4 2.3-3.8 3.5-.6 2-.8 2-2.4.6-2-1.8-5.4-2.1-8.1-.6-1.7.9-1.8.6-1.3-4.9.3-3.4 0-7.4-.7-9.7-1.9-6.1-10-18.1-10-14.9 0 .3 1.4 2.7 3 5.3 1.7 2.7 3 5.3 3 5.7 0 1.3-7.4-.6-13.8-3.6-6.6-3.2-16.2-11.8-16.2-14.6 0-1.3-.3-1.4-1.2-.5-.9.9-.7 1.9 1 4.2 1.2 1.6 2.2 3.4 2.2 3.9 0 2.2-17.2 9.5-20.1 8.6-1-.4-3-2.5-4.4-4.8-1.4-2.3-2.5-3.6-2.5-2.9 0 2.1 2 5.5 4.4 7.5l2.1 1.8-3-.3c-2.4-.2-3.4-1.1-5-4.3-1.5-3-2-3.5-2.3-2.1-.2 1 .6 3.1 1.7 4.7l2.2 2.9h-3c-4.2 0-6.1-.9-6.1-3.1 0-2.9-2.2-6.9-3.8-6.9-1 0-1.2-.6-.7-1.8 1.6-3.9 1.7-5.3.1-7.7-1.5-2.3-1.5-2.7-.1-4.1 2.2-2.2 2.8-5.5 1.6-8.8-.6-1.5-1.1-2.9-1.1-3.1 0-.1 1.8-1 4-1.9 4.7-1.9 12.1-2.1 13.8-.4 1.7 1.7 2.7.2 1.2-1.7-1.3-1.6-.7-4.8 2.1-12.2l.9-2.3 3.7 2.3c2.1 1.3 6.1 3.2 8.8 4.3zm83.1 10.8c.1 0 .6 1 1.2 2.1 1.1 1.9 1.1 1.9 1.2.1 0-1.2.5-1.6 1.6-1.2.9.3 2 .6 2.5.6 1.5 0 1 3-.7 3.7-2.2.8-8-2.1-9.4-4.8-1.1-1.9-1-2 1.2-1.4 1.2.4 2.3.8 2.4.9zM63 184.6c0 2.3-3.5 7.3-4.4 6.3-.3-.3.1-3 1-5.9 1.1-3.9 1.8-4.9 2.5-3.9.5.8.9 2.4.9 3.5zm136.5 6.9c2.4 1.4 6.2 4.7 8.5 7.3 2.3 2.6 5.5 6 7 7.7 2.2 2.4 2.6 3.7 2.3 6.2-.4 2.7-1 3.3-3.1 3.3-3.1 0-6.2 2.6-6.2 5.2 0 1.4-.5 1.8-1.9 1.3-2.8-.9-6.8 1.4-8.2 4.6-.9 2.3-1.8 2.9-4.1 2.9-5.3 0-6.8-1.5-6.8-7.1 0-6.1-1.6-9.4-6.8-14.1l-3.9-3.5 4.9-4.3c2.7-2.3 5.4-5.3 6-6.6.6-1.3 1.7-2.4 2.3-2.4.7 0 1.8-.7 2.5-1.5 1.7-2 2.4-1.9 7.5 1zm-138.4 3.9c1.3 2.9.3 9-1.1 6.6-.4-.8-1.1-3.2-1.5-5.3-.8-4.3.9-5.2 2.6-1.3zm3.5 12.1c.9 3.8-.2 4.1-2.1.6-1.4-2.7-1.4-3.1 0-3.1.8 0 1.7 1.1 2.1 2.5zm43.5.1c.7.8 2.6 2.2 4.3 3.1 2.8 1.5 2.9 1.7 1.1 2.4-2.6 1-19.5 1.1-19.5.1 0-.4 2-1.5 4.4-2.5 2.5-1 5-2.5 5.7-3.3 1.5-1.8 2.3-1.8 4 .2zm112.9 5.8c0 .8-.7 1.9-1.5 2.6-1.2 1-1.5 1-1.5-.3 0-2.5 1.1-4.7 2.1-4.1.5.3.9 1.1.9 1.8zm-3.5 4.5c.5 1-6.2 7.1-7.8 7.1-1.4 0 .2-5.4 2-6.8 2-1.4 4.9-1.6 5.8-.3zm-9.8 7.7c.2.6-1.4 1.6-3.5 2.2-6 1.8-7 1.4-3.8-1.4 2.8-2.5 6.6-2.9 7.3-.8zm-40.9 2.6c1.8 1.8 1.5 2.6-1.8 4.3-5 2.6-5.9 2-4-2.9 1-2.8 3.8-3.4 5.8-1.4zM157 231c3.6 3.6 2.9 4.5-4.7 5.5-6.2.8-6.8-.2-2.4-4.6 3.5-3.4 4.4-3.6 7.1-.9zm-12.6 3.6c2.4 2.3 2 2.7-2.1 1.9-4.6-.8-5.5-1.3-4.8-2.6 1-1.4 5.2-1.1 6.9.7z"></path><path d="M182.5 90.5c7.1 1.7 13.4 4.7 20.5 9.7 10 6.9 10.8 7.3 5.6 2.5-7.6-7-22.4-13.9-29-13.6-1.2.1.2.7 2.9 1.4zM212.4 110c-2.4.9-4.1 3-2.5 3 .5 0 1.3-.5 1.7-1.1.3-.6 2.2-.9 4-.7 1.9.2 3.4 0 3.4-.4s-.4-.8-.9-.8-1.5-.2-2.3-.4c-.7-.3-2.3-.1-3.4.4zM118.4 118.7c1.8 3.8 4.4 7.9 5.6 9.3l2.2 2.5-2-3c-1.1-1.7-3.4-5.8-5.1-9.3-1.7-3.4-3.4-6.2-3.6-6.2-.3 0 1 3 2.9 6.7zM167.1 116.6c-1.7 1.4-3.1 3.3-3.1 4.2 0 1.4.3 1.3 1.8-.4 2.1-2.6 5.4-4.4 8.1-4.4 1.2 0 2.1-.5 2.1-1 0-2-5.9-1-8.9 1.6zM213.4 115c-4.1 1.6-3.2 2.5 2.7 2.5 3.2.1 5.9 0 5.9-.2 0-.3-5.8-3.3-6.2-3.2-.2 0-1.3.4-2.4.9zM170.2 121.6c-1.2.8-2.9 2.8-3.7 4.5-1.7 3.2-.7 4 1.2.9 1.9-3 6.9-5.2 10-4.4 2.5.7 2.7.6 1.4-.9-1.7-2.1-6-2.2-8.9-.1zM171 133.5c-2.5 2.6-3.1 6.8-1.7 11.7.7 2.5.5 2.8-1.8 2.8-1.4 0-2.5.4-2.5 1 0 .5 2 1 4.3 1 3.3 0 5.4.8 8.5 2.9 3.9 2.9 4 2.9 5.7 1.1 2.3-2.5 3-9.8 1.5-14.3-1.3-4.3-6.2-8.7-9.4-8.7-1.2 0-3.3 1.1-4.6 2.5zm9.3 2.2c3.6 4.1 4.3 15.9.9 17.1-.9.3-1-.9-.5-4.3.6-4.5.5-4.7-1.5-4.1-2.5.8-3.8-.9-1.6-2.2.9-.5 1.4-1.4 1-2.1-.9-1.5-4.9-1.4-6.4.1-.9.9-1.2.6-1.2-1.3 0-1.4.5-3 1.2-3.7 1.8-1.8 6.3-1.5 8.1.5zM275.2 143.2c-3 3 .4 12.4 3.7 10.3 1.5-.9 1.3-7.6-.3-9.8-1.6-2-1.8-2.1-3.4-.5zm3.3 3.1c.3 1.2.2 3.3-.3 4.7l-.9 2.4-1.2-2.3c-1.3-2.4-.7-7.1.9-7.1.5 0 1.2 1 1.5 2.3zM200.1 146.1c-4.1 2.5-3.5 3.7.8 1.5 1.6-.9 3.7-1.6 4.5-1.6.8 0 1.8-.5 2.1-1 1.1-1.8-3.9-1.1-7.4 1.1zM261.1 150c-2.9 1.6-5.9 3.5-6.7 4.1-.7.6-4.1 2.6-7.6 4.5s-5.2 3.2-3.9 2.8c1.3-.3 4.5-1.9 7-3.5 2.5-1.5 7.8-4.6 11.6-6.9 8-4.6 7.7-5.5-.4-1zM204.5 154.1c-1.9 1.7-3.5 3.6-3.5 4.1 0 .6 1.5-.3 3.3-1.8 1.9-1.6 4.2-3.4 5.3-4.1 1.7-1 1.7-1.2.2-1.2-1-.1-3.3 1.3-5.3 3zM216.9 159.3c-1.5 1.2-3.2 3.3-3.9 4.7-.9 1.9-.2 1.5 3.1-1.7 4.6-4.5 5.1-6.6.8-3zM224.3 161.5c2.1 1.5 9.5 3 10.4 2.1.4-.3-.5-.6-1.8-.6-1.3-.1-4.2-.7-6.4-1.5-3.3-1.2-3.7-1.2-2.2 0zM89.3 170.7c1.2 1.9 13.3 7.3 18.6 8.3 2.9.5 8.3.9 12 .9 6.1-.2 5.8-.3-3-.9-11-.9-15.2-2-22.8-6.3-3-1.7-5.1-2.6-4.8-2zM77.1 178c0 .8.7 3.1 1.4 5 1.2 3.1 1.4 3.2 1.4 1 0-1.4-.6-3.6-1.4-5-.8-1.4-1.4-1.8-1.4-1zM73.1 182.6c-.1 2.5.5 4.6 1.4 5.4.8.7 1.5 1.1 1.5.9-.1-.2-.7-2.7-1.5-5.4l-1.4-5v4.1zM80 201.7c0 1.3 4.1 7.5 4.6 7 .3-.2-.5-2.1-1.7-4.1-2.1-3.5-2.9-4.4-2.9-2.9zM151.4 208.1c-1.7.5-3.8 1.6-4.5 2.6-1.2 1.4-1.2 1.5.1 1 .8-.3 3.4-1.2 5.8-1.9 2.3-.7 4.2-1.6 4.2-2 0-1-1.5-.9-5.6.3zM155.5 212.7c-4.4 1-8.6 2.5-8.1 3 .7.7 11.6-1.9 11.6-2.9 0-.8-.2-.9-3.5-.1zM152.7 218.5c-3.2.5-5.6 1.3-5.3 1.6.7.7 10.5-.7 11.4-1.6 1.1-1.1-.4-1.1-6.1 0zM197 201.5c-4.7 4.8-3.4 5.1 1.9.4 2.4-2.1 3.7-3.9 2.9-3.9-.8 0-2.9 1.6-4.8 3.5zM199.7 205.1c-2 1.7-3.7 3.5-3.7 4.1 0 .5 1.5-.3 3.3-1.8 1.9-1.6 4.2-3.4 5.3-4.1 1.5-.9 1.5-1.2.4-1.2-.9-.1-3.2 1.3-5.3 3zM203.3 208.1c-2.4 1.7-4.3 3.4-4.3 4 0 .5 2.3-.7 5-2.7 2.8-2 5-3.8 5-4 0-.9-1.8-.1-5.7 2.7z"></path></svg> \ No newline at end of file diff --git a/static/img/team2024.jpg b/static/img/team2024.jpg new file mode 100644 index 0000000..f8be0d4 --- /dev/null +++ b/static/img/team2024.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2d95e07926f1f798160f18f04e0320c72aec7644f694bdc4bc61c8bb3d1d420 +size 6585031 diff --git a/static/img/wifi-pass.png b/static/img/wifi-pass.png new file mode 100644 index 0000000..5009c44 --- /dev/null +++ b/static/img/wifi-pass.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b798350ce286ffcfeaf32b26651d9c8cdaf3682b1e8c5543e090488ff46ea33 +size 11767 diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..bea973b --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,34 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], + theme: { + extend: { + fontFamily: { + sans: ["JetBrains Mono", "monospace"], + mono: ["JetBrains Mono", "monospace"], + }, + }, + }, + plugins: [require("daisyui")], + daisyui: { + darkTheme: "admtheme", + themes: [ + "dark", + { + admtheme: { + primary: "#618375", + secondary: "#73747b", + accent: "#618375", + neutral: "#252627", + "base-100": "#292a2d", + "base-200": "#3b3d42", + "base-300": "#4a4b50", + info: "#618375", + success: "#618375", + warning: "#a9a9b3", + error: "#ff4444", + }, + }, + ], + }, +}; diff --git a/themes/website-theme b/themes/website-theme deleted file mode 160000 index 2feec37..0000000 --- a/themes/website-theme +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2feec37cd5615bf62d888cf8b20d64a154d25c91 diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..d698220 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,13 @@ +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + "@": "/src", + }, + }, + publicDir: "static", + assetsInclude: ["**/*.md"], +});