├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── README.md
├── bb.edn
├── index.html
├── package-lock.json
├── package.json
├── squint.edn
├── src
├── app.cljs
└── app.css
└── vite.config.mjs
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to GitHub Pages
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v3
13 |
14 | - name: Set up Node.js
15 | uses: actions/setup-node@v3
16 | with:
17 | node-version: '18'
18 | cache: 'npm'
19 |
20 | - name: Install Node dependencies
21 | run: npm ci
22 |
23 | - name: Install Babashka
24 | uses: just-sultanov/setup-babashka@v2
25 | with:
26 | version: '1.3.186' # Specify the version you need
27 |
28 | - name: Build
29 | run: bb build
30 |
31 | - name: Upload static files as artifact
32 | uses: actions/upload-pages-artifact@v3 # or specific "vX.X.X" version tag for this action
33 | id: deployment
34 | with:
35 | path: dist/
36 |
37 | deploy:
38 | runs-on: ubuntu-latest
39 | needs: build
40 | permissions:
41 | pages: write
42 | id-token: write
43 | environment:
44 | name: github-pages
45 | url: ${{ steps.deployment.outputs.page_url }}
46 | steps:
47 | - name: Deploy to GitHub Pages
48 | id: deployment
49 | uses: actions/deploy-pages@v4
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .calva/
2 | .clj-kondo/*
3 | !.clj-kondo/config.edn
4 | .cpcache/
5 | .lsp/
6 | .nrepl-port
7 | node_modules/
8 | resources/public/assets/
9 | resources/public/.vite/
10 | resources/public/js/
11 | .portal/
12 | .npm_pid
13 | dist/
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hiccupad
2 |
3 | Convert HTML to Hiccup
4 |
5 | Use at: https://brianium.github.io/hiccupad/
6 |
7 | ## About
8 |
9 | Really just an excuse to deploy something small with [squint](https://github.com/squint-cljs/squint), [tailwindcss](https://tailwindcss.com/), and [daisyui](https://daisyui.com/).
10 |
11 | app.cljs almost entirely written using [Cursor](https://www.cursor.com/) and [Claude 3.7 Sonnet](https://www.anthropic.com/claude/sonnet).
12 |
13 | ## Features
14 |
15 | - Convert HTML to Hiccup
16 | - Entirely client side
17 | - Copy to clipboard
18 | - Dark mode
19 | - Mobile friendly
20 | - Wraps multiple root elements in a `(list)` form
21 |
22 | ## Dev
23 |
24 | Requires
25 | - [babashka](https://github.com/babashka/babashka) for building and development.
26 | - [vite](https://vite.dev/)
27 |
28 | To develop, just run the `bb dev` task:
29 |
30 | ```bash
31 | $ bb dev
32 | ```
33 |
34 | This will start squint's watch mode and the vite dev server. View the app at [http://localhost:5173](http://localhost:5173).
35 |
36 |
37 |
--------------------------------------------------------------------------------
/bb.edn:
--------------------------------------------------------------------------------
1 | {:deps
2 | {org.babashka/json {:mvn/version "0.1.6"}}
3 |
4 | :tasks
5 | {:requires ([babashka.json :as json]
6 | [clojure.string :as str])
7 |
8 | dev:squint (shell "npx squint watch --repl true")
9 | dev:vite (shell "npx vite")
10 | -dev {:depends [dev:squint dev:vite]}
11 | dev (run '-dev {:parallel true})
12 |
13 | build:squint (shell "npx squint compile")
14 | build:vite (shell "npx vite build")
15 |
16 | update-html {:doc "Update index.html with hashed filenames from Vite manifest"
17 | :task (let [manifest (json/read-str (slurp "dist/.vite/manifest.json") {:key-fn identity})
18 | css-path (get-in manifest ["src/app.css" "file"])
19 | js-path (get-in manifest ["dist/app.js" "file"])
20 | html (slurp "index.html")
21 | updated-html (-> html
22 | (str/replace "/src/app.css" css-path)
23 | (str/replace "/dist/app.js" js-path))]
24 | ;; Copy index.html to dist directory
25 | (spit "dist/index.html" updated-html)
26 | (println "✓ Updated index.html with manifest paths and copied to dist/"))}
27 |
28 | build {:depends [build:squint build:vite update-html]}}}
29 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | hiccupad - HTML to Hiccup
10 |
19 |
20 |
21 |
22 |
38 |
39 |
40 |
41 |
42 |
47 |
48 |
49 |
52 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hiccalpine",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "hiccalpine",
9 | "version": "1.0.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "squint-cljs": "^0.8.141",
13 | "tailwindcss": "^4.0.12"
14 | },
15 | "devDependencies": {
16 | "@tailwindcss/vite": "^4.0.13",
17 | "daisyui": "^5.0.2",
18 | "vite": "^6.2.1"
19 | }
20 | },
21 | "node_modules/@esbuild/aix-ppc64": {
22 | "version": "0.25.1",
23 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz",
24 | "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==",
25 | "cpu": [
26 | "ppc64"
27 | ],
28 | "dev": true,
29 | "optional": true,
30 | "os": [
31 | "aix"
32 | ],
33 | "engines": {
34 | "node": ">=18"
35 | }
36 | },
37 | "node_modules/@esbuild/android-arm": {
38 | "version": "0.25.1",
39 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz",
40 | "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==",
41 | "cpu": [
42 | "arm"
43 | ],
44 | "dev": true,
45 | "optional": true,
46 | "os": [
47 | "android"
48 | ],
49 | "engines": {
50 | "node": ">=18"
51 | }
52 | },
53 | "node_modules/@esbuild/android-arm64": {
54 | "version": "0.25.1",
55 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz",
56 | "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==",
57 | "cpu": [
58 | "arm64"
59 | ],
60 | "dev": true,
61 | "optional": true,
62 | "os": [
63 | "android"
64 | ],
65 | "engines": {
66 | "node": ">=18"
67 | }
68 | },
69 | "node_modules/@esbuild/android-x64": {
70 | "version": "0.25.1",
71 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz",
72 | "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==",
73 | "cpu": [
74 | "x64"
75 | ],
76 | "dev": true,
77 | "optional": true,
78 | "os": [
79 | "android"
80 | ],
81 | "engines": {
82 | "node": ">=18"
83 | }
84 | },
85 | "node_modules/@esbuild/darwin-arm64": {
86 | "version": "0.25.1",
87 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz",
88 | "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==",
89 | "cpu": [
90 | "arm64"
91 | ],
92 | "dev": true,
93 | "optional": true,
94 | "os": [
95 | "darwin"
96 | ],
97 | "engines": {
98 | "node": ">=18"
99 | }
100 | },
101 | "node_modules/@esbuild/darwin-x64": {
102 | "version": "0.25.1",
103 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz",
104 | "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==",
105 | "cpu": [
106 | "x64"
107 | ],
108 | "dev": true,
109 | "optional": true,
110 | "os": [
111 | "darwin"
112 | ],
113 | "engines": {
114 | "node": ">=18"
115 | }
116 | },
117 | "node_modules/@esbuild/freebsd-arm64": {
118 | "version": "0.25.1",
119 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz",
120 | "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==",
121 | "cpu": [
122 | "arm64"
123 | ],
124 | "dev": true,
125 | "optional": true,
126 | "os": [
127 | "freebsd"
128 | ],
129 | "engines": {
130 | "node": ">=18"
131 | }
132 | },
133 | "node_modules/@esbuild/freebsd-x64": {
134 | "version": "0.25.1",
135 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz",
136 | "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==",
137 | "cpu": [
138 | "x64"
139 | ],
140 | "dev": true,
141 | "optional": true,
142 | "os": [
143 | "freebsd"
144 | ],
145 | "engines": {
146 | "node": ">=18"
147 | }
148 | },
149 | "node_modules/@esbuild/linux-arm": {
150 | "version": "0.25.1",
151 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz",
152 | "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==",
153 | "cpu": [
154 | "arm"
155 | ],
156 | "dev": true,
157 | "optional": true,
158 | "os": [
159 | "linux"
160 | ],
161 | "engines": {
162 | "node": ">=18"
163 | }
164 | },
165 | "node_modules/@esbuild/linux-arm64": {
166 | "version": "0.25.1",
167 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz",
168 | "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==",
169 | "cpu": [
170 | "arm64"
171 | ],
172 | "dev": true,
173 | "optional": true,
174 | "os": [
175 | "linux"
176 | ],
177 | "engines": {
178 | "node": ">=18"
179 | }
180 | },
181 | "node_modules/@esbuild/linux-ia32": {
182 | "version": "0.25.1",
183 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz",
184 | "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==",
185 | "cpu": [
186 | "ia32"
187 | ],
188 | "dev": true,
189 | "optional": true,
190 | "os": [
191 | "linux"
192 | ],
193 | "engines": {
194 | "node": ">=18"
195 | }
196 | },
197 | "node_modules/@esbuild/linux-loong64": {
198 | "version": "0.25.1",
199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz",
200 | "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==",
201 | "cpu": [
202 | "loong64"
203 | ],
204 | "dev": true,
205 | "optional": true,
206 | "os": [
207 | "linux"
208 | ],
209 | "engines": {
210 | "node": ">=18"
211 | }
212 | },
213 | "node_modules/@esbuild/linux-mips64el": {
214 | "version": "0.25.1",
215 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz",
216 | "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==",
217 | "cpu": [
218 | "mips64el"
219 | ],
220 | "dev": true,
221 | "optional": true,
222 | "os": [
223 | "linux"
224 | ],
225 | "engines": {
226 | "node": ">=18"
227 | }
228 | },
229 | "node_modules/@esbuild/linux-ppc64": {
230 | "version": "0.25.1",
231 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz",
232 | "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==",
233 | "cpu": [
234 | "ppc64"
235 | ],
236 | "dev": true,
237 | "optional": true,
238 | "os": [
239 | "linux"
240 | ],
241 | "engines": {
242 | "node": ">=18"
243 | }
244 | },
245 | "node_modules/@esbuild/linux-riscv64": {
246 | "version": "0.25.1",
247 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz",
248 | "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==",
249 | "cpu": [
250 | "riscv64"
251 | ],
252 | "dev": true,
253 | "optional": true,
254 | "os": [
255 | "linux"
256 | ],
257 | "engines": {
258 | "node": ">=18"
259 | }
260 | },
261 | "node_modules/@esbuild/linux-s390x": {
262 | "version": "0.25.1",
263 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz",
264 | "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==",
265 | "cpu": [
266 | "s390x"
267 | ],
268 | "dev": true,
269 | "optional": true,
270 | "os": [
271 | "linux"
272 | ],
273 | "engines": {
274 | "node": ">=18"
275 | }
276 | },
277 | "node_modules/@esbuild/linux-x64": {
278 | "version": "0.25.1",
279 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz",
280 | "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==",
281 | "cpu": [
282 | "x64"
283 | ],
284 | "dev": true,
285 | "optional": true,
286 | "os": [
287 | "linux"
288 | ],
289 | "engines": {
290 | "node": ">=18"
291 | }
292 | },
293 | "node_modules/@esbuild/netbsd-arm64": {
294 | "version": "0.25.1",
295 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz",
296 | "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==",
297 | "cpu": [
298 | "arm64"
299 | ],
300 | "dev": true,
301 | "optional": true,
302 | "os": [
303 | "netbsd"
304 | ],
305 | "engines": {
306 | "node": ">=18"
307 | }
308 | },
309 | "node_modules/@esbuild/netbsd-x64": {
310 | "version": "0.25.1",
311 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz",
312 | "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==",
313 | "cpu": [
314 | "x64"
315 | ],
316 | "dev": true,
317 | "optional": true,
318 | "os": [
319 | "netbsd"
320 | ],
321 | "engines": {
322 | "node": ">=18"
323 | }
324 | },
325 | "node_modules/@esbuild/openbsd-arm64": {
326 | "version": "0.25.1",
327 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz",
328 | "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==",
329 | "cpu": [
330 | "arm64"
331 | ],
332 | "dev": true,
333 | "optional": true,
334 | "os": [
335 | "openbsd"
336 | ],
337 | "engines": {
338 | "node": ">=18"
339 | }
340 | },
341 | "node_modules/@esbuild/openbsd-x64": {
342 | "version": "0.25.1",
343 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz",
344 | "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==",
345 | "cpu": [
346 | "x64"
347 | ],
348 | "dev": true,
349 | "optional": true,
350 | "os": [
351 | "openbsd"
352 | ],
353 | "engines": {
354 | "node": ">=18"
355 | }
356 | },
357 | "node_modules/@esbuild/sunos-x64": {
358 | "version": "0.25.1",
359 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz",
360 | "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==",
361 | "cpu": [
362 | "x64"
363 | ],
364 | "dev": true,
365 | "optional": true,
366 | "os": [
367 | "sunos"
368 | ],
369 | "engines": {
370 | "node": ">=18"
371 | }
372 | },
373 | "node_modules/@esbuild/win32-arm64": {
374 | "version": "0.25.1",
375 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz",
376 | "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==",
377 | "cpu": [
378 | "arm64"
379 | ],
380 | "dev": true,
381 | "optional": true,
382 | "os": [
383 | "win32"
384 | ],
385 | "engines": {
386 | "node": ">=18"
387 | }
388 | },
389 | "node_modules/@esbuild/win32-ia32": {
390 | "version": "0.25.1",
391 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz",
392 | "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==",
393 | "cpu": [
394 | "ia32"
395 | ],
396 | "dev": true,
397 | "optional": true,
398 | "os": [
399 | "win32"
400 | ],
401 | "engines": {
402 | "node": ">=18"
403 | }
404 | },
405 | "node_modules/@esbuild/win32-x64": {
406 | "version": "0.25.1",
407 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz",
408 | "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==",
409 | "cpu": [
410 | "x64"
411 | ],
412 | "dev": true,
413 | "optional": true,
414 | "os": [
415 | "win32"
416 | ],
417 | "engines": {
418 | "node": ">=18"
419 | }
420 | },
421 | "node_modules/@rollup/rollup-android-arm-eabi": {
422 | "version": "4.35.0",
423 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz",
424 | "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==",
425 | "cpu": [
426 | "arm"
427 | ],
428 | "dev": true,
429 | "optional": true,
430 | "os": [
431 | "android"
432 | ]
433 | },
434 | "node_modules/@rollup/rollup-android-arm64": {
435 | "version": "4.35.0",
436 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz",
437 | "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==",
438 | "cpu": [
439 | "arm64"
440 | ],
441 | "dev": true,
442 | "optional": true,
443 | "os": [
444 | "android"
445 | ]
446 | },
447 | "node_modules/@rollup/rollup-darwin-arm64": {
448 | "version": "4.35.0",
449 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz",
450 | "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==",
451 | "cpu": [
452 | "arm64"
453 | ],
454 | "dev": true,
455 | "optional": true,
456 | "os": [
457 | "darwin"
458 | ]
459 | },
460 | "node_modules/@rollup/rollup-darwin-x64": {
461 | "version": "4.35.0",
462 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz",
463 | "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==",
464 | "cpu": [
465 | "x64"
466 | ],
467 | "dev": true,
468 | "optional": true,
469 | "os": [
470 | "darwin"
471 | ]
472 | },
473 | "node_modules/@rollup/rollup-freebsd-arm64": {
474 | "version": "4.35.0",
475 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz",
476 | "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==",
477 | "cpu": [
478 | "arm64"
479 | ],
480 | "dev": true,
481 | "optional": true,
482 | "os": [
483 | "freebsd"
484 | ]
485 | },
486 | "node_modules/@rollup/rollup-freebsd-x64": {
487 | "version": "4.35.0",
488 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz",
489 | "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==",
490 | "cpu": [
491 | "x64"
492 | ],
493 | "dev": true,
494 | "optional": true,
495 | "os": [
496 | "freebsd"
497 | ]
498 | },
499 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
500 | "version": "4.35.0",
501 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz",
502 | "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==",
503 | "cpu": [
504 | "arm"
505 | ],
506 | "dev": true,
507 | "optional": true,
508 | "os": [
509 | "linux"
510 | ]
511 | },
512 | "node_modules/@rollup/rollup-linux-arm-musleabihf": {
513 | "version": "4.35.0",
514 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz",
515 | "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==",
516 | "cpu": [
517 | "arm"
518 | ],
519 | "dev": true,
520 | "optional": true,
521 | "os": [
522 | "linux"
523 | ]
524 | },
525 | "node_modules/@rollup/rollup-linux-arm64-gnu": {
526 | "version": "4.35.0",
527 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz",
528 | "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==",
529 | "cpu": [
530 | "arm64"
531 | ],
532 | "dev": true,
533 | "optional": true,
534 | "os": [
535 | "linux"
536 | ]
537 | },
538 | "node_modules/@rollup/rollup-linux-arm64-musl": {
539 | "version": "4.35.0",
540 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz",
541 | "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==",
542 | "cpu": [
543 | "arm64"
544 | ],
545 | "dev": true,
546 | "optional": true,
547 | "os": [
548 | "linux"
549 | ]
550 | },
551 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
552 | "version": "4.35.0",
553 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz",
554 | "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==",
555 | "cpu": [
556 | "loong64"
557 | ],
558 | "dev": true,
559 | "optional": true,
560 | "os": [
561 | "linux"
562 | ]
563 | },
564 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
565 | "version": "4.35.0",
566 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz",
567 | "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==",
568 | "cpu": [
569 | "ppc64"
570 | ],
571 | "dev": true,
572 | "optional": true,
573 | "os": [
574 | "linux"
575 | ]
576 | },
577 | "node_modules/@rollup/rollup-linux-riscv64-gnu": {
578 | "version": "4.35.0",
579 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz",
580 | "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==",
581 | "cpu": [
582 | "riscv64"
583 | ],
584 | "dev": true,
585 | "optional": true,
586 | "os": [
587 | "linux"
588 | ]
589 | },
590 | "node_modules/@rollup/rollup-linux-s390x-gnu": {
591 | "version": "4.35.0",
592 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz",
593 | "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==",
594 | "cpu": [
595 | "s390x"
596 | ],
597 | "dev": true,
598 | "optional": true,
599 | "os": [
600 | "linux"
601 | ]
602 | },
603 | "node_modules/@rollup/rollup-linux-x64-gnu": {
604 | "version": "4.35.0",
605 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz",
606 | "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==",
607 | "cpu": [
608 | "x64"
609 | ],
610 | "dev": true,
611 | "optional": true,
612 | "os": [
613 | "linux"
614 | ]
615 | },
616 | "node_modules/@rollup/rollup-linux-x64-musl": {
617 | "version": "4.35.0",
618 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz",
619 | "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==",
620 | "cpu": [
621 | "x64"
622 | ],
623 | "dev": true,
624 | "optional": true,
625 | "os": [
626 | "linux"
627 | ]
628 | },
629 | "node_modules/@rollup/rollup-win32-arm64-msvc": {
630 | "version": "4.35.0",
631 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz",
632 | "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==",
633 | "cpu": [
634 | "arm64"
635 | ],
636 | "dev": true,
637 | "optional": true,
638 | "os": [
639 | "win32"
640 | ]
641 | },
642 | "node_modules/@rollup/rollup-win32-ia32-msvc": {
643 | "version": "4.35.0",
644 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz",
645 | "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==",
646 | "cpu": [
647 | "ia32"
648 | ],
649 | "dev": true,
650 | "optional": true,
651 | "os": [
652 | "win32"
653 | ]
654 | },
655 | "node_modules/@rollup/rollup-win32-x64-msvc": {
656 | "version": "4.35.0",
657 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz",
658 | "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==",
659 | "cpu": [
660 | "x64"
661 | ],
662 | "dev": true,
663 | "optional": true,
664 | "os": [
665 | "win32"
666 | ]
667 | },
668 | "node_modules/@tailwindcss/node": {
669 | "version": "4.0.13",
670 | "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.13.tgz",
671 | "integrity": "sha512-P9TmtE9Vew0vv5FwyD4bsg/dHHsIsAuUXkenuGUc5gm8fYgaxpdoxIKngCyEMEQxyCKR8PQY5V5VrrKNOx7exg==",
672 | "dev": true,
673 | "dependencies": {
674 | "enhanced-resolve": "^5.18.1",
675 | "jiti": "^2.4.2",
676 | "tailwindcss": "4.0.13"
677 | }
678 | },
679 | "node_modules/@tailwindcss/oxide": {
680 | "version": "4.0.13",
681 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.0.13.tgz",
682 | "integrity": "sha512-pTH3Ex5zAWC9LbS+WsYAFmkXQW3NRjmvxkKJY3NP1x0KHBWjz0Q2uGtdGMJzsa0EwoZ7wq9RTbMH1UNPceCpWw==",
683 | "dev": true,
684 | "engines": {
685 | "node": ">= 10"
686 | },
687 | "optionalDependencies": {
688 | "@tailwindcss/oxide-android-arm64": "4.0.13",
689 | "@tailwindcss/oxide-darwin-arm64": "4.0.13",
690 | "@tailwindcss/oxide-darwin-x64": "4.0.13",
691 | "@tailwindcss/oxide-freebsd-x64": "4.0.13",
692 | "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.13",
693 | "@tailwindcss/oxide-linux-arm64-gnu": "4.0.13",
694 | "@tailwindcss/oxide-linux-arm64-musl": "4.0.13",
695 | "@tailwindcss/oxide-linux-x64-gnu": "4.0.13",
696 | "@tailwindcss/oxide-linux-x64-musl": "4.0.13",
697 | "@tailwindcss/oxide-win32-arm64-msvc": "4.0.13",
698 | "@tailwindcss/oxide-win32-x64-msvc": "4.0.13"
699 | }
700 | },
701 | "node_modules/@tailwindcss/oxide-android-arm64": {
702 | "version": "4.0.13",
703 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.13.tgz",
704 | "integrity": "sha512-+9zmwaPQ8A9ycDcdb+hRkMn6NzsmZ4YJBsW5Xqq5EdOu9xlIgmuMuJauVzDPB5BSbIWfhPdZ+le8NeRZpl1coA==",
705 | "cpu": [
706 | "arm64"
707 | ],
708 | "dev": true,
709 | "optional": true,
710 | "os": [
711 | "android"
712 | ],
713 | "engines": {
714 | "node": ">= 10"
715 | }
716 | },
717 | "node_modules/@tailwindcss/oxide-darwin-arm64": {
718 | "version": "4.0.13",
719 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.13.tgz",
720 | "integrity": "sha512-Bj1QGlEJSjs/205CIRfb5/jeveOqzJ4pFMdRxu0gyiYWxBRyxsExXqaD+7162wnLP/EDKh6S1MC9E/1GwEhLtA==",
721 | "cpu": [
722 | "arm64"
723 | ],
724 | "dev": true,
725 | "optional": true,
726 | "os": [
727 | "darwin"
728 | ],
729 | "engines": {
730 | "node": ">= 10"
731 | }
732 | },
733 | "node_modules/@tailwindcss/oxide-darwin-x64": {
734 | "version": "4.0.13",
735 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.13.tgz",
736 | "integrity": "sha512-lRTkxjTpMGXhLLM5GjZ0MtjPczMuhAo9j7PeSsaU6Imkm7W7RbrXfT8aP934kS7cBBV+HKN5U19Z0WWaORfb8Q==",
737 | "cpu": [
738 | "x64"
739 | ],
740 | "dev": true,
741 | "optional": true,
742 | "os": [
743 | "darwin"
744 | ],
745 | "engines": {
746 | "node": ">= 10"
747 | }
748 | },
749 | "node_modules/@tailwindcss/oxide-freebsd-x64": {
750 | "version": "4.0.13",
751 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.13.tgz",
752 | "integrity": "sha512-p/YLyKhs+xFibVeAPlpMGDVMKgjChgzs12VnDFaaqRSJoOz+uJgRSKiir2tn50e7Nm4YYw35q/DRBwpDBNo1MQ==",
753 | "cpu": [
754 | "x64"
755 | ],
756 | "dev": true,
757 | "optional": true,
758 | "os": [
759 | "freebsd"
760 | ],
761 | "engines": {
762 | "node": ">= 10"
763 | }
764 | },
765 | "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
766 | "version": "4.0.13",
767 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.13.tgz",
768 | "integrity": "sha512-Ua/5ydE/QOTX8jHuc7M9ICWnaLi6K2MV/r+Ws2OppsOjy8tdlPbqYainJJ6Kl7ofm524K+4Fk9CQITPzeIESPw==",
769 | "cpu": [
770 | "arm"
771 | ],
772 | "dev": true,
773 | "optional": true,
774 | "os": [
775 | "linux"
776 | ],
777 | "engines": {
778 | "node": ">= 10"
779 | }
780 | },
781 | "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
782 | "version": "4.0.13",
783 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.13.tgz",
784 | "integrity": "sha512-/W1+Q6tBAVgZWh/bhfOHo4n7Ryh6E7zYj4bJd9SRbkPyLtRioyK3bi6RLuDj57sa7Amk/DeomSV9iycS0xqIPA==",
785 | "cpu": [
786 | "arm64"
787 | ],
788 | "dev": true,
789 | "optional": true,
790 | "os": [
791 | "linux"
792 | ],
793 | "engines": {
794 | "node": ">= 10"
795 | }
796 | },
797 | "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
798 | "version": "4.0.13",
799 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.13.tgz",
800 | "integrity": "sha512-GQj6TWevNxwsYw20FdT2r2d1f7uiRsF07iFvNYxPIvIyPEV74eZ0zgFEsAH1daK1OxPy+LXdZ4grV17P5tVzhQ==",
801 | "cpu": [
802 | "arm64"
803 | ],
804 | "dev": true,
805 | "optional": true,
806 | "os": [
807 | "linux"
808 | ],
809 | "engines": {
810 | "node": ">= 10"
811 | }
812 | },
813 | "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
814 | "version": "4.0.13",
815 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.13.tgz",
816 | "integrity": "sha512-sQRH09faifF9w9WS6TKDWr1oLi4hoPx0EIWXZHQK/jcjarDpXGQ2DbF0KnALJCwWBxOIP/1nrmU01fZwwMzY3g==",
817 | "cpu": [
818 | "x64"
819 | ],
820 | "dev": true,
821 | "optional": true,
822 | "os": [
823 | "linux"
824 | ],
825 | "engines": {
826 | "node": ">= 10"
827 | }
828 | },
829 | "node_modules/@tailwindcss/oxide-linux-x64-musl": {
830 | "version": "4.0.13",
831 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.13.tgz",
832 | "integrity": "sha512-Or1N8DIF3tP+LsloJp+UXLTIMMHMUcWXFhJLCsM4T7MzFzxkeReewRWXfk5mk137cdqVeUEH/R50xAhY1mOkTQ==",
833 | "cpu": [
834 | "x64"
835 | ],
836 | "dev": true,
837 | "optional": true,
838 | "os": [
839 | "linux"
840 | ],
841 | "engines": {
842 | "node": ">= 10"
843 | }
844 | },
845 | "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
846 | "version": "4.0.13",
847 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.13.tgz",
848 | "integrity": "sha512-u2mQyqCFrr9vVTP6sfDRfGE6bhOX3/7rInehzxNhHX1HYRIx09H3sDdXzTxnZWKOjIg3qjFTCrYFUZckva5PIg==",
849 | "cpu": [
850 | "arm64"
851 | ],
852 | "dev": true,
853 | "optional": true,
854 | "os": [
855 | "win32"
856 | ],
857 | "engines": {
858 | "node": ">= 10"
859 | }
860 | },
861 | "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
862 | "version": "4.0.13",
863 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.13.tgz",
864 | "integrity": "sha512-sOEc4iCanp1Yqyeu9suQcEzfaUcHnqjBUgDg0ZXpjUMUwdSi37S1lu1RGoV1BYInvvGu3y3HHTmvsSfDhx2L8w==",
865 | "cpu": [
866 | "x64"
867 | ],
868 | "dev": true,
869 | "optional": true,
870 | "os": [
871 | "win32"
872 | ],
873 | "engines": {
874 | "node": ">= 10"
875 | }
876 | },
877 | "node_modules/@tailwindcss/vite": {
878 | "version": "4.0.13",
879 | "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.13.tgz",
880 | "integrity": "sha512-0XTd/NoVUAktIDaA4MdXhve0QWYh7WlZg20EHCuBFR80F8FhbVkRX+AY5cjbUP/IO2itHzt0iHc0iSE5kBUMhQ==",
881 | "dev": true,
882 | "dependencies": {
883 | "@tailwindcss/node": "4.0.13",
884 | "@tailwindcss/oxide": "4.0.13",
885 | "lightningcss": "1.29.2",
886 | "tailwindcss": "4.0.13"
887 | },
888 | "peerDependencies": {
889 | "vite": "^5.2.0 || ^6"
890 | }
891 | },
892 | "node_modules/@types/estree": {
893 | "version": "1.0.6",
894 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
895 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
896 | "dev": true
897 | },
898 | "node_modules/chokidar": {
899 | "version": "4.0.3",
900 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
901 | "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
902 | "dependencies": {
903 | "readdirp": "^4.0.1"
904 | },
905 | "engines": {
906 | "node": ">= 14.16.0"
907 | },
908 | "funding": {
909 | "url": "https://paulmillr.com/funding/"
910 | }
911 | },
912 | "node_modules/daisyui": {
913 | "version": "5.0.2",
914 | "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.2.tgz",
915 | "integrity": "sha512-AfOlwcE+Ukwuh2NSrMDE8VXOl9UWidj2Q5f64DEYqtZVW0Z9pELBA50iGEKg2FpBUvztFY5DFv7+eZgRts70BA==",
916 | "dev": true,
917 | "funding": {
918 | "url": "https://github.com/saadeghi/daisyui?sponsor=1"
919 | }
920 | },
921 | "node_modules/detect-libc": {
922 | "version": "2.0.3",
923 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
924 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
925 | "dev": true,
926 | "engines": {
927 | "node": ">=8"
928 | }
929 | },
930 | "node_modules/enhanced-resolve": {
931 | "version": "5.18.1",
932 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
933 | "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
934 | "dev": true,
935 | "dependencies": {
936 | "graceful-fs": "^4.2.4",
937 | "tapable": "^2.2.0"
938 | },
939 | "engines": {
940 | "node": ">=10.13.0"
941 | }
942 | },
943 | "node_modules/esbuild": {
944 | "version": "0.25.1",
945 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz",
946 | "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==",
947 | "dev": true,
948 | "hasInstallScript": true,
949 | "bin": {
950 | "esbuild": "bin/esbuild"
951 | },
952 | "engines": {
953 | "node": ">=18"
954 | },
955 | "optionalDependencies": {
956 | "@esbuild/aix-ppc64": "0.25.1",
957 | "@esbuild/android-arm": "0.25.1",
958 | "@esbuild/android-arm64": "0.25.1",
959 | "@esbuild/android-x64": "0.25.1",
960 | "@esbuild/darwin-arm64": "0.25.1",
961 | "@esbuild/darwin-x64": "0.25.1",
962 | "@esbuild/freebsd-arm64": "0.25.1",
963 | "@esbuild/freebsd-x64": "0.25.1",
964 | "@esbuild/linux-arm": "0.25.1",
965 | "@esbuild/linux-arm64": "0.25.1",
966 | "@esbuild/linux-ia32": "0.25.1",
967 | "@esbuild/linux-loong64": "0.25.1",
968 | "@esbuild/linux-mips64el": "0.25.1",
969 | "@esbuild/linux-ppc64": "0.25.1",
970 | "@esbuild/linux-riscv64": "0.25.1",
971 | "@esbuild/linux-s390x": "0.25.1",
972 | "@esbuild/linux-x64": "0.25.1",
973 | "@esbuild/netbsd-arm64": "0.25.1",
974 | "@esbuild/netbsd-x64": "0.25.1",
975 | "@esbuild/openbsd-arm64": "0.25.1",
976 | "@esbuild/openbsd-x64": "0.25.1",
977 | "@esbuild/sunos-x64": "0.25.1",
978 | "@esbuild/win32-arm64": "0.25.1",
979 | "@esbuild/win32-ia32": "0.25.1",
980 | "@esbuild/win32-x64": "0.25.1"
981 | }
982 | },
983 | "node_modules/fsevents": {
984 | "version": "2.3.3",
985 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
986 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
987 | "dev": true,
988 | "hasInstallScript": true,
989 | "optional": true,
990 | "os": [
991 | "darwin"
992 | ],
993 | "engines": {
994 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
995 | }
996 | },
997 | "node_modules/graceful-fs": {
998 | "version": "4.2.11",
999 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
1000 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
1001 | "dev": true
1002 | },
1003 | "node_modules/jiti": {
1004 | "version": "2.4.2",
1005 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
1006 | "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
1007 | "dev": true,
1008 | "bin": {
1009 | "jiti": "lib/jiti-cli.mjs"
1010 | }
1011 | },
1012 | "node_modules/lightningcss": {
1013 | "version": "1.29.2",
1014 | "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz",
1015 | "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==",
1016 | "dev": true,
1017 | "dependencies": {
1018 | "detect-libc": "^2.0.3"
1019 | },
1020 | "engines": {
1021 | "node": ">= 12.0.0"
1022 | },
1023 | "funding": {
1024 | "type": "opencollective",
1025 | "url": "https://opencollective.com/parcel"
1026 | },
1027 | "optionalDependencies": {
1028 | "lightningcss-darwin-arm64": "1.29.2",
1029 | "lightningcss-darwin-x64": "1.29.2",
1030 | "lightningcss-freebsd-x64": "1.29.2",
1031 | "lightningcss-linux-arm-gnueabihf": "1.29.2",
1032 | "lightningcss-linux-arm64-gnu": "1.29.2",
1033 | "lightningcss-linux-arm64-musl": "1.29.2",
1034 | "lightningcss-linux-x64-gnu": "1.29.2",
1035 | "lightningcss-linux-x64-musl": "1.29.2",
1036 | "lightningcss-win32-arm64-msvc": "1.29.2",
1037 | "lightningcss-win32-x64-msvc": "1.29.2"
1038 | }
1039 | },
1040 | "node_modules/lightningcss-darwin-arm64": {
1041 | "version": "1.29.2",
1042 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz",
1043 | "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==",
1044 | "cpu": [
1045 | "arm64"
1046 | ],
1047 | "dev": true,
1048 | "optional": true,
1049 | "os": [
1050 | "darwin"
1051 | ],
1052 | "engines": {
1053 | "node": ">= 12.0.0"
1054 | },
1055 | "funding": {
1056 | "type": "opencollective",
1057 | "url": "https://opencollective.com/parcel"
1058 | }
1059 | },
1060 | "node_modules/lightningcss-darwin-x64": {
1061 | "version": "1.29.2",
1062 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz",
1063 | "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==",
1064 | "cpu": [
1065 | "x64"
1066 | ],
1067 | "dev": true,
1068 | "optional": true,
1069 | "os": [
1070 | "darwin"
1071 | ],
1072 | "engines": {
1073 | "node": ">= 12.0.0"
1074 | },
1075 | "funding": {
1076 | "type": "opencollective",
1077 | "url": "https://opencollective.com/parcel"
1078 | }
1079 | },
1080 | "node_modules/lightningcss-freebsd-x64": {
1081 | "version": "1.29.2",
1082 | "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz",
1083 | "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==",
1084 | "cpu": [
1085 | "x64"
1086 | ],
1087 | "dev": true,
1088 | "optional": true,
1089 | "os": [
1090 | "freebsd"
1091 | ],
1092 | "engines": {
1093 | "node": ">= 12.0.0"
1094 | },
1095 | "funding": {
1096 | "type": "opencollective",
1097 | "url": "https://opencollective.com/parcel"
1098 | }
1099 | },
1100 | "node_modules/lightningcss-linux-arm-gnueabihf": {
1101 | "version": "1.29.2",
1102 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz",
1103 | "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==",
1104 | "cpu": [
1105 | "arm"
1106 | ],
1107 | "dev": true,
1108 | "optional": true,
1109 | "os": [
1110 | "linux"
1111 | ],
1112 | "engines": {
1113 | "node": ">= 12.0.0"
1114 | },
1115 | "funding": {
1116 | "type": "opencollective",
1117 | "url": "https://opencollective.com/parcel"
1118 | }
1119 | },
1120 | "node_modules/lightningcss-linux-arm64-gnu": {
1121 | "version": "1.29.2",
1122 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz",
1123 | "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==",
1124 | "cpu": [
1125 | "arm64"
1126 | ],
1127 | "dev": true,
1128 | "optional": true,
1129 | "os": [
1130 | "linux"
1131 | ],
1132 | "engines": {
1133 | "node": ">= 12.0.0"
1134 | },
1135 | "funding": {
1136 | "type": "opencollective",
1137 | "url": "https://opencollective.com/parcel"
1138 | }
1139 | },
1140 | "node_modules/lightningcss-linux-arm64-musl": {
1141 | "version": "1.29.2",
1142 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz",
1143 | "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==",
1144 | "cpu": [
1145 | "arm64"
1146 | ],
1147 | "dev": true,
1148 | "optional": true,
1149 | "os": [
1150 | "linux"
1151 | ],
1152 | "engines": {
1153 | "node": ">= 12.0.0"
1154 | },
1155 | "funding": {
1156 | "type": "opencollective",
1157 | "url": "https://opencollective.com/parcel"
1158 | }
1159 | },
1160 | "node_modules/lightningcss-linux-x64-gnu": {
1161 | "version": "1.29.2",
1162 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz",
1163 | "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==",
1164 | "cpu": [
1165 | "x64"
1166 | ],
1167 | "dev": true,
1168 | "optional": true,
1169 | "os": [
1170 | "linux"
1171 | ],
1172 | "engines": {
1173 | "node": ">= 12.0.0"
1174 | },
1175 | "funding": {
1176 | "type": "opencollective",
1177 | "url": "https://opencollective.com/parcel"
1178 | }
1179 | },
1180 | "node_modules/lightningcss-linux-x64-musl": {
1181 | "version": "1.29.2",
1182 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz",
1183 | "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==",
1184 | "cpu": [
1185 | "x64"
1186 | ],
1187 | "dev": true,
1188 | "optional": true,
1189 | "os": [
1190 | "linux"
1191 | ],
1192 | "engines": {
1193 | "node": ">= 12.0.0"
1194 | },
1195 | "funding": {
1196 | "type": "opencollective",
1197 | "url": "https://opencollective.com/parcel"
1198 | }
1199 | },
1200 | "node_modules/lightningcss-win32-arm64-msvc": {
1201 | "version": "1.29.2",
1202 | "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz",
1203 | "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==",
1204 | "cpu": [
1205 | "arm64"
1206 | ],
1207 | "dev": true,
1208 | "optional": true,
1209 | "os": [
1210 | "win32"
1211 | ],
1212 | "engines": {
1213 | "node": ">= 12.0.0"
1214 | },
1215 | "funding": {
1216 | "type": "opencollective",
1217 | "url": "https://opencollective.com/parcel"
1218 | }
1219 | },
1220 | "node_modules/lightningcss-win32-x64-msvc": {
1221 | "version": "1.29.2",
1222 | "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz",
1223 | "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==",
1224 | "cpu": [
1225 | "x64"
1226 | ],
1227 | "dev": true,
1228 | "optional": true,
1229 | "os": [
1230 | "win32"
1231 | ],
1232 | "engines": {
1233 | "node": ">= 12.0.0"
1234 | },
1235 | "funding": {
1236 | "type": "opencollective",
1237 | "url": "https://opencollective.com/parcel"
1238 | }
1239 | },
1240 | "node_modules/nanoid": {
1241 | "version": "3.3.9",
1242 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz",
1243 | "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==",
1244 | "dev": true,
1245 | "funding": [
1246 | {
1247 | "type": "github",
1248 | "url": "https://github.com/sponsors/ai"
1249 | }
1250 | ],
1251 | "bin": {
1252 | "nanoid": "bin/nanoid.cjs"
1253 | },
1254 | "engines": {
1255 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1256 | }
1257 | },
1258 | "node_modules/picocolors": {
1259 | "version": "1.1.1",
1260 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1261 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1262 | "dev": true
1263 | },
1264 | "node_modules/postcss": {
1265 | "version": "8.5.3",
1266 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
1267 | "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
1268 | "dev": true,
1269 | "funding": [
1270 | {
1271 | "type": "opencollective",
1272 | "url": "https://opencollective.com/postcss/"
1273 | },
1274 | {
1275 | "type": "tidelift",
1276 | "url": "https://tidelift.com/funding/github/npm/postcss"
1277 | },
1278 | {
1279 | "type": "github",
1280 | "url": "https://github.com/sponsors/ai"
1281 | }
1282 | ],
1283 | "dependencies": {
1284 | "nanoid": "^3.3.8",
1285 | "picocolors": "^1.1.1",
1286 | "source-map-js": "^1.2.1"
1287 | },
1288 | "engines": {
1289 | "node": "^10 || ^12 || >=14"
1290 | }
1291 | },
1292 | "node_modules/readdirp": {
1293 | "version": "4.1.2",
1294 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
1295 | "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
1296 | "engines": {
1297 | "node": ">= 14.18.0"
1298 | },
1299 | "funding": {
1300 | "type": "individual",
1301 | "url": "https://paulmillr.com/funding/"
1302 | }
1303 | },
1304 | "node_modules/rollup": {
1305 | "version": "4.35.0",
1306 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz",
1307 | "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==",
1308 | "dev": true,
1309 | "dependencies": {
1310 | "@types/estree": "1.0.6"
1311 | },
1312 | "bin": {
1313 | "rollup": "dist/bin/rollup"
1314 | },
1315 | "engines": {
1316 | "node": ">=18.0.0",
1317 | "npm": ">=8.0.0"
1318 | },
1319 | "optionalDependencies": {
1320 | "@rollup/rollup-android-arm-eabi": "4.35.0",
1321 | "@rollup/rollup-android-arm64": "4.35.0",
1322 | "@rollup/rollup-darwin-arm64": "4.35.0",
1323 | "@rollup/rollup-darwin-x64": "4.35.0",
1324 | "@rollup/rollup-freebsd-arm64": "4.35.0",
1325 | "@rollup/rollup-freebsd-x64": "4.35.0",
1326 | "@rollup/rollup-linux-arm-gnueabihf": "4.35.0",
1327 | "@rollup/rollup-linux-arm-musleabihf": "4.35.0",
1328 | "@rollup/rollup-linux-arm64-gnu": "4.35.0",
1329 | "@rollup/rollup-linux-arm64-musl": "4.35.0",
1330 | "@rollup/rollup-linux-loongarch64-gnu": "4.35.0",
1331 | "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0",
1332 | "@rollup/rollup-linux-riscv64-gnu": "4.35.0",
1333 | "@rollup/rollup-linux-s390x-gnu": "4.35.0",
1334 | "@rollup/rollup-linux-x64-gnu": "4.35.0",
1335 | "@rollup/rollup-linux-x64-musl": "4.35.0",
1336 | "@rollup/rollup-win32-arm64-msvc": "4.35.0",
1337 | "@rollup/rollup-win32-ia32-msvc": "4.35.0",
1338 | "@rollup/rollup-win32-x64-msvc": "4.35.0",
1339 | "fsevents": "~2.3.2"
1340 | }
1341 | },
1342 | "node_modules/source-map-js": {
1343 | "version": "1.2.1",
1344 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1345 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1346 | "dev": true,
1347 | "engines": {
1348 | "node": ">=0.10.0"
1349 | }
1350 | },
1351 | "node_modules/squint-cljs": {
1352 | "version": "0.8.141",
1353 | "resolved": "https://registry.npmjs.org/squint-cljs/-/squint-cljs-0.8.141.tgz",
1354 | "integrity": "sha512-wJfvnBsfTG1CNimZILiLlXEO2WEpGbdXbm3CZbjx0i3I02RGBcGps5UCvS8UI/m2LPxDBWBKPt96WA03m7XoJA==",
1355 | "funding": [
1356 | {
1357 | "type": "github",
1358 | "url": "https://github.com/sponsors/borkdude"
1359 | }
1360 | ],
1361 | "dependencies": {
1362 | "chokidar": "^4.0.1"
1363 | },
1364 | "bin": {
1365 | "squint": "node_cli.js"
1366 | }
1367 | },
1368 | "node_modules/tailwindcss": {
1369 | "version": "4.0.13",
1370 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.13.tgz",
1371 | "integrity": "sha512-gbvFrB0fOsTv/OugXWi2PtflJ4S6/ctu6Mmn3bCftmLY/6xRsQVEJPgIIpABwpZ52DpONkCA3bEj5b54MHxF2Q=="
1372 | },
1373 | "node_modules/tapable": {
1374 | "version": "2.2.1",
1375 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
1376 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
1377 | "dev": true,
1378 | "engines": {
1379 | "node": ">=6"
1380 | }
1381 | },
1382 | "node_modules/vite": {
1383 | "version": "6.2.1",
1384 | "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz",
1385 | "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==",
1386 | "dev": true,
1387 | "dependencies": {
1388 | "esbuild": "^0.25.0",
1389 | "postcss": "^8.5.3",
1390 | "rollup": "^4.30.1"
1391 | },
1392 | "bin": {
1393 | "vite": "bin/vite.js"
1394 | },
1395 | "engines": {
1396 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
1397 | },
1398 | "funding": {
1399 | "url": "https://github.com/vitejs/vite?sponsor=1"
1400 | },
1401 | "optionalDependencies": {
1402 | "fsevents": "~2.3.3"
1403 | },
1404 | "peerDependencies": {
1405 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
1406 | "jiti": ">=1.21.0",
1407 | "less": "*",
1408 | "lightningcss": "^1.21.0",
1409 | "sass": "*",
1410 | "sass-embedded": "*",
1411 | "stylus": "*",
1412 | "sugarss": "*",
1413 | "terser": "^5.16.0",
1414 | "tsx": "^4.8.1",
1415 | "yaml": "^2.4.2"
1416 | },
1417 | "peerDependenciesMeta": {
1418 | "@types/node": {
1419 | "optional": true
1420 | },
1421 | "jiti": {
1422 | "optional": true
1423 | },
1424 | "less": {
1425 | "optional": true
1426 | },
1427 | "lightningcss": {
1428 | "optional": true
1429 | },
1430 | "sass": {
1431 | "optional": true
1432 | },
1433 | "sass-embedded": {
1434 | "optional": true
1435 | },
1436 | "stylus": {
1437 | "optional": true
1438 | },
1439 | "sugarss": {
1440 | "optional": true
1441 | },
1442 | "terser": {
1443 | "optional": true
1444 | },
1445 | "tsx": {
1446 | "optional": true
1447 | },
1448 | "yaml": {
1449 | "optional": true
1450 | }
1451 | }
1452 | }
1453 | }
1454 | }
1455 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hiccalpine",
3 | "version": "1.0.0",
4 | "description": "npm for hiccalpine dev environment",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Brian Scaturro",
10 | "license": "MIT",
11 | "dependencies": {
12 | "squint-cljs": "^0.8.141",
13 | "tailwindcss": "^4.0.12"
14 | },
15 | "devDependencies": {
16 | "@tailwindcss/vite": "^4.0.13",
17 | "daisyui": "^5.0.2",
18 | "vite": "^6.2.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/squint.edn:
--------------------------------------------------------------------------------
1 | {:paths ["src"]
2 | :output-dir "dist"
3 | :extension "js"}
4 |
--------------------------------------------------------------------------------
/src/app.cljs:
--------------------------------------------------------------------------------
1 | (ns app
2 | (:require [clojure.string :as str]))
3 |
4 | (defn get-element-by-id [id]
5 | (js/document.getElementById id))
6 |
7 | (defn parse-attributes [attrs-string]
8 | (when (and attrs-string (not (str/blank? attrs-string)))
9 | (let [attr-pattern #"([^\s=]+)(?:=\"([^\"]*)\")?"
10 | matches (re-seq attr-pattern attrs-string)]
11 | (into {}
12 | (map (fn [[_ name value]]
13 | [(str ":" name) (or value true)])
14 | matches)))))
15 |
16 | (defn strip-html-comments [html]
17 | (str/replace html #"" ""))
18 |
19 | (defn normalize-whitespace [text]
20 | (-> text
21 | (str/replace #"\s+" " ")
22 | str/trim))
23 |
24 | (defn js-array->clj-vec [arr]
25 | (let [result (transient [])
26 | len (.-length arr)]
27 | (loop [i 0]
28 | (if (< i len)
29 | (do
30 | (conj! result (aget arr i))
31 | (recur (inc i)))
32 | (persistent! result)))))
33 |
34 | (defn has-multiple-roots? [html]
35 | (let [cleaned-html (-> html
36 | strip-html-comments
37 | str/trim)
38 | ;; Create a temporary DOM to count top-level elements
39 | temp-div (js/document.createElement "div")]
40 |
41 | ;; Set the HTML content
42 | (set! (.-innerHTML temp-div) cleaned-html)
43 |
44 | ;; Count the number of element nodes (nodeType 1) at the top level
45 | (let [child-nodes (.-childNodes temp-div)
46 | element-count (loop [i 0
47 | count 0]
48 | (if (< i (.-length child-nodes))
49 | (let [node (aget child-nodes i)]
50 | (recur (inc i)
51 | (if (= (.-nodeType node) 1)
52 | (inc count)
53 | count)))
54 | count))]
55 | (> element-count 1))))
56 |
57 | (defn simple-html->hiccup [html]
58 | (let [html (-> html
59 | strip-html-comments
60 | str/trim)
61 | has-html-tag (re-find #"]" html)
62 | has-body-tag (re-find #"]" html)
63 | has-head-tag (re-find #"]" html)
64 |
65 | ;; Check for multiple roots
66 | multiple-roots (has-multiple-roots? html)
67 |
68 | ;; For multiple root elements, wrap in a container
69 | parse-html (if multiple-roots
70 | (str "" html "
")
71 | html)
72 |
73 | dom-parser (js/DOMParser.)
74 | doc (.parseFromString dom-parser parse-html "text/html")]
75 |
76 | (letfn [(element->hiccup [el]
77 | (if (= (.-nodeType el) 3) ; Text node
78 | (let [text (normalize-whitespace (.-textContent el))]
79 | (when-not (str/blank? text)
80 | text))
81 |
82 | (when (= (.-nodeType el) 1) ; Element node
83 | (let [tag-name (str/lower-case (.-tagName el))
84 | is-wrapper (and multiple-roots
85 | (= tag-name "div")
86 | (= (.-id el) "multiple-roots-wrapper"))
87 | skip-tag (or
88 | (and (= tag-name "html") (not has-html-tag))
89 | (and (= tag-name "body") (not has-body-tag))
90 | (and (= tag-name "head") (not has-head-tag)))
91 | tag-kw (str ":" tag-name)
92 | attrs (when (.-attributes el)
93 | (let [attrs-map {}]
94 | (loop [i 0
95 | result attrs-map]
96 | (if (< i (.-length (.-attributes el)))
97 | (let [attr (aget (.-attributes el) i)
98 | name (str ":" (.-name attr))
99 | value (.-value attr)]
100 | (recur (inc i) (assoc result name value)))
101 | (when (> (count result) 0)
102 | result)))))
103 | children (js-array->clj-vec (.-childNodes el))
104 | child-hiccups (filter identity (map element->hiccup children))]
105 |
106 | (cond
107 | ;; If this is our multiple roots wrapper, return children with special marker
108 | is-wrapper
109 | (into ["__multiple_roots__"] child-hiccups)
110 |
111 | ;; If we're skipping this tag, just return its children directly
112 | skip-tag
113 | (if (empty? child-hiccups)
114 | nil
115 | (if (= (count child-hiccups) 1)
116 | (first child-hiccups)
117 | child-hiccups))
118 |
119 | ;; Otherwise return the normal hiccup form
120 | :else
121 | (if attrs
122 | (into [tag-kw attrs] child-hiccups)
123 | (into [tag-kw] child-hiccups)))))))]
124 |
125 | ;; Process the document and extract the actual content
126 | (let [raw-result (element->hiccup (.-documentElement doc))]
127 | (js/console.log "Multiple roots:" multiple-roots)
128 |
129 | ;; Check if we have multiple roots that need to be wrapped in a list
130 | (cond
131 | ;; If we have multiple roots, wrap children in a list
132 | (and multiple-roots
133 | (vector? raw-result)
134 | (= (first raw-result) "__multiple_roots__"))
135 | (into ["list"] (rest raw-result))
136 |
137 | ;; If we have a single root but got the special marker, just return the first child
138 | (and (not multiple-roots)
139 | (vector? raw-result)
140 | (= (first raw-result) "__multiple_roots__")
141 | (> (count raw-result) 1))
142 | (second raw-result)
143 |
144 | ;; If we got a single hiccup vector, return it
145 | (and (vector? raw-result)
146 | (string? (first raw-result))
147 | (str/starts-with? (first raw-result) ":"))
148 | raw-result
149 |
150 | ;; If we got a collection, find the first real element
151 | (vector? raw-result)
152 | (loop [items raw-result]
153 | (cond
154 | (empty? items) nil
155 | (and (vector? (first items))
156 | (not (empty? (first items)))
157 | (string? (first (first items)))
158 | (str/starts-with? (first (first items)) ":"))
159 | (first items)
160 | :else
161 | (recur (rest items))))
162 |
163 | ;; Otherwise just return what we got
164 | :else raw-result)))))
165 |
166 | (defn pretty-print-hiccup [hiccup]
167 | (let [indent-level (atom 0)
168 | result (atom "")]
169 |
170 | (letfn [(indent []
171 | (apply str (repeat (* 2 @indent-level) " ")))
172 |
173 | (append! [s]
174 | (swap! result str s))
175 |
176 | (pp-map [m]
177 | (append! "{")
178 | (let [entries (js/Object.entries m)
179 | len (.-length entries)]
180 | (loop [i 0]
181 | (when (< i len)
182 | (let [entry (aget entries i)
183 | k (aget entry 0)
184 | v (aget entry 1)]
185 | (append! k)
186 | (append! " ")
187 | (append! (pr-str v))
188 | ;; Add space instead of comma between entries
189 | (when (< (inc i) len)
190 | (append! " ")))
191 | (recur (inc i)))))
192 | (append! "}"))
193 |
194 | (pp [form]
195 | (cond
196 | (and (vector? form) (= (first form) "list"))
197 | (do
198 | (append! "(list")
199 | (swap! indent-level inc)
200 | (doseq [child (rest form)]
201 | (append! "\n")
202 | (append! (indent))
203 | (pp child))
204 | (swap! indent-level dec)
205 | (append! ")"))
206 |
207 | (vector? form)
208 | (do
209 | (append! "[")
210 | (when-let [tag (first form)]
211 | (append! tag)
212 | (when (and (> (count form) 1) (map? (second form)))
213 | (append! " ")
214 | (pp-map (second form))))
215 | (when (> (count form) (if (map? (second form)) 2 1))
216 | (swap! indent-level inc)
217 | (doseq [child (drop (if (map? (second form)) 2 1) form)]
218 | (append! "\n")
219 | (append! (indent))
220 | (pp child))
221 | (swap! indent-level dec))
222 | (append! "]"))
223 |
224 | (map? form)
225 | (pp-map form)
226 |
227 | :else (append! (pr-str form))))]
228 |
229 | (pp hiccup)
230 | @result)))
231 |
232 | (defn translate [event]
233 | (let [html-input (.. event -target -value)
234 | result-el (get-element-by-id "result-output")]
235 | (when (and html-input (not (str/blank? html-input)))
236 | (try
237 | (let [hiccup (simple-html->hiccup html-input)
238 | pretty-hiccup (pretty-print-hiccup hiccup)]
239 | ;; Clear the result element
240 | (set! (.-innerHTML result-el) "")
241 | (.setAttribute result-el "data-count" (count hiccup))
242 | ;; Create pre and code elements
243 | (let [pre-el (js/document.createElement "pre")
244 | code-el (js/document.createElement "code")]
245 |
246 | ;; Add classes to elements
247 | (.add (.-classList pre-el) "whitespace-pre-wrap")
248 |
249 | ;; Add Tailwind classes for compact text
250 | (.add (.-classList code-el) "text-xs")
251 | (.add (.-classList code-el) "leading-tight")
252 | (.add (.-classList code-el) "font-mono")
253 | (.add (.-classList code-el) "language-clojure") ;; Add language class for Prism
254 |
255 | ;; Set the hiccup content
256 | (set! (.-textContent code-el) pretty-hiccup)
257 |
258 | ;; Append elements
259 | (.appendChild pre-el code-el)
260 | (.appendChild result-el pre-el)
261 |
262 | ;; Apply syntax highlighting
263 | (when (and js/window.Prism js/window.Prism.highlightElement)
264 | (js/window.Prism.highlightElement code-el))))
265 | (catch js/Error e
266 | (set! (.-innerHTML result-el)
267 | (str "Error parsing HTML: "
268 | (.-message e)
269 | "
")))))
270 |
271 | (js/console.log "Translation complete")))
272 |
273 | (defn toggle-convert-button []
274 | (let [textarea (get-element-by-id "html-input")
275 | convert-button (get-element-by-id "convert-button")]
276 | (if (and textarea (not (str/blank? (.-value textarea))))
277 | (.remove (.-classList convert-button) "hidden")
278 | (.add (.-classList convert-button) "hidden"))))
279 |
280 | (defn copy-to-clipboard []
281 | (let [result-el (get-element-by-id "result-output")
282 | copy-button (get-element-by-id "copy-button")
283 | code-el (when result-el (.querySelector result-el "code"))]
284 | (when (and code-el copy-button)
285 | (let [text-content (.-textContent code-el)
286 | temp-textarea (js/document.createElement "textarea")]
287 | (set! (.-value temp-textarea) text-content)
288 | (set! (.-style temp-textarea) "position: absolute; left: -9999px;")
289 | (.appendChild js/document.body temp-textarea)
290 | (.select temp-textarea)
291 | (js/document.execCommand "copy")
292 | (.removeChild js/document.body temp-textarea)
293 |
294 | ;; Show success feedback
295 | (let [icon-elements (.querySelectorAll copy-button "svg")]
296 | (when (and (> (.-length icon-elements) 0) (> (.-length icon-elements) 1))
297 | (.add (.-classList (aget icon-elements 0)) "hidden")
298 | (.remove (.-classList (aget icon-elements 1)) "hidden")
299 | (js/setTimeout (fn []
300 | (.remove (.-classList (aget icon-elements 0)) "hidden")
301 | (.add (.-classList (aget icon-elements 1)) "hidden"))
302 | 1500)))))))
303 |
304 | (defn init []
305 | (let [textarea (get-element-by-id "html-input")
306 | convert-button (get-element-by-id "convert-button")
307 | copy-button (get-element-by-id "copy-button")]
308 | (when (and textarea convert-button copy-button)
309 | (.addEventListener textarea "input" (fn [_] (toggle-convert-button)))
310 | (.addEventListener textarea "blur" translate)
311 | (.addEventListener convert-button "click" translate)
312 | (.addEventListener copy-button "click" (fn [_] (copy-to-clipboard))))))
313 |
314 | (init)
315 |
--------------------------------------------------------------------------------
/src/app.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 | @plugin "daisyui" {
3 | themes: winter --default, sunset --prefersdark;
4 | }
5 |
6 | @theme {
7 | --font-sans: InterVariable, sans-serif;
8 | }
9 |
10 | [data-count="0"] + #copy-button {
11 | display: none;
12 | }
13 |
--------------------------------------------------------------------------------
/vite.config.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import tailwindcss from '@tailwindcss/vite';
3 |
4 | export default defineConfig({
5 | plugins: [
6 | tailwindcss()
7 | ],
8 | build: {
9 | outDir: 'dist',
10 | emptyOutDir: false,
11 | manifest: true,
12 | rollupOptions: {
13 | input: ['src/app.css', 'dist/app.js']
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------