⭐
Log in to mark this repository.
fix frontend biz
14ab219 · gmorell · 2026-06-17 13:57
Files changed
modified
Dockerfile
+2
−1
@@ -4,7 +4,7 @@
| 4 | 4 | # RUN steps, so subsequent `cp` from the cached target/ would miss). |
| 5 | 5 | |
| 6 | 6 | # --------------------------------------------------------------------------- |
| 7 | −# Stage 1 — assets: compile Tailwind CSS and stage FontAwesome webfonts. | |
| 7 | +# Stage 1 — assets: compile Tailwind CSS, bundle JS, and stage FontAwesome webfonts. | |
| 8 | 8 | # --------------------------------------------------------------------------- |
| 9 | 9 | FROM node:20-alpine AS assets |
| 10 | 10 | WORKDIR /app |
@@ -19,6 +19,7 @@ COPY templates ./templates
| 19 | 19 | |
| 20 | 20 | RUN cd assets \ |
| 21 | 21 | && ./node_modules/.bin/tailwindcss -c tailwind.config.js -i f/css/style.css -o f/css/app.css \ |
| 22 | + && ./node_modules/.bin/esbuild f/js/src.js --bundle --minify --outfile=f/js/app.js \ | |
| 22 | 23 | && mkdir -p f/webfonts \ |
| 23 | 24 | && cp node_modules/@fortawesome/fontawesome-free/webfonts/*.woff2 f/webfonts/ \ |
| 24 | 25 | && cp node_modules/@fortawesome/fontawesome-free/webfonts/*.ttf f/webfonts/ |
modified
Justfile
+10
−3
@@ -2,19 +2,26 @@ set shell := ["bash", "-cu"]
| 2 | 2 | |
| 3 | 3 | assets_dir := "assets" |
| 4 | 4 | tailwind := "./node_modules/.bin/tailwindcss" |
| 5 | +esbuild := "./node_modules/.bin/esbuild" | |
| 5 | 6 | css_in := "f/css/style.css" |
| 6 | 7 | css_out := "f/css/app.css" |
| 8 | +js_in := "f/js/src.js" | |
| 9 | +js_out := "f/js/app.js" | |
| 7 | 10 | |
| 8 | 11 | # Default: list available recipes |
| 9 | 12 | default: |
| 10 | 13 | @just --list |
| 11 | 14 | |
| 12 | −# One-shot CSS build + sync vendored webfonts/fonts | |
| 13 | −assets: webfonts | |
| 15 | +# One-shot CSS + JS build + sync vendored webfonts/fonts | |
| 16 | +assets: webfonts js | |
| 14 | 17 | cd {{assets_dir}} && {{tailwind}} -c tailwind.config.js -i {{css_in}} -o {{css_out}} |
| 15 | 18 | |
| 19 | +# Bundle + minify JS (src.js -> app.js), mirroring the Dockerfile assets stage | |
| 20 | +js: | |
| 21 | + cd {{assets_dir}} && {{esbuild}} {{js_in}} --bundle --minify --outfile={{js_out}} | |
| 22 | + | |
| 16 | 23 | # Watch CSS for changes; webfonts only need to be synced once per dep change |
| 17 | −watch: webfonts | |
| 24 | +watch: webfonts js | |
| 18 | 25 | cd {{assets_dir}} && {{tailwind}} -c tailwind.config.js -i {{css_in}} -o {{css_out}} --watch |
| 19 | 26 | |
| 20 | 27 | # Copy vendored fonts into the served /assets tree. |
modified
assets/f/js/src.js
+138
−0
@@ -0,0 +1,138 @@
| 1 | +(() => { | |
| 2 | + const isTypingTarget = (el) => { | |
| 3 | + if (!el) return false; | |
| 4 | + const tag = el.tagName; | |
| 5 | + if (tag === "TEXTAREA") return true; | |
| 6 | + if (tag === "INPUT") { | |
| 7 | + const t = el.type; | |
| 8 | + return t !== "file" && t !== "checkbox" && t !== "radio" && t !== "button" && t !== "submit"; | |
| 9 | + } | |
| 10 | + return !!el.isContentEditable; | |
| 11 | + }; | |
| 12 | + | |
| 13 | + const extFor = (type) => { | |
| 14 | + if (!type) return "bin"; | |
| 15 | + const slash = type.indexOf("/"); | |
| 16 | + return slash >= 0 ? type.slice(slash + 1).split("+")[0] : "bin"; | |
| 17 | + }; | |
| 18 | + | |
| 19 | + const pastedName = (blob) => { | |
| 20 | + if (blob.name && blob.name !== "image.png") return blob; | |
| 21 | + return new File([blob], `pasted-${Date.now()}.${extFor(blob.type)}`, { type: blob.type }); | |
| 22 | + }; | |
| 23 | + | |
| 24 | + // Toast — created on demand, auto-removes after a few seconds. | |
| 25 | + const showToast = (msg, opts = {}) => { | |
| 26 | + let host = document.getElementById("dms-toast-host"); | |
| 27 | + if (!host) { | |
| 28 | + host = document.createElement("div"); | |
| 29 | + host.id = "dms-toast-host"; | |
| 30 | + host.className = "toast toast-end z-50"; | |
| 31 | + document.body.appendChild(host); | |
| 32 | + } | |
| 33 | + const alert = document.createElement("div"); | |
| 34 | + const kind = opts.kind || "info"; | |
| 35 | + alert.className = `alert alert-${kind} shadow-lg`; | |
| 36 | + if (opts.href) { | |
| 37 | + const a = document.createElement("a"); | |
| 38 | + a.href = opts.href; | |
| 39 | + a.className = "underline"; | |
| 40 | + a.textContent = msg; | |
| 41 | + alert.appendChild(a); | |
| 42 | + } else { | |
| 43 | + const span = document.createElement("span"); | |
| 44 | + span.textContent = msg; | |
| 45 | + alert.appendChild(span); | |
| 46 | + } | |
| 47 | + host.appendChild(alert); | |
| 48 | + const ttl = opts.ttl ?? 4000; | |
| 49 | + if (ttl > 0) setTimeout(() => alert.remove(), ttl); | |
| 50 | + return alert; | |
| 51 | + }; | |
| 52 | + | |
| 53 | + // Path 1: a quick-upload form is on this page — attach the pasted file to it. | |
| 54 | + const attachToQuickForm = (file) => { | |
| 55 | + const fileInput = document.getElementById("quick-upload-file"); | |
| 56 | + const preview = document.getElementById("quick-upload-preview"); | |
| 57 | + if (!fileInput) return false; | |
| 58 | + const dt = new DataTransfer(); | |
| 59 | + dt.items.add(file); | |
| 60 | + fileInput.files = dt.files; | |
| 61 | + if (preview) { | |
| 62 | + const img = preview.querySelector("img"); | |
| 63 | + const name = preview.querySelector("[data-name]"); | |
| 64 | + if (img) { | |
| 65 | + if (img.src) URL.revokeObjectURL(img.src); | |
| 66 | + img.src = URL.createObjectURL(file); | |
| 67 | + } | |
| 68 | + if (name) name.textContent = `${file.name} · ${(file.size / 1024).toFixed(1)} KB`; | |
| 69 | + preview.classList.remove("hidden"); | |
| 70 | + preview.classList.add("flex"); | |
| 71 | + } | |
| 72 | + fileInput.scrollIntoView({ behavior: "smooth", block: "center" }); | |
| 73 | + return true; | |
| 74 | + }; | |
| 75 | + | |
| 76 | + // Path 2: anywhere else on the site — POST it directly and surface the result. | |
| 77 | + const uploadDirect = async (file) => { | |
| 78 | + const fd = new FormData(); | |
| 79 | + fd.append("file", file, file.name); | |
| 80 | + const status = showToast(`Uploading ${file.name}…`, { kind: "info", ttl: 0 }); | |
| 81 | + try { | |
| 82 | + const res = await fetch("/uploads", { method: "POST", body: fd, credentials: "same-origin" }); | |
| 83 | + status.remove(); | |
| 84 | + if (res.redirected && res.url.includes("/login")) { | |
| 85 | + showToast("Sign in to upload.", { kind: "warning" }); | |
| 86 | + return; | |
| 87 | + } | |
| 88 | + if (!res.ok) { | |
| 89 | + showToast(`Upload failed (${res.status}).`, { kind: "error" }); | |
| 90 | + return; | |
| 91 | + } | |
| 92 | + const href = res.redirected ? res.url : "/uploads"; | |
| 93 | + showToast(`Uploaded ${file.name} — view`, { kind: "success", href }); | |
| 94 | + } catch (e) { | |
| 95 | + status.remove(); | |
| 96 | + showToast(`Upload error: ${e.message || e}`, { kind: "error" }); | |
| 97 | + } | |
| 98 | + }; | |
| 99 | + | |
| 100 | + document.addEventListener("paste", (e) => { | |
| 101 | + if (!document.body.dataset.authed) return; | |
| 102 | + if (isTypingTarget(e.target)) return; | |
| 103 | + const items = e.clipboardData && e.clipboardData.items; | |
| 104 | + if (!items) return; | |
| 105 | + for (const it of items) { | |
| 106 | + if (it.kind !== "file") continue; | |
| 107 | + const blob = it.getAsFile(); | |
| 108 | + if (!blob || !blob.type.startsWith("image/")) continue; | |
| 109 | + const file = pastedName(blob); | |
| 110 | + e.preventDefault(); | |
| 111 | + if (!attachToQuickForm(file)) uploadDirect(file); | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + }); | |
| 115 | + | |
| 116 | + // When the quick-upload form is on the page, also preview manual file picks. | |
| 117 | + const quickFile = document.getElementById("quick-upload-file"); | |
| 118 | + const quickPreview = document.getElementById("quick-upload-preview"); | |
| 119 | + if (quickFile && quickPreview) { | |
| 120 | + const img = quickPreview.querySelector("img"); | |
| 121 | + const name = quickPreview.querySelector("[data-name]"); | |
| 122 | + quickFile.addEventListener("change", () => { | |
| 123 | + const f = quickFile.files && quickFile.files[0]; | |
| 124 | + if (!f || !f.type.startsWith("image/")) { | |
| 125 | + quickPreview.classList.add("hidden"); | |
| 126 | + quickPreview.classList.remove("flex"); | |
| 127 | + return; | |
| 128 | + } | |
| 129 | + if (img) { | |
| 130 | + if (img.src) URL.revokeObjectURL(img.src); | |
| 131 | + img.src = URL.createObjectURL(f); | |
| 132 | + } | |
| 133 | + if (name) name.textContent = `${f.name} · ${(f.size / 1024).toFixed(1)} KB`; | |
| 134 | + quickPreview.classList.remove("hidden"); | |
| 135 | + quickPreview.classList.add("flex"); | |
| 136 | + }); | |
| 137 | + } | |
| 138 | +})(); |
modified
assets/package-lock.json
+487
−60
@@ -11,11 +11,12 @@
| 11 | 11 | "@tailwindcss/forms": "^0.5.10", |
| 12 | 12 | "alpinejs": "^3.14.9", |
| 13 | 13 | "daisyui": "^4.12.24", |
| 14 | − "html2canvas": "^1.4.1", | |
| 15 | 14 | "htmx-ext-ws": "^2.0.3", |
| 16 | 15 | "htmx.org": "^2.0.4", |
| 17 | − "prismjs": "^1.29.0", | |
| 18 | 16 | "tailwindcss": "^3.4.17" |
| 17 | + }, | |
| 18 | + "devDependencies": { | |
| 19 | + "esbuild": "^0.28.1" | |
| 19 | 20 | } |
| 20 | 21 | }, |
| 21 | 22 | "node_modules/@alloc/quick-lru": { |
@@ -30,6 +31,448 @@
| 30 | 31 | "url": "https://github.com/sponsors/sindresorhus" |
| 31 | 32 | } |
| 32 | 33 | }, |
| 34 | + "node_modules/@esbuild/aix-ppc64": { | |
| 35 | + "version": "0.28.1", | |
| 36 | + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", | |
| 37 | + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", | |
| 38 | + "cpu": [ | |
| 39 | + "ppc64" | |
| 40 | + ], | |
| 41 | + "dev": true, | |
| 42 | + "license": "MIT", | |
| 43 | + "optional": true, | |
| 44 | + "os": [ | |
| 45 | + "aix" | |
| 46 | + ], | |
| 47 | + "engines": { | |
| 48 | + "node": ">=18" | |
| 49 | + } | |
| 50 | + }, | |
| 51 | + "node_modules/@esbuild/android-arm": { | |
| 52 | + "version": "0.28.1", | |
| 53 | + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", | |
| 54 | + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", | |
| 55 | + "cpu": [ | |
| 56 | + "arm" | |
| 57 | + ], | |
| 58 | + "dev": true, | |
| 59 | + "license": "MIT", | |
| 60 | + "optional": true, | |
| 61 | + "os": [ | |
| 62 | + "android" | |
| 63 | + ], | |
| 64 | + "engines": { | |
| 65 | + "node": ">=18" | |
| 66 | + } | |
| 67 | + }, | |
| 68 | + "node_modules/@esbuild/android-arm64": { | |
| 69 | + "version": "0.28.1", | |
| 70 | + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", | |
| 71 | + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", | |
| 72 | + "cpu": [ | |
| 73 | + "arm64" | |
| 74 | + ], | |
| 75 | + "dev": true, | |
| 76 | + "license": "MIT", | |
| 77 | + "optional": true, | |
| 78 | + "os": [ | |
| 79 | + "android" | |
| 80 | + ], | |
| 81 | + "engines": { | |
| 82 | + "node": ">=18" | |
| 83 | + } | |
| 84 | + }, | |
| 85 | + "node_modules/@esbuild/android-x64": { | |
| 86 | + "version": "0.28.1", | |
| 87 | + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", | |
| 88 | + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", | |
| 89 | + "cpu": [ | |
| 90 | + "x64" | |
| 91 | + ], | |
| 92 | + "dev": true, | |
| 93 | + "license": "MIT", | |
| 94 | + "optional": true, | |
| 95 | + "os": [ | |
| 96 | + "android" | |
| 97 | + ], | |
| 98 | + "engines": { | |
| 99 | + "node": ">=18" | |
| 100 | + } | |
| 101 | + }, | |
| 102 | + "node_modules/@esbuild/darwin-arm64": { | |
| 103 | + "version": "0.28.1", | |
| 104 | + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", | |
| 105 | + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", | |
| 106 | + "cpu": [ | |
| 107 | + "arm64" | |
| 108 | + ], | |
| 109 | + "dev": true, | |
| 110 | + "license": "MIT", | |
| 111 | + "optional": true, | |
| 112 | + "os": [ | |
| 113 | + "darwin" | |
| 114 | + ], | |
| 115 | + "engines": { | |
| 116 | + "node": ">=18" | |
| 117 | + } | |
| 118 | + }, | |
| 119 | + "node_modules/@esbuild/darwin-x64": { | |
| 120 | + "version": "0.28.1", | |
| 121 | + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", | |
| 122 | + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", | |
| 123 | + "cpu": [ | |
| 124 | + "x64" | |
| 125 | + ], | |
| 126 | + "dev": true, | |
| 127 | + "license": "MIT", | |
| 128 | + "optional": true, | |
| 129 | + "os": [ | |
| 130 | + "darwin" | |
| 131 | + ], | |
| 132 | + "engines": { | |
| 133 | + "node": ">=18" | |
| 134 | + } | |
| 135 | + }, | |
| 136 | + "node_modules/@esbuild/freebsd-arm64": { | |
| 137 | + "version": "0.28.1", | |
| 138 | + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", | |
| 139 | + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", | |
| 140 | + "cpu": [ | |
| 141 | + "arm64" | |
| 142 | + ], | |
| 143 | + "dev": true, | |
| 144 | + "license": "MIT", | |
| 145 | + "optional": true, | |
| 146 | + "os": [ | |
| 147 | + "freebsd" | |
| 148 | + ], | |
| 149 | + "engines": { | |
| 150 | + "node": ">=18" | |
| 151 | + } | |
| 152 | + }, | |
| 153 | + "node_modules/@esbuild/freebsd-x64": { | |
| 154 | + "version": "0.28.1", | |
| 155 | + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", | |
| 156 | + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", | |
| 157 | + "cpu": [ | |
| 158 | + "x64" | |
| 159 | + ], | |
| 160 | + "dev": true, | |
| 161 | + "license": "MIT", | |
| 162 | + "optional": true, | |
| 163 | + "os": [ | |
| 164 | + "freebsd" | |
| 165 | + ], | |
| 166 | + "engines": { | |
| 167 | + "node": ">=18" | |
| 168 | + } | |
| 169 | + }, | |
| 170 | + "node_modules/@esbuild/linux-arm": { | |
| 171 | + "version": "0.28.1", | |
| 172 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", | |
| 173 | + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", | |
| 174 | + "cpu": [ | |
| 175 | + "arm" | |
| 176 | + ], | |
| 177 | + "dev": true, | |
| 178 | + "license": "MIT", | |
| 179 | + "optional": true, | |
| 180 | + "os": [ | |
| 181 | + "linux" | |
| 182 | + ], | |
| 183 | + "engines": { | |
| 184 | + "node": ">=18" | |
| 185 | + } | |
| 186 | + }, | |
| 187 | + "node_modules/@esbuild/linux-arm64": { | |
| 188 | + "version": "0.28.1", | |
| 189 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", | |
| 190 | + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", | |
| 191 | + "cpu": [ | |
| 192 | + "arm64" | |
| 193 | + ], | |
| 194 | + "dev": true, | |
| 195 | + "license": "MIT", | |
| 196 | + "optional": true, | |
| 197 | + "os": [ | |
| 198 | + "linux" | |
| 199 | + ], | |
| 200 | + "engines": { | |
| 201 | + "node": ">=18" | |
| 202 | + } | |
| 203 | + }, | |
| 204 | + "node_modules/@esbuild/linux-ia32": { | |
| 205 | + "version": "0.28.1", | |
| 206 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", | |
| 207 | + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", | |
| 208 | + "cpu": [ | |
| 209 | + "ia32" | |
| 210 | + ], | |
| 211 | + "dev": true, | |
| 212 | + "license": "MIT", | |
| 213 | + "optional": true, | |
| 214 | + "os": [ | |
| 215 | + "linux" | |
| 216 | + ], | |
| 217 | + "engines": { | |
| 218 | + "node": ">=18" | |
| 219 | + } | |
| 220 | + }, | |
| 221 | + "node_modules/@esbuild/linux-loong64": { | |
| 222 | + "version": "0.28.1", | |
| 223 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", | |
| 224 | + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", | |
| 225 | + "cpu": [ | |
| 226 | + "loong64" | |
| 227 | + ], | |
| 228 | + "dev": true, | |
| 229 | + "license": "MIT", | |
| 230 | + "optional": true, | |
| 231 | + "os": [ | |
| 232 | + "linux" | |
| 233 | + ], | |
| 234 | + "engines": { | |
| 235 | + "node": ">=18" | |
| 236 | + } | |
| 237 | + }, | |
| 238 | + "node_modules/@esbuild/linux-mips64el": { | |
| 239 | + "version": "0.28.1", | |
| 240 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", | |
| 241 | + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", | |
| 242 | + "cpu": [ | |
| 243 | + "mips64el" | |
| 244 | + ], | |
| 245 | + "dev": true, | |
| 246 | + "license": "MIT", | |
| 247 | + "optional": true, | |
| 248 | + "os": [ | |
| 249 | + "linux" | |
| 250 | + ], | |
| 251 | + "engines": { | |
| 252 | + "node": ">=18" | |
| 253 | + } | |
| 254 | + }, | |
| 255 | + "node_modules/@esbuild/linux-ppc64": { | |
| 256 | + "version": "0.28.1", | |
| 257 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", | |
| 258 | + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", | |
| 259 | + "cpu": [ | |
| 260 | + "ppc64" | |
| 261 | + ], | |
| 262 | + "dev": true, | |
| 263 | + "license": "MIT", | |
| 264 | + "optional": true, | |
| 265 | + "os": [ | |
| 266 | + "linux" | |
| 267 | + ], | |
| 268 | + "engines": { | |
| 269 | + "node": ">=18" | |
| 270 | + } | |
| 271 | + }, | |
| 272 | + "node_modules/@esbuild/linux-riscv64": { | |
| 273 | + "version": "0.28.1", | |
| 274 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", | |
| 275 | + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", | |
| 276 | + "cpu": [ | |
| 277 | + "riscv64" | |
| 278 | + ], | |
| 279 | + "dev": true, | |
| 280 | + "license": "MIT", | |
| 281 | + "optional": true, | |
| 282 | + "os": [ | |
| 283 | + "linux" | |
| 284 | + ], | |
| 285 | + "engines": { | |
| 286 | + "node": ">=18" | |
| 287 | + } | |
| 288 | + }, | |
| 289 | + "node_modules/@esbuild/linux-s390x": { | |
| 290 | + "version": "0.28.1", | |
| 291 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", | |
| 292 | + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", | |
| 293 | + "cpu": [ | |
| 294 | + "s390x" | |
| 295 | + ], | |
| 296 | + "dev": true, | |
| 297 | + "license": "MIT", | |
| 298 | + "optional": true, | |
| 299 | + "os": [ | |
| 300 | + "linux" | |
| 301 | + ], | |
| 302 | + "engines": { | |
| 303 | + "node": ">=18" | |
| 304 | + } | |
| 305 | + }, | |
| 306 | + "node_modules/@esbuild/linux-x64": { | |
| 307 | + "version": "0.28.1", | |
| 308 | + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", | |
| 309 | + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", | |
| 310 | + "cpu": [ | |
| 311 | + "x64" | |
| 312 | + ], | |
| 313 | + "dev": true, | |
| 314 | + "license": "MIT", | |
| 315 | + "optional": true, | |
| 316 | + "os": [ | |
| 317 | + "linux" | |
| 318 | + ], | |
| 319 | + "engines": { | |
| 320 | + "node": ">=18" | |
| 321 | + } | |
| 322 | + }, | |
| 323 | + "node_modules/@esbuild/netbsd-arm64": { | |
| 324 | + "version": "0.28.1", | |
| 325 | + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", | |
| 326 | + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", | |
| 327 | + "cpu": [ | |
| 328 | + "arm64" | |
| 329 | + ], | |
| 330 | + "dev": true, | |
| 331 | + "license": "MIT", | |
| 332 | + "optional": true, | |
| 333 | + "os": [ | |
| 334 | + "netbsd" | |
| 335 | + ], | |
| 336 | + "engines": { | |
| 337 | + "node": ">=18" | |
| 338 | + } | |
| 339 | + }, | |
| 340 | + "node_modules/@esbuild/netbsd-x64": { | |
| 341 | + "version": "0.28.1", | |
| 342 | + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", | |
| 343 | + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", | |
| 344 | + "cpu": [ | |
| 345 | + "x64" | |
| 346 | + ], | |
| 347 | + "dev": true, | |
| 348 | + "license": "MIT", | |
| 349 | + "optional": true, | |
| 350 | + "os": [ | |
| 351 | + "netbsd" | |
| 352 | + ], | |
| 353 | + "engines": { | |
| 354 | + "node": ">=18" | |
| 355 | + } | |
| 356 | + }, | |
| 357 | + "node_modules/@esbuild/openbsd-arm64": { | |
| 358 | + "version": "0.28.1", | |
| 359 | + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", | |
| 360 | + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", | |
| 361 | + "cpu": [ | |
| 362 | + "arm64" | |
| 363 | + ], | |
| 364 | + "dev": true, | |
| 365 | + "license": "MIT", | |
| 366 | + "optional": true, | |
| 367 | + "os": [ | |
| 368 | + "openbsd" | |
| 369 | + ], | |
| 370 | + "engines": { | |
| 371 | + "node": ">=18" | |
| 372 | + } | |
| 373 | + }, | |
| 374 | + "node_modules/@esbuild/openbsd-x64": { | |
| 375 | + "version": "0.28.1", | |
| 376 | + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", | |
| 377 | + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", | |
| 378 | + "cpu": [ | |
| 379 | + "x64" | |
| 380 | + ], | |
| 381 | + "dev": true, | |
| 382 | + "license": "MIT", | |
| 383 | + "optional": true, | |
| 384 | + "os": [ | |
| 385 | + "openbsd" | |
| 386 | + ], | |
| 387 | + "engines": { | |
| 388 | + "node": ">=18" | |
| 389 | + } | |
| 390 | + }, | |
| 391 | + "node_modules/@esbuild/openharmony-arm64": { | |
| 392 | + "version": "0.28.1", | |
| 393 | + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", | |
| 394 | + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", | |
| 395 | + "cpu": [ | |
| 396 | + "arm64" | |
| 397 | + ], | |
| 398 | + "dev": true, | |
| 399 | + "license": "MIT", | |
| 400 | + "optional": true, | |
| 401 | + "os": [ | |
| 402 | + "openharmony" | |
| 403 | + ], | |
| 404 | + "engines": { | |
| 405 | + "node": ">=18" | |
| 406 | + } | |
| 407 | + }, | |
| 408 | + "node_modules/@esbuild/sunos-x64": { | |
| 409 | + "version": "0.28.1", | |
| 410 | + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", | |
| 411 | + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", | |
| 412 | + "cpu": [ | |
| 413 | + "x64" | |
| 414 | + ], | |
| 415 | + "dev": true, | |
| 416 | + "license": "MIT", | |
| 417 | + "optional": true, | |
| 418 | + "os": [ | |
| 419 | + "sunos" | |
| 420 | + ], | |
| 421 | + "engines": { | |
| 422 | + "node": ">=18" | |
| 423 | + } | |
| 424 | + }, | |
| 425 | + "node_modules/@esbuild/win32-arm64": { | |
| 426 | + "version": "0.28.1", | |
| 427 | + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", | |
| 428 | + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", | |
| 429 | + "cpu": [ | |
| 430 | + "arm64" | |
| 431 | + ], | |
| 432 | + "dev": true, | |
| 433 | + "license": "MIT", | |
| 434 | + "optional": true, | |
| 435 | + "os": [ | |
| 436 | + "win32" | |
| 437 | + ], | |
| 438 | + "engines": { | |
| 439 | + "node": ">=18" | |
| 440 | + } | |
| 441 | + }, | |
| 442 | + "node_modules/@esbuild/win32-ia32": { | |
| 443 | + "version": "0.28.1", | |
| 444 | + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", | |
| 445 | + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", | |
| 446 | + "cpu": [ | |
| 447 | + "ia32" | |
| 448 | + ], | |
| 449 | + "dev": true, | |
| 450 | + "license": "MIT", | |
| 451 | + "optional": true, | |
| 452 | + "os": [ | |
| 453 | + "win32" | |
| 454 | + ], | |
| 455 | + "engines": { | |
| 456 | + "node": ">=18" | |
| 457 | + } | |
| 458 | + }, | |
| 459 | + "node_modules/@esbuild/win32-x64": { | |
| 460 | + "version": "0.28.1", | |
| 461 | + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", | |
| 462 | + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", | |
| 463 | + "cpu": [ | |
| 464 | + "x64" | |
| 465 | + ], | |
| 466 | + "dev": true, | |
| 467 | + "license": "MIT", | |
| 468 | + "optional": true, | |
| 469 | + "os": [ | |
| 470 | + "win32" | |
| 471 | + ], | |
| 472 | + "engines": { | |
| 473 | + "node": ">=18" | |
| 474 | + } | |
| 475 | + }, | |
| 33 | 476 | "node_modules/@fontsource/b612": { |
| 34 | 477 | "version": "5.2.7", |
| 35 | 478 | "resolved": "https://registry.npmjs.org/@fontsource/b612/-/b612-5.2.7.tgz", |
@@ -245,15 +688,6 @@
| 245 | 688 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", |
| 246 | 689 | "license": "MIT" |
| 247 | 690 | }, |
| 248 | − "node_modules/base64-arraybuffer": { | |
| 249 | − "version": "1.0.2", | |
| 250 | − "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", | |
| 251 | − "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", | |
| 252 | − "license": "MIT", | |
| 253 | − "engines": { | |
| 254 | − "node": ">= 0.6.0" | |
| 255 | − } | |
| 256 | − }, | |
| 257 | 691 | "node_modules/binary-extensions": { |
| 258 | 692 | "version": "2.3.0", |
| 259 | 693 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", |
@@ -373,15 +807,6 @@
| 373 | 807 | "node": ">= 8" |
| 374 | 808 | } |
| 375 | 809 | }, |
| 376 | − "node_modules/css-line-break": { | |
| 377 | − "version": "2.1.0", | |
| 378 | − "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", | |
| 379 | − "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", | |
| 380 | − "license": "MIT", | |
| 381 | − "dependencies": { | |
| 382 | − "utrie": "^1.0.2" | |
| 383 | − } | |
| 384 | − }, | |
| 385 | 810 | "node_modules/css-selector-tokenizer": { |
| 386 | 811 | "version": "0.8.0", |
| 387 | 812 | "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", |
@@ -456,6 +881,48 @@
| 456 | 881 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", |
| 457 | 882 | "license": "MIT" |
| 458 | 883 | }, |
| 884 | + "node_modules/esbuild": { | |
| 885 | + "version": "0.28.1", | |
| 886 | + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", | |
| 887 | + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", | |
| 888 | + "dev": true, | |
| 889 | + "hasInstallScript": true, | |
| 890 | + "license": "MIT", | |
| 891 | + "bin": { | |
| 892 | + "esbuild": "bin/esbuild" | |
| 893 | + }, | |
| 894 | + "engines": { | |
| 895 | + "node": ">=18" | |
| 896 | + }, | |
| 897 | + "optionalDependencies": { | |
| 898 | + "@esbuild/aix-ppc64": "0.28.1", | |
| 899 | + "@esbuild/android-arm": "0.28.1", | |
| 900 | + "@esbuild/android-arm64": "0.28.1", | |
| 901 | + "@esbuild/android-x64": "0.28.1", | |
| 902 | + "@esbuild/darwin-arm64": "0.28.1", | |
| 903 | + "@esbuild/darwin-x64": "0.28.1", | |
| 904 | + "@esbuild/freebsd-arm64": "0.28.1", | |
| 905 | + "@esbuild/freebsd-x64": "0.28.1", | |
| 906 | + "@esbuild/linux-arm": "0.28.1", | |
| 907 | + "@esbuild/linux-arm64": "0.28.1", | |
| 908 | + "@esbuild/linux-ia32": "0.28.1", | |
| 909 | + "@esbuild/linux-loong64": "0.28.1", | |
| 910 | + "@esbuild/linux-mips64el": "0.28.1", | |
| 911 | + "@esbuild/linux-ppc64": "0.28.1", | |
| 912 | + "@esbuild/linux-riscv64": "0.28.1", | |
| 913 | + "@esbuild/linux-s390x": "0.28.1", | |
| 914 | + "@esbuild/linux-x64": "0.28.1", | |
| 915 | + "@esbuild/netbsd-arm64": "0.28.1", | |
| 916 | + "@esbuild/netbsd-x64": "0.28.1", | |
| 917 | + "@esbuild/openbsd-arm64": "0.28.1", | |
| 918 | + "@esbuild/openbsd-x64": "0.28.1", | |
| 919 | + "@esbuild/openharmony-arm64": "0.28.1", | |
| 920 | + "@esbuild/sunos-x64": "0.28.1", | |
| 921 | + "@esbuild/win32-arm64": "0.28.1", | |
| 922 | + "@esbuild/win32-ia32": "0.28.1", | |
| 923 | + "@esbuild/win32-x64": "0.28.1" | |
| 924 | + } | |
| 925 | + }, | |
| 459 | 926 | "node_modules/fast-glob": { |
| 460 | 927 | "version": "3.3.3", |
| 461 | 928 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", |
@@ -594,19 +1061,6 @@
| 594 | 1061 | "node": ">= 0.4" |
| 595 | 1062 | } |
| 596 | 1063 | }, |
| 597 | − "node_modules/html2canvas": { | |
| 598 | − "version": "1.4.1", | |
| 599 | − "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", | |
| 600 | − "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", | |
| 601 | − "license": "MIT", | |
| 602 | − "dependencies": { | |
| 603 | − "css-line-break": "^2.1.0", | |
| 604 | − "text-segmentation": "^1.0.3" | |
| 605 | − }, | |
| 606 | − "engines": { | |
| 607 | − "node": ">=8.0.0" | |
| 608 | − } | |
| 609 | − }, | |
| 610 | 1064 | "node_modules/htmx-ext-ws": { |
| 611 | 1065 | "version": "2.0.3", |
| 612 | 1066 | "resolved": "https://registry.npmjs.org/htmx-ext-ws/-/htmx-ext-ws-2.0.3.tgz", |
@@ -1074,15 +1528,6 @@
| 1074 | 1528 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", |
| 1075 | 1529 | "license": "MIT" |
| 1076 | 1530 | }, |
| 1077 | − "node_modules/prismjs": { | |
| 1078 | − "version": "1.30.0", | |
| 1079 | − "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", | |
| 1080 | − "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", | |
| 1081 | − "license": "MIT", | |
| 1082 | − "engines": { | |
| 1083 | − "node": ">=6" | |
| 1084 | − } | |
| 1085 | − }, | |
| 1086 | 1531 | "node_modules/queue-microtask": { |
| 1087 | 1532 | "version": "1.2.3", |
| 1088 | 1533 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", |
@@ -1386,15 +1831,6 @@
| 1386 | 1831 | "node": ">=14.0.0" |
| 1387 | 1832 | } |
| 1388 | 1833 | }, |
| 1389 | − "node_modules/text-segmentation": { | |
| 1390 | − "version": "1.0.3", | |
| 1391 | − "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", | |
| 1392 | − "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", | |
| 1393 | − "license": "MIT", | |
| 1394 | − "dependencies": { | |
| 1395 | − "utrie": "^1.0.2" | |
| 1396 | − } | |
| 1397 | − }, | |
| 1398 | 1834 | "node_modules/thenify": { |
| 1399 | 1835 | "version": "3.3.1", |
| 1400 | 1836 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", |
@@ -1440,15 +1876,6 @@
| 1440 | 1876 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", |
| 1441 | 1877 | "license": "MIT" |
| 1442 | 1878 | }, |
| 1443 | − "node_modules/utrie": { | |
| 1444 | − "version": "1.0.2", | |
| 1445 | − "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", | |
| 1446 | − "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", | |
| 1447 | − "license": "MIT", | |
| 1448 | − "dependencies": { | |
| 1449 | − "base64-arraybuffer": "^1.0.2" | |
| 1450 | − } | |
| 1451 | − }, | |
| 1452 | 1879 | "node_modules/which": { |
| 1453 | 1880 | "version": "2.0.2", |
| 1454 | 1881 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", |
modified
assets/package.json
+3
−0
@@ -9,5 +9,8 @@
| 9 | 9 | "htmx-ext-ws": "^2.0.3", |
| 10 | 10 | "htmx.org": "^2.0.4", |
| 11 | 11 | "tailwindcss": "^3.4.17" |
| 12 | + }, | |
| 13 | + "devDependencies": { | |
| 14 | + "esbuild": "^0.28.1" | |
| 12 | 15 | } |
| 13 | 16 | } |
Parents: f5b246f