From 93ee2a943edf9a7ebca0b6eb941ee43fb19e70b0 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sat, 24 Oct 2026 22:37:39 +0200
Subject: [PATCH 01/40] Port to astro
---
.gitignore | 3 +
astro.config.mjs | 6 +
package-lock.json | 3657 +++++++++++++++++++++++++
package.json | 13 +
logo.png => public/logo.png | Bin
src/components/Prompt.astro | 1 +
src/components/Terminal.astro | 110 +
src/layouts/Layout.astro | 37 +
coc-en.html => src/pages/coc-en.astro | 27 +-
coc.html => src/pages/coc.astro | 27 +-
en.html => src/pages/en.astro | 30 +-
index.html => src/pages/index.astro | 138 +-
style.css => src/styles/style.css | 0
13 files changed, 3869 insertions(+), 180 deletions(-)
create mode 100644 .gitignore
create mode 100644 astro.config.mjs
create mode 100644 package-lock.json
create mode 100644 package.json
rename logo.png => public/logo.png (100%)
create mode 100644 src/components/Prompt.astro
create mode 100644 src/components/Terminal.astro
create mode 100644 src/layouts/Layout.astro
rename coc-en.html => src/pages/coc-en.astro (78%)
rename coc.html => src/pages/coc.astro (80%)
rename en.html => src/pages/en.astro (86%)
rename index.html => src/pages/index.astro (56%)
rename style.css => src/styles/style.css (100%)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ddce69b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+dist/
+.astro/
diff --git a/astro.config.mjs b/astro.config.mjs
new file mode 100644
index 0000000..37a0a32
--- /dev/null
+++ b/astro.config.mjs
@@ -0,0 +1,6 @@
+import { defineConfig } from 'astro/config';
+
+export default defineConfig({
+ build: { format: 'file' },
+ compressHTML: false,
+});
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..f6ce6bb
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3657 @@
+{
+ "name": "kik-website",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "kik-website",
+ "dependencies": {
+ "astro": "^7.4.2"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.5.2.tgz",
+ "integrity": "sha512-lEn76+0JcMQ5RDXU0wSMWJg2ZppiZvSULpghC29cfv4o9bhvWFDbQjsCtvjjXN9iVLFQ7fL3wTR2L2UU13mP8g==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@astrojs/compiler-binding-android-arm64": "0.5.2",
+ "@astrojs/compiler-binding-darwin-arm64": "0.5.2",
+ "@astrojs/compiler-binding-darwin-x64": "0.5.2",
+ "@astrojs/compiler-binding-linux-arm64-gnu": "0.5.2",
+ "@astrojs/compiler-binding-linux-arm64-musl": "0.5.2",
+ "@astrojs/compiler-binding-linux-x64-gnu": "0.5.2",
+ "@astrojs/compiler-binding-linux-x64-musl": "0.5.2",
+ "@astrojs/compiler-binding-wasm32-wasi": "0.5.2",
+ "@astrojs/compiler-binding-win32-arm64-msvc": "0.5.2",
+ "@astrojs/compiler-binding-win32-x64-msvc": "0.5.2"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-android-arm64": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-android-arm64/-/compiler-binding-android-arm64-0.5.2.tgz",
+ "integrity": "sha512-kckIxon6Rm/Bxzh9mGPYpRRqUbToUQoHptCmpMmE+Yt0Xumq8CqrKUidyYhrBsrHVO7bxuRzzWUUqvpf+iYceQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-darwin-arm64": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.5.2.tgz",
+ "integrity": "sha512-1ZG5Ar3dD8HtodX9XH1mRmE0qBXZlvjYXSFfpgFwocqfWnvhFuqtGUNseL8wgfImiRMztIjpQqlogQFQQtgiag==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-darwin-x64": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.5.2.tgz",
+ "integrity": "sha512-+kl35S7hiHJ2cb7eujwEsPFYYuSgE11uEE2Z20lAJ+undpgulMcW+weQqFPOSSZccEKHOiLIY+kQHkb4e4092w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.5.2.tgz",
+ "integrity": "sha512-BqlR0EHNQLPLwgL9+xogjsAc7zGf0cHho2CPdhv0P1yqbVMwGVaGAqrANP6VYAXCqSC43AF4Czcxc2n+oqdesg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-linux-arm64-musl": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.5.2.tgz",
+ "integrity": "sha512-GRGyby3AZWw5d6JQzidyxPyvGgHWsSusrpgKyFVpDTKctABF7L3Pd5V1cRJbV36/rcu+Eh292/wL7pF7MkmGkQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-linux-x64-gnu": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.5.2.tgz",
+ "integrity": "sha512-9XAqGTMQAtIslMsjK3xdyY6OI9d59OZqcLBB6pvD/DcoR0daYswfrKx2azdDERDY4AqAnWPC7odVM1BmxYv3Vw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-linux-x64-musl": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.5.2.tgz",
+ "integrity": "sha512-jOViewGeTh9bSfS8vK72ECxoy2yvmA+Pd/ZcEvBI5c7+7IcfHwZ5qA4L9fRYuOhSrAifvQ2dV4vm1XAtloaWBw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-wasm32-wasi": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.5.2.tgz",
+ "integrity": "sha512-Z7p64doar1uvR5C9Xs6j1CV9lGlPVQX7OQ2aAtZ/xKC5aGS6GB13nyc2UfQXTQLvZrvVwsyaflTQy6ziY5Bekw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.11.3",
+ "@emnapi/runtime": "1.11.3",
+ "@napi-rs/wasm-runtime": "^1.2.5"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.5.2.tgz",
+ "integrity": "sha512-Tr13bh+ahTWsjXjzctK7pFpWV+dUU4FtBfETlR7gO+ueex0F+RDch7eRr0YfKysaRhk9tWm14lsCJ5uWyFPNHQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-binding-win32-x64-msvc": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.5.2.tgz",
+ "integrity": "sha512-SfKkI+jOQYLh6wojPvVPV0lFfQnxisweN9B+qCzRvZp7DHAuGif8Y0WcC5PUgN4jb8VKy57LggQDtggR46Du1g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/compiler-rs": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.5.2.tgz",
+ "integrity": "sha512-IvwYLB8t1M86rKO4oPdBi9GP4gzXcgrVlNgocjwos1jeeUuEIV8d9Crn1PvYD/5IKteWOxpIHomf7e8iYlkE+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/compiler-binding": "0.5.2"
+ },
+ "engines": {
+ "node": ">=22.12.0"
+ }
+ },
+ "node_modules/@astrojs/internal-helpers": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.13.0.tgz",
+ "integrity": "sha512-20jxQqnSmpskcGyad7N5l6Xf1gz0UCa6lNde44bEBdaXGpncEYfAZJ142r2ZgzBaG4dUyzGmhqZWv1INU2eiHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.5",
+ "@types/mdast": "^4.0.4",
+ "picomatch": "^4.0.7",
+ "retext-smartypants": "^6.2.0",
+ "shiki": "^4.5.0",
+ "smol-toml": "^1.9.1",
+ "unified": "^11.0.5",
+ "yaml": "^2.9.1"
+ }
+ },
+ "node_modules/@astrojs/markdown-satteri": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.5.tgz",
+ "integrity": "sha512-0IeGdoFbv0f+442KJhYS44Wg8F3MuHmRsxIEYuFyqkjRubc6dPBFZ7azor5t4AeXLQoT5A5h9HyViKpd70Dl9w==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/internal-helpers": "0.13.0",
+ "@astrojs/prism": "4.1.1",
+ "github-slugger": "^2.0.0",
+ "satteri": "^0.10.5"
+ }
+ },
+ "node_modules/@astrojs/prism": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.1.tgz",
+ "integrity": "sha512-sXlAXJX6t4QfuLg+CuCDzpg7NoxWcyb4paFprgtFppLeisCBmh935h+tJ5CWXfsXEoW2IDy/ihbRMtiu28Chjw==",
+ "license": "MIT",
+ "dependencies": {
+ "prismjs": "^1.30.0"
+ },
+ "engines": {
+ "node": ">=22.23.4"
+ }
+ },
+ "node_modules/@astrojs/telemetry": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.1.tgz",
+ "integrity": "sha512-SMkvMsGOpM0FMAoT5pzhgI3LZC0JSPWf7Evwop+fZ3N6UkusPM7lI+sOJjMNI5OJrVoiei1/AGo1cY7sikTc5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ci-info": "^4.4.0",
+ "dset": "^3.1.4",
+ "is-docker": "^4.0.0",
+ "package-manager-detector": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=22.23.4"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.11.tgz",
+ "integrity": "sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.11.tgz",
+ "integrity": "sha512-OZ6+oaK7GMyg3IfCpj8JOmn8n+w2rJbDT0LLfVDTLb1ZFeKDh3AiNELgCMUw175IJHSkLl74hG0M0VLsvx+gag==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.11"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.11",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.11.tgz",
+ "integrity": "sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.11",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bruits/satteri-darwin-arm64": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.10.5.tgz",
+ "integrity": "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@bruits/satteri-darwin-x64": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.10.5.tgz",
+ "integrity": "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@bruits/satteri-linux-arm64-gnu": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz",
+ "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@bruits/satteri-linux-arm64-musl": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz",
+ "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@bruits/satteri-linux-x64-gnu": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz",
+ "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@bruits/satteri-linux-x64-musl": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz",
+ "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@bruits/satteri-wasm32-wasi": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.10.5.tgz",
+ "integrity": "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.11.1",
+ "@emnapi/runtime": "1.11.1",
+ "@napi-rs/wasm-runtime": "^1.2.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
+ "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.2",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
+ "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@bruits/satteri-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
+ "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@bruits/satteri-win32-arm64-msvc": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.10.5.tgz",
+ "integrity": "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@bruits/satteri-win32-x64-msvc": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.10.5.tgz",
+ "integrity": "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@capsizecss/unpack": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz",
+ "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@clack/core": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz",
+ "integrity": "sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-wrap-ansi": "^0.2.0",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 20.12.0"
+ }
+ },
+ "node_modules/@clack/prompts": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.8.1.tgz",
+ "integrity": "sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@clack/core": "1.5.1",
+ "fast-string-width": "^3.0.2",
+ "fast-wrap-ansi": "^0.2.0",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 20.12.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz",
+ "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.3",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz",
+ "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz",
+ "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz",
+ "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-freebsd-wasm32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz",
+ "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.5"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz",
+ "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz",
+ "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz",
+ "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz",
+ "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz",
+ "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz",
+ "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz",
+ "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz",
+ "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz",
+ "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz",
+ "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz",
+ "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz",
+ "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz",
+ "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz",
+ "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz",
+ "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz",
+ "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz",
+ "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz",
+ "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz",
+ "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==",
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.11.3"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-webcontainers-wasm32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz",
+ "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.5"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz",
+ "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz",
+ "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz",
+ "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
+ "license": "MIT"
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz",
+ "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.3"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
+ }
+ },
+ "node_modules/@oslojs/encoding": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
+ "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
+ "license": "MIT"
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.155.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz",
+ "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/oxc-project"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm-eabi": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz",
+ "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz",
+ "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz",
+ "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz",
+ "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz",
+ "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz",
+ "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz",
+ "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz",
+ "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz",
+ "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz",
+ "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz",
+ "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz",
+ "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz",
+ "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz",
+ "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz",
+ "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "license": "MIT"
+ },
+ "node_modules/@shikijs/core": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.5.0.tgz",
+ "integrity": "sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/primitive": "4.5.0",
+ "@shikijs/types": "4.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.5",
+ "hast-util-to-html": "^9.0.5"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.5.0.tgz",
+ "integrity": "sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^4.3.6"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.5.0.tgz",
+ "integrity": "sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.5.0.tgz",
+ "integrity": "sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.5.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/primitive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.5.0.tgz",
+ "integrity": "sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.5.0.tgz",
+ "integrity": "sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "4.5.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.5.0.tgz",
+ "integrity": "sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.1.0.tgz",
+ "integrity": "sha512-cVBuhDQjBZaNMTwBquYfPydrUP+E3hE6oYGasx8h6ZrODIM7/r+gxLDXdd66oszbrggZHEntdE6j+5gYIVyMWQ==",
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz",
+ "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
+ "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/nlcst": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz",
+ "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz",
+ "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
+ "license": "ISC"
+ },
+ "node_modules/am-i-vibing": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.5.0.tgz",
+ "integrity": "sha512-KLcsDhqf1XRrJmJr+9I/C0EX2K+sGrAGZFgkmd84c8TJO9zJBu+/kFInjazu1KfJWFhWDKdRWkpBzEs7s35DVA==",
+ "license": "MIT",
+ "dependencies": {
+ "process-ancestry": "^0.1.0"
+ },
+ "bin": {
+ "am-i-vibing": "dist/cli.mjs"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/anymatch/node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/astro": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.2.tgz",
+ "integrity": "sha512-FAH4cdDlFaVnQGjazLTEIC5vJqGlo5XANc1wIbzQHIqAjJTll/RWTUs+SPNW1JdezG4YGxMZllaE5A41T2kzhA==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/compiler-rs": "^0.5.1",
+ "@astrojs/internal-helpers": "0.13.0",
+ "@astrojs/markdown-satteri": "0.4.5",
+ "@astrojs/telemetry": "3.4.1",
+ "@capsizecss/unpack": "^4.0.1",
+ "@clack/prompts": "^1.8.1",
+ "@oslojs/encoding": "^1.1.0",
+ "am-i-vibing": "^0.5.0",
+ "aria-query": "^5.3.2",
+ "axobject-query": "^4.1.0",
+ "ci-info": "^4.4.0",
+ "clsx": "^2.1.1",
+ "common-ancestor-path": "^2.0.0",
+ "cookie": "^2.0.1",
+ "devalue": "^6.0.2",
+ "diff": "^9.0.0",
+ "dset": "^3.1.4",
+ "es-module-lexer": "^3.0.3",
+ "flattie": "^1.1.1",
+ "fontace": "~0.4.1",
+ "get-tsconfig": "5.0.0-beta.6",
+ "github-slugger": "^2.0.0",
+ "html-escaper": "3.0.3",
+ "http-cache-semantics": "^4.3.0",
+ "jsonc-parser": "^3.3.1",
+ "magic-string": "^1.4.3",
+ "magicast": "^0.5.5",
+ "mrmime": "^2.0.1",
+ "neotraverse": "^1.0.1",
+ "obug": "^3.0.0",
+ "p-limit": "^7.3.3",
+ "p-queue": "^9.3.5",
+ "package-manager-detector": "^1.9.0",
+ "piccolore": "^0.1.3",
+ "picomatch": "^4.0.7",
+ "rolldown": "^1.2.13",
+ "shiki": "^4.5.0",
+ "smol-toml": "^1.9.1",
+ "svgo": "^4.1.0",
+ "tinyclip": "^1.0.3",
+ "tinyexec": "^1.3.1",
+ "tinyglobby": "^0.2.17",
+ "tinyps": "^0.5.0",
+ "ultrahtml": "^1.7.0",
+ "unifont": "^1.0.3",
+ "unstorage": "^1.17.5",
+ "verkit": "^0.5.0",
+ "vite": "^8.3.4",
+ "vitefu": "^1.1.3",
+ "xxhash-wasm": "^1.1.0",
+ "yargs-parser": "^22.0.0",
+ "zod": "^4.6.6"
+ },
+ "bin": {
+ "astro": "bin/astro.mjs"
+ },
+ "engines": {
+ "node": ">=22.23.4",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/astrodotbuild"
+ },
+ "optionalDependencies": {
+ "sharp": "^0.35.4"
+ },
+ "peerDependencies": {
+ "@astrojs/markdown-remark": "^7.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@astrojs/markdown-remark": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
+ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/common-ancestor-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz",
+ "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz",
+ "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cookie-es": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz",
+ "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==",
+ "license": "MIT"
+ },
+ "node_modules/crossws": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz",
+ "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==",
+ "license": "MIT",
+ "dependencies": {
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz",
+ "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^7.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "nth-check": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz",
+ "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/defu": {
+ "version": "6.1.7",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
+ "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==",
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
+ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-6.0.3.tgz",
+ "integrity": "sha512-3woMEITftG1wKeO/4d/QXH1DVKctTSZg3jNGPpjp9hNr5Hos8MCFF5McTML5ZtgKDObm2R591B0spRp2IVernA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/diff": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz",
+ "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dset": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
+ "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.4.tgz",
+ "integrity": "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA==",
+ "license": "MIT"
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
+ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
+ "license": "MIT"
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fast-string-truncated-width": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz",
+ "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==",
+ "license": "MIT"
+ },
+ "node_modules/fast-string-width": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz",
+ "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-string-truncated-width": "^3.0.2"
+ }
+ },
+ "node_modules/fast-wrap-ansi": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz",
+ "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-string-width": "^3.0.2"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/flattie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz",
+ "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fnv1a-64": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/fnv1a-64/-/fnv1a-64-0.1.2.tgz",
+ "integrity": "sha512-mJbcILTPybAR1jdOwt/lVv8N2cffeJFFP+gVbSAwLEx1ujXH27RpPd8Rokec/KX9c76UYIB6Co+H4lQzxPnJfA==",
+ "license": "MIT"
+ },
+ "node_modules/fontace": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz",
+ "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.2"
+ }
+ },
+ "node_modules/fontkitten": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz",
+ "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==",
+ "license": "MIT",
+ "dependencies": {
+ "tiny-inflate": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "5.0.0-beta.6",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.6.tgz",
+ "integrity": "sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==",
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=20.20.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/github-slugger": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
+ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
+ "license": "ISC"
+ },
+ "node_modules/h3": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz",
+ "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie-es": "^1.2.3",
+ "crossws": "^0.3.5",
+ "defu": "^6.1.6",
+ "destr": "^2.0.5",
+ "iron-webcrypto": "^1.2.1",
+ "node-mock-http": "^1.0.4",
+ "radix3": "^1.1.2",
+ "ufo": "^1.6.3",
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
+ "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==",
+ "license": "MIT"
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz",
+ "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/iron-webcrypto": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
+ "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/brc-dd"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz",
+ "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "license": "MIT"
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "11.5.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
+ "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz",
+ "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.6.0"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.5.tgz",
+ "integrity": "sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.3.tgz",
+ "integrity": "sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/neotraverse": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-1.0.1.tgz",
+ "integrity": "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/nlcst-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz",
+ "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/node-fetch-native": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
+ "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
+ "license": "MIT"
+ },
+ "node_modules/node-mock-http": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.5.tgz",
+ "integrity": "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==",
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/obug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz",
+ "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==",
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/ofetch": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz",
+ "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==",
+ "license": "MIT",
+ "dependencies": {
+ "destr": "^2.0.5",
+ "node-fetch-native": "^1.6.7",
+ "ufo": "^1.6.1"
+ }
+ },
+ "node_modules/oniguruma-parser": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz",
+ "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz",
+ "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==",
+ "license": "MIT",
+ "dependencies": {
+ "oniguruma-parser": "^0.12.2",
+ "regex": "^6.1.0",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.3.tgz",
+ "integrity": "sha512-SKgVvDU5TNIxQ4r30U75BNLC6a+6GOEjngrk/ysM5+Zu3oJuk1SC5ApzIzY/7PjCEjoVPMWJ0zho/4QUiEB7TQ==",
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-queue": {
+ "version": "9.3.5",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.5.tgz",
+ "integrity": "sha512-Lki/zhXFVmDhesBUn/yHRLW9Bte7mE7xoFHzTR8sIomV7a2z+LxYAPkGvdfidNiu4fKSfjtawixxSHcZci5QcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^5.0.4",
+ "p-timeout": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.2.tgz",
+ "integrity": "sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-manager-detector": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz",
+ "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==",
+ "license": "MIT"
+ },
+ "node_modules/piccolore": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz",
+ "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==",
+ "license": "ISC"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz",
+ "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.20",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/process-ancestry": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/process-ancestry/-/process-ancestry-0.1.0.tgz",
+ "integrity": "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz",
+ "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/radix3": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
+ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz",
+ "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz",
+ "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "license": "MIT"
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/retext-smartypants": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz",
+ "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz",
+ "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.155.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm-eabi": "1.2.15",
+ "@rolldown/binding-android-arm64": "1.2.15",
+ "@rolldown/binding-darwin-arm64": "1.2.15",
+ "@rolldown/binding-darwin-x64": "1.2.15",
+ "@rolldown/binding-freebsd-x64": "1.2.15",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.15",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.15",
+ "@rolldown/binding-linux-arm64-musl": "1.2.15",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.15",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.15",
+ "@rolldown/binding-linux-x64-gnu": "1.2.15",
+ "@rolldown/binding-linux-x64-musl": "1.2.15",
+ "@rolldown/binding-openharmony-arm64": "1.2.15",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.15",
+ "@rolldown/binding-win32-x64-msvc": "1.2.15"
+ }
+ },
+ "node_modules/satteri": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.10.5.tgz",
+ "integrity": "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.5",
+ "@types/hast": "^3.0.5",
+ "@types/mdast": "^4.0.4",
+ "@types/unist": "^3.0.3"
+ },
+ "optionalDependencies": {
+ "@bruits/satteri-darwin-arm64": "0.10.5",
+ "@bruits/satteri-darwin-x64": "0.10.5",
+ "@bruits/satteri-linux-arm64-gnu": "0.10.5",
+ "@bruits/satteri-linux-arm64-musl": "0.10.5",
+ "@bruits/satteri-linux-x64-gnu": "0.10.5",
+ "@bruits/satteri-linux-x64-musl": "0.10.5",
+ "@bruits/satteri-wasm32-wasi": "0.10.5",
+ "@bruits/satteri-win32-arm64-msvc": "0.10.5",
+ "@bruits/satteri-win32-x64-msvc": "0.10.5"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz",
+ "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz",
+ "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/colour": "^1.1.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.8.5"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.35.5",
+ "@img/sharp-darwin-x64": "0.35.5",
+ "@img/sharp-freebsd-wasm32": "0.35.5",
+ "@img/sharp-libvips-darwin-arm64": "1.3.4",
+ "@img/sharp-libvips-darwin-x64": "1.3.4",
+ "@img/sharp-libvips-linux-arm": "1.3.4",
+ "@img/sharp-libvips-linux-arm64": "1.3.4",
+ "@img/sharp-libvips-linux-ppc64": "1.3.4",
+ "@img/sharp-libvips-linux-riscv64": "1.3.4",
+ "@img/sharp-libvips-linux-s390x": "1.3.4",
+ "@img/sharp-libvips-linux-x64": "1.3.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4",
+ "@img/sharp-linux-arm": "0.35.5",
+ "@img/sharp-linux-arm64": "0.35.5",
+ "@img/sharp-linux-ppc64": "0.35.5",
+ "@img/sharp-linux-riscv64": "0.35.5",
+ "@img/sharp-linux-s390x": "0.35.5",
+ "@img/sharp-linux-x64": "0.35.5",
+ "@img/sharp-linuxmusl-arm64": "0.35.5",
+ "@img/sharp-linuxmusl-x64": "0.35.5",
+ "@img/sharp-webcontainers-wasm32": "0.35.5",
+ "@img/sharp-win32-arm64": "0.35.5",
+ "@img/sharp-win32-ia32": "0.35.5",
+ "@img/sharp-win32-x64": "0.35.5"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/shiki": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.5.0.tgz",
+ "integrity": "sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "4.5.0",
+ "@shikijs/engine-javascript": "4.5.0",
+ "@shikijs/engine-oniguruma": "4.5.0",
+ "@shikijs/langs": "4.5.0",
+ "@shikijs/themes": "4.5.0",
+ "@shikijs/types": "4.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/smol-toml": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.1.tgz",
+ "integrity": "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/cyyynthia"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/std-env": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz",
+ "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==",
+ "license": "MIT"
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/svgo": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.1.0.tgz",
+ "integrity": "sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "css-select": "^6.0.0",
+ "css-tree": "^3.0.1",
+ "css-what": "^7.0.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.1.1",
+ "sax": "1.6.1"
+ },
+ "bin": {
+ "svgo": "bin/svgo.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "license": "MIT"
+ },
+ "node_modules/tinyclip": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-1.0.3.tgz",
+ "integrity": "sha512-nTv2raKFMzGG6JJp0lpNDsRPdfFE6UHlu2rVEjXo8vkx1ZS3LW2CVXqIaLu8xZlu+6tbFs9V58Qc/Jmk/Ii7wA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^16.14.0 || >= 17.3.0"
+ }
+ },
+ "node_modules/tinyexec": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyps": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/tinyps/-/tinyps-0.5.1.tgz",
+ "integrity": "sha512-B6Ykif5HflC3AdDkS4Zst/2muYVfeXoVMy+KorqH80s/1x4vunIORpNySH681X7fjj+dFM9MDKD6/Hsccjb87Q==",
+ "license": "MIT"
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/ufo": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz",
+ "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
+ "license": "MIT"
+ },
+ "node_modules/ultrahtml": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz",
+ "integrity": "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==",
+ "license": "MIT"
+ },
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
+ },
+ "node_modules/undici": {
+ "version": "8.12.3",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.12.3.tgz",
+ "integrity": "sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22.19.0"
+ }
+ },
+ "node_modules/unified": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "bail": "^2.0.0",
+ "devlop": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unifont": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/unifont/-/unifont-1.0.3.tgz",
+ "integrity": "sha512-XGnEwj5sWdCbiBX01mWLSBncS0yMRjnLygau3IfdOlfjMacNIQvTGW4VH7pWBq+gGWArfSef/CensMLjMmIr/A==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "^3.1.0",
+ "fnv1a-64": "^0.1.2",
+ "std-env": "^4.2.0",
+ "undici": "^8.0.0"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.2.0.tgz",
+ "integrity": "sha512-fpsYs/VVoZxfGY9/j3FQpZmN8wdLJaV1Pt38AaJNZu9uKIHcFU3halCdBveEq1HGKO1OEfJY65w1zvoFV1b3qQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.1.0.tgz",
+ "integrity": "sha512-vKXxz6O38sKDj1mtx/k2cWvkkFBuYGx6uGrlzBkVeWCRF/F8sdI0j3Wbkz/5rVNRRuVc8UrgRdbCxNhmYXgP3w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unstorage": {
+ "version": "1.17.6",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.6.tgz",
+ "integrity": "sha512-gjKtcmn/KwZuJZO9o2sc0esAQnhmTw0LviDHwevTXbJMYs0dRTp8ZEEWXHU0vTpzbN3cA0yxlTeyXssMp3zDqw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^5.0.0",
+ "destr": "^2.0.5",
+ "h3": "^1.15.11",
+ "lru-cache": "^11.5.3",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.4"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6 || ^7 || ^8",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1 || ^2 || ^3",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/verkit": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.5.0.tgz",
+ "integrity": "sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz",
+ "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.7",
+ "postcss": "^8.5.30",
+ "rolldown": "~1.2.14",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.7.1 || ^0.8.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",
+ "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==",
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*",
+ "tests/projects/workspace/packages/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xxhash-wasm": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
+ "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==",
+ "license": "MIT"
+ },
+ "node_modules/yaml": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz",
+ "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "22.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
+ "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==",
+ "license": "ISC",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=23"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
+ "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.6.7",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz",
+ "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d087ca7
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "kik-website",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "astro dev",
+ "build": "astro build",
+ "preview": "astro preview"
+ },
+ "dependencies": {
+ "astro": "^7.4.2"
+ }
+}
diff --git a/logo.png b/public/logo.png
similarity index 100%
rename from logo.png
rename to public/logo.png
diff --git a/src/components/Prompt.astro b/src/components/Prompt.astro
new file mode 100644
index 0000000..c7c74bc
--- /dev/null
+++ b/src/components/Prompt.astro
@@ -0,0 +1 @@
+root@khaos-im-kiez:~#
diff --git a/src/components/Terminal.astro b/src/components/Terminal.astro
new file mode 100644
index 0000000..cb712ac
--- /dev/null
+++ b/src/components/Terminal.astro
@@ -0,0 +1,110 @@
+---
+import Prompt from './Prompt.astro';
+---
+
+
+
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
new file mode 100644
index 0000000..f366c1c
--- /dev/null
+++ b/src/layouts/Layout.astro
@@ -0,0 +1,37 @@
+---
+import '../styles/style.css';
+import Prompt from '../components/Prompt.astro';
+import Terminal from '../components/Terminal.astro';
+
+interface Props {
+ lang: 'de' | 'en';
+ title: string;
+ description?: string;
+ command: string;
+ alternate: string;
+}
+
+const { lang, title, description, command, alternate } = Astro.props;
+---
+
+
+
+
+
+{title}
+{description && }
+
+
+
+
+
+
+{command}
+
+
+
+
+
+
+
+
diff --git a/coc-en.html b/src/pages/coc-en.astro
similarity index 78%
rename from coc-en.html
rename to src/pages/coc-en.astro
index 367ec6a..611465d 100644
--- a/coc-en.html
+++ b/src/pages/coc-en.astro
@@ -1,17 +1,12 @@
-
-
-
-
-
-Code of Conduct - Khaos im Kiez
-
-
-
-
-
-
-
-visitor@khaos-im-kiez:~$ cat CODE_OF_CONDUCT.en
+---
+import Layout from '../layouts/Layout.astro';
+---
+
-
-
+
diff --git a/coc.html b/src/pages/coc.astro
similarity index 80%
rename from coc.html
rename to src/pages/coc.astro
index ab14dfd..5a81481 100644
--- a/coc.html
+++ b/src/pages/coc.astro
@@ -1,17 +1,12 @@
-
-
-
-
-
-Code of Conduct - Khaos im Kiez
-
-
-
-
-
-
-
-visitor@khaos-im-kiez:~$ cat CODE_OF_CONDUCT
+---
+import Layout from '../layouts/Layout.astro';
+---
+
-
-
+
diff --git a/en.html b/src/pages/en.astro
similarity index 86%
rename from en.html
rename to src/pages/en.astro
index 3f866a6..02fa73d 100644
--- a/en.html
+++ b/src/pages/en.astro
@@ -1,18 +1,13 @@
-
-
-
-
-
-Khaos im Kiez
-
-
-
-
-
-
-
-
-visitor@khaos-im-kiez:~$ cat README.en
+---
+import Layout from '../layouts/Layout.astro';
+---
+
@@ -98,9 +93,6 @@
-
-
-
+
diff --git a/index.html b/src/pages/index.astro
similarity index 56%
rename from index.html
rename to src/pages/index.astro
index 1aeb855..8eea88e 100644
--- a/index.html
+++ b/src/pages/index.astro
@@ -1,18 +1,13 @@
-
-
-
-
-
-Khaos im Kiez
-
-
-
-
-
-
-
-
-visitor@khaos-im-kiez:~$ cat README
+---
+import Layout from '../layouts/Layout.astro';
+---
+
- visitor@khaos-im-kiez:~$
-
-
-
-
+
diff --git a/style.css b/src/styles/style.css
similarity index 100%
rename from style.css
rename to src/styles/style.css
From a36da4af6f39f6845dacd193bab957cc141b3737 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sat, 24 Oct 2026 22:37:54 +0200
Subject: [PATCH 02/40] Add root ssh key
---
public/root_key | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 public/root_key
diff --git a/public/root_key b/public/root_key
new file mode 100644
index 0000000..d9952ae
--- /dev/null
+++ b/public/root_key
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACCQ8HhB/G4WQB1WgHnYU1Q29o/6DBJ975ve8QsAsPSwvQAAAKjlKiEr5Soh
+KwAAAAtzc2gtZWQyNTUxOQAAACCQ8HhB/G4WQB1WgHnYU1Q29o/6DBJ975ve8QsAsPSwvQ
+AAAEA8lgTuE+19YARukm7eq2FZ1PvUbE+owyOAEO5IbCnvnJDweEH8bhZAHVaAedhTVDb2
+j/oMEn3vm97xCwCw9LC9AAAAIXJvb3RAbm93aGVyZS53aXJzLmluZyBjeWd3aW4tMjIyMg
+ECAwQ=
+-----END OPENSSH PRIVATE KEY-----
From 83e25907a8c522d7d86264ab11828a88f91a2757 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 00:58:38 +0200
Subject: [PATCH 03/40] Connect the bottom prompt to the shared SSH server
The bottom prompt is now a real text input. Sending the first command
lazy-loads an xterm.js terminal that continues right below it and
connects to wss://web.nowhere.wirs.ing with a minimal in-browser SSH
client (curve25519, strict kex, pinned ed25519 host key,
chacha20-poly1305, re-keying) using public/root_key.
The page is the scrollback: lines scrolling off the window-sized
terminal screen become page text, the screen grows with the lines in
use, and the wheel scrolls the page except in full-screen apps.
Typing anywhere on the page goes to the prompt, later to the terminal.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
package-lock.json | 59 ++++++++
package.json | 5 +
src/components/Prompt.astro | 2 +-
src/components/Terminal.astro | 126 ++++------------
src/scripts/ssh.ts | 276 ++++++++++++++++++++++++++++++++++
src/scripts/terminal.ts | 129 ++++++++++++++++
src/styles/style.css | 16 +-
7 files changed, 511 insertions(+), 102 deletions(-)
create mode 100644 src/scripts/ssh.ts
create mode 100644 src/scripts/terminal.ts
diff --git a/package-lock.json b/package-lock.json
index f6ce6bb..332eeb7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,6 +6,11 @@
"": {
"name": "kik-website",
"dependencies": {
+ "@noble/ciphers": "^2.4.0",
+ "@noble/curves": "^2.4.0",
+ "@noble/hashes": "^2.4.0",
+ "@xterm/addon-fit": "^0.11.0",
+ "@xterm/xterm": "^6.0.0",
"astro": "^7.4.2"
}
},
@@ -1057,6 +1062,45 @@
"@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"
}
},
+ "node_modules/@noble/ciphers": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.4.0.tgz",
+ "integrity": "sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/curves": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.4.0.tgz",
+ "integrity": "sha512-P4/62zrgfH33CneE3Dn4WhJVA22YUU0eR51wKIan4NVRvwsA0YnPTwWGpNbpuacSujmSFLvyzpyuR30+fbq2Ew==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "2.4.0"
+ },
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz",
+ "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/@oslojs/encoding": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
@@ -1482,6 +1526,21 @@
"integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
"license": "ISC"
},
+ "node_modules/@xterm/addon-fit": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz",
+ "integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==",
+ "license": "MIT"
+ },
+ "node_modules/@xterm/xterm": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz",
+ "integrity": "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==",
+ "license": "MIT",
+ "workspaces": [
+ "addons/*"
+ ]
+ },
"node_modules/am-i-vibing": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.5.0.tgz",
diff --git a/package.json b/package.json
index d087ca7..83e6eb8 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,11 @@
"preview": "astro preview"
},
"dependencies": {
+ "@noble/ciphers": "^2.4.0",
+ "@noble/curves": "^2.4.0",
+ "@noble/hashes": "^2.4.0",
+ "@xterm/addon-fit": "^0.11.0",
+ "@xterm/xterm": "^6.0.0",
"astro": "^7.4.2"
}
}
diff --git a/src/components/Prompt.astro b/src/components/Prompt.astro
index c7c74bc..6081309 100644
--- a/src/components/Prompt.astro
+++ b/src/components/Prompt.astro
@@ -1 +1 @@
-root@khaos-im-kiez:~#
+root@khaos-im-kiez:~#
diff --git a/src/components/Terminal.astro b/src/components/Terminal.astro
index cb712ac..eed8acb 100644
--- a/src/components/Terminal.astro
+++ b/src/components/Terminal.astro
@@ -1,110 +1,36 @@
---
import Prompt from './Prompt.astro';
---
-
+
diff --git a/src/scripts/ssh.ts b/src/scripts/ssh.ts
new file mode 100644
index 0000000..e20e5c1
--- /dev/null
+++ b/src/scripts/ssh.ts
@@ -0,0 +1,276 @@
+// Minimal SSH client for one interactive shell over a websockify bridge (raw SSH bytes in binary frames).
+// Supports exactly: curve25519-sha256 with strict kex, ssh-ed25519 host and user keys,
+// chacha20-poly1305@openssh.com, one session channel with a pty, and server-initiated re-keying.
+import { ed25519, x25519 } from '@noble/curves/ed25519.js';
+import { sha256 } from '@noble/hashes/sha2.js';
+import { chacha20orig } from '@noble/ciphers/chacha.js';
+import { poly1305 } from '@noble/ciphers/_poly1305.js';
+import { concatBytes as concat, equalBytes, randomBytes } from '@noble/ciphers/utils.js';
+
+export interface Options {
+ socket: WebSocket;
+ user: string;
+ privateKey: string; // unencrypted ed25519 key in openssh-key-v1 format
+ hostKey: string; // expected host key fingerprint, "SHA256:..."
+ term: string;
+ cols: number;
+ rows: number;
+ onData: (data: Uint8Array) => void;
+ onClose: (error?: Error) => void;
+}
+
+export interface Session {
+ write(data: string | Uint8Array): void;
+ resize(cols: number, rows: number): void;
+}
+
+const CIPHER = 'chacha20-poly1305@openssh.com';
+const WINDOW = 1 << 16;
+const MAX_PACKET = 1 << 15;
+
+const enc = new TextEncoder();
+const dec = new TextDecoder();
+
+const u32 = (n: number) => Uint8Array.of(n >>> 24, n >>> 16, n >>> 8, n);
+
+/** SSH wire encoding: number → uint32, boolean → byte, string or bytes → length-prefixed string. */
+function pack(...values: (number | boolean | string | Uint8Array)[]): Uint8Array {
+ return concat(...values.map((v) => {
+ if (typeof v === 'number') return u32(v);
+ if (typeof v === 'boolean') return Uint8Array.of(+v);
+ const bytes = typeof v === 'string' ? enc.encode(v) : v;
+ return concat(u32(bytes.length), bytes);
+ }));
+}
+
+const msg = (type: number, ...values: Parameters) => concat(Uint8Array.of(type), pack(...values));
+
+function reader(bytes: Uint8Array, offset = 0) {
+ const r = {
+ u8: () => bytes[offset++],
+ u32: () => new DataView(bytes.buffer, bytes.byteOffset).getUint32((offset += 4) - 4),
+ bytes: () => { const n = r.u32(); return bytes.subarray(offset, (offset += n)); },
+ str: () => dec.decode(r.bytes()),
+ };
+ return r;
+}
+
+/** Unsigned big-endian integer → SSH mpint. */
+function mpint(bytes: Uint8Array) {
+ const n = bytes.subarray(bytes.findIndex((b) => b !== 0));
+ return pack(n[0] & 0x80 ? concat(Uint8Array.of(0), n) : n);
+}
+
+function parsePrivateKey(text: string) {
+ const r = reader(Uint8Array.from(atob(text.replace(/-----[^-]+-----|\s/g, '')), (c) => c.charCodeAt(0)), 15); // skip "openssh-key-v1\0"
+ if (r.str() !== 'none') throw new Error('encrypted private keys are not supported');
+ r.str(); r.bytes(); r.u32(); // kdf name, kdf options, number of keys
+ const publicKey = r.bytes();
+ const secret = reader(r.bytes(), 8); // skip check ints
+ secret.str(); secret.bytes(); // key type, public key
+ return { publicKey, seed: secret.bytes().subarray(0, 32) };
+}
+
+/** chacha20-poly1305@openssh.com. Sequence numbers restart at 0 after every NEWKEYS because of strict kex. */
+function chachaPoly(key: Uint8Array) {
+ const main = key.subarray(0, 32);
+ const header = key.subarray(32);
+ let seq = 0;
+ const nonce = () => concat(u32(0), u32(seq));
+ const mac = (n: Uint8Array, data: Uint8Array) => poly1305(data, chacha20orig(main, n, new Uint8Array(32)));
+ return {
+ length: (head: Uint8Array) => reader(chacha20orig(header, nonce(), head)).u32(),
+ seal(packet: Uint8Array) {
+ const n = nonce();
+ seq++;
+ const sealed = concat(chacha20orig(header, n, packet.subarray(0, 4)), chacha20orig(main, n, packet.subarray(4), undefined, 1));
+ return concat(sealed, mac(n, sealed));
+ },
+ open(packet: Uint8Array) {
+ const n = nonce();
+ seq++;
+ const sealed = packet.subarray(0, -16);
+ if (!equalBytes(mac(n, sealed), packet.subarray(-16))) throw new Error('bad packet MAC');
+ return chacha20orig(main, n, sealed.subarray(4), undefined, 1);
+ },
+ };
+}
+
+export function connect(o: Options): Session {
+ const { socket } = o;
+ let buffer = new Uint8Array(0);
+ let wake = () => {};
+ let closed = false;
+ socket.binaryType = 'arraybuffer';
+ socket.onmessage = (e) => { buffer = concat(buffer, new Uint8Array(e.data)); wake(); };
+ socket.onclose = () => { closed = true; wake(); };
+
+ async function read(n: number) {
+ while (buffer.length < n) {
+ if (closed) throw new Error('connection closed');
+ await new Promise((resolve) => (wake = resolve));
+ }
+ const bytes = buffer.subarray(0, n);
+ buffer = buffer.subarray(n);
+ return bytes;
+ }
+
+ let tx: ReturnType | undefined;
+ let rx: ReturnType | undefined;
+ let held: Uint8Array[] | undefined; // connection-layer messages held back during a key exchange
+
+ function send(payload: Uint8Array) {
+ if (socket.readyState !== WebSocket.OPEN) return; // the session has ended
+ if (held && payload[0] >= 50) return void held.push(payload);
+ let padding = 8 - ((payload.length + (tx ? 1 : 5)) % 8); // chacha20-poly1305 excludes the length field
+ if (padding < 4) padding += 8;
+ const packet = concat(u32(payload.length + padding + 1), Uint8Array.of(padding), payload, new Uint8Array(padding));
+ socket.send(tx ? tx.seal(packet) : packet);
+ }
+
+ async function readPacket() {
+ const head = await read(4);
+ const packet = concat(head, await read(rx ? rx.length(head) + 16 : reader(head).u32()));
+ const plain = rx ? rx.open(packet) : packet.subarray(4);
+ return plain.subarray(1, plain.length - plain[0]);
+ }
+
+ /** Next packet, after handling the messages that may arrive at any time once the initial key exchange is done. */
+ async function receive(): Promise {
+ for (;;) {
+ const p = await readPacket();
+ if (!rx) return p; // strict kex: nothing else is allowed during the initial key exchange
+ const r = reader(p, 1);
+ switch (p[0]) {
+ case 1: r.u32(); throw new Error(`disconnected: ${r.str()}`);
+ case 80: r.str(); if (r.u8()) send(Uint8Array.of(82)); break; // global request: reply failure
+ case 2: case 3: case 4: case 53: break; // ignore, unimplemented, debug, auth banner
+ default: return p;
+ }
+ }
+ }
+
+ async function expect(type: number) {
+ const p = await receive();
+ if (p[0] !== type) throw new Error(`expected message ${type}, got ${p[0]}`);
+ return p;
+ }
+
+ let channel: number | undefined;
+ let remoteWindow = 0;
+ let remoteMaxPacket = 0;
+ let pending = new Uint8Array(0);
+
+ function flush() {
+ while (pending.length && remoteWindow) {
+ const n = Math.min(pending.length, remoteWindow, remoteMaxPacket);
+ send(msg(94, channel!, pending.subarray(0, n)));
+ pending = pending.subarray(n);
+ remoteWindow -= n;
+ }
+ }
+
+ async function run() {
+ let line;
+ do {
+ line = '';
+ while (!line.endsWith('\n')) line += String.fromCharCode((await read(1))[0]);
+ } while (!line.startsWith('SSH-'));
+ const serverVersion = line.trimEnd();
+ const clientVersion = 'SSH-2.0-web';
+ socket.send(enc.encode(`${clientVersion}\r\n`));
+
+ let sessionId: Uint8Array | undefined;
+ /** The initial key exchange, or a re-key started by the server's KEXINIT. */
+ async function kex(serverKexinit?: Uint8Array) {
+ held = [];
+ const clientKexinit = concat(Uint8Array.of(20), randomBytes(16), pack(
+ 'curve25519-sha256,kex-strict-c-v00@openssh.com', 'ssh-ed25519',
+ CIPHER, CIPHER, '', '', 'none', 'none', '', '', false, 0,
+ ));
+ send(clientKexinit);
+ serverKexinit ??= await expect(20);
+ if (!sessionId && !reader(serverKexinit, 17).str().split(',').includes('kex-strict-s-v00@openssh.com')) throw new Error('server lacks strict kex');
+
+ const ephemeral = x25519.keygen();
+ send(msg(30, ephemeral.publicKey));
+ const reply = reader(await expect(31), 1);
+ const hostKey = reply.bytes();
+ const serverPublic = reply.bytes();
+ const signature = reply.bytes();
+ const fingerprint = `SHA256:${btoa(String.fromCharCode(...sha256(hostKey))).replace(/=+$/, '')}`;
+ if (fingerprint !== o.hostKey) throw new Error(`unexpected host key ${fingerprint}`);
+ const K = mpint(x25519.getSharedSecret(ephemeral.secretKey, serverPublic));
+ const H = sha256(concat(pack(clientVersion, serverVersion, clientKexinit, serverKexinit, hostKey, ephemeral.publicKey, serverPublic), K));
+ if (!ed25519.verify(signature.subarray(-64), H, hostKey.subarray(-32))) throw new Error('bad host key signature');
+
+ const id = (sessionId ??= H);
+ const key = (letter: string) => {
+ const k1 = sha256(concat(K, H, enc.encode(letter), id));
+ return concat(k1, sha256(concat(K, H, k1)));
+ };
+ send(Uint8Array.of(21));
+ tx = chachaPoly(key('C'));
+ await expect(21);
+ rx = chachaPoly(key('D'));
+ const messages = held;
+ held = undefined;
+ messages.forEach(send);
+ }
+ await kex();
+
+ send(msg(5, 'ssh-userauth'));
+ await expect(6);
+ const { publicKey, seed } = parsePrivateKey(o.privateKey);
+ const auth = msg(50, o.user, 'ssh-connection', 'publickey', true, 'ssh-ed25519', publicKey);
+ send(concat(auth, pack(pack('ssh-ed25519', ed25519.sign(concat(pack(sessionId!), auth), seed)))));
+ if ((await receive())[0] !== 52) throw new Error('authentication failed');
+
+ send(msg(90, 'session', 0, WINDOW, MAX_PACKET));
+ const confirmation = reader(await expect(91), 5);
+ channel = confirmation.u32();
+ remoteWindow = confirmation.u32();
+ remoteMaxPacket = confirmation.u32();
+ send(msg(98, channel, 'pty-req', true, o.term, o.cols, o.rows, 0, 0, '\0')); // no terminal modes, just TTY_OP_END
+ send(msg(98, channel, 'shell', true));
+ flush();
+
+ let window = WINDOW;
+ for (;;) {
+ const p = await receive();
+ const r = reader(p, 5); // everything from here on is for our only channel
+ switch (p[0]) {
+ case 20: await kex(p); break;
+ case 93: remoteWindow += r.u32(); flush(); break;
+ case 95: r.u32(); // extended data (stderr): skip the type code
+ // falls through
+ case 94: {
+ const data = r.bytes();
+ o.onData(data);
+ if ((window -= data.length) <= WINDOW / 2) {
+ send(msg(93, channel, WINDOW - window));
+ window = WINDOW;
+ }
+ break;
+ }
+ case 98: r.str(); if (r.u8()) send(msg(100, channel)); break; // exit-status, keepalive, ...
+ case 100: throw new Error('pty or shell request failed');
+ case 97: send(msg(97, channel)); return;
+ }
+ }
+ }
+
+ run().catch((e) => e).then((error) => { socket.close(); o.onClose(error); });
+
+ return {
+ write(data) {
+ pending = concat(pending, typeof data === 'string' ? enc.encode(data) : data);
+ flush();
+ },
+ resize(cols, rows) {
+ o.cols = cols;
+ o.rows = rows;
+ if (channel !== undefined) send(msg(98, channel, 'window-change', false, cols, rows, 0, 0));
+ },
+ };
+}
diff --git a/src/scripts/terminal.ts b/src/scripts/terminal.ts
new file mode 100644
index 0000000..980f95b
--- /dev/null
+++ b/src/scripts/terminal.ts
@@ -0,0 +1,129 @@
+// The real terminal: xterm.js connected to the shared shell server over SSH. Loaded only once the first command is sent.
+import { Terminal, type IMarker } from '@xterm/xterm';
+import { FitAddon } from '@xterm/addon-fit';
+import css from '@xterm/xterm/css/xterm.css?inline';
+import { connect } from './ssh';
+
+const SERVER = 'wss://web.nowhere.wirs.ing';
+const HOST_KEY = 'SHA256:aLNZKHCfhvbGYnjghKsOLPrOWPVWwCsIPCuTb5f9J6A';
+const SCROLLBACK = 10000;
+
+/** Continues the page's `prompt` with a terminal in which `command` was just entered, and returns that terminal. */
+export async function start(prompt: HTMLElement, command: string) {
+ const privateKey = await (await fetch('root_key')).text();
+ document.head.append(Object.assign(document.createElement('style'), { textContent: css }));
+ // The page is the scrollback: lines that scroll off the terminal's screen continue as page text above it,
+ // and the screen only grows to the rows in use, up to the window height.
+ const history = document.createElement('div');
+ history.className = 'history';
+ const screen = document.createElement('div');
+ screen.className = 'screen';
+ const element = screen.appendChild(document.createElement('div'));
+ prompt.after(history, screen);
+
+ const { color, fontFamily, fontSize } = getComputedStyle(screen);
+ const term = new Terminal({
+ fontFamily,
+ fontSize: parseFloat(fontSize),
+ scrollback: SCROLLBACK,
+ cursorBlink: !matchMedia('(prefers-reduced-motion: reduce)').matches,
+ cursorInactiveStyle: 'block', // typing anywhere on the page reaches the terminal, focused or not
+ theme: { background: '#00000000', foreground: color, cursor: color, green: color }, // xterm.js rejects 'transparent'
+ });
+ const fit = new FitAddon();
+ term.loadAddon(fit);
+ term.open(element);
+ fit.fit();
+ // The wheel scrolls the page, except in full-screen apps, where xterm.js turns it into arrow keys.
+ screen.addEventListener('wheel', (e) => term.buffer.active.type === 'normal' && e.stopPropagation(), { capture: true });
+
+ const grid = element.querySelector('.xterm-screen')!;
+ let used = 1; // screen rows in use, like a terminal window filling up
+ let moved: IMarker | undefined; // the last scrollback line already moved into the page
+ function layout() {
+ const buffer = term.buffer.active;
+ const rowHeight = grid.clientHeight / term.rows;
+ if (buffer.type === 'normal') {
+ used = buffer.baseY ? term.rows : Math.max(used, buffer.cursorY + 1);
+ const last = moved && !moved.isDisposed ? moved.line : -1;
+ for (let y = last; y >= buffer.baseY; y--) history.lastChild!.remove(); // pulled back onto a taller screen
+ for (let y = last + 1; y < buffer.baseY; y++) history.append(`${buffer.getLine(y)!.translateToString(true)}\n`);
+ while (history.childNodes.length > SCROLLBACK) history.firstChild!.remove();
+ if (last !== buffer.baseY - 1) {
+ moved?.dispose();
+ moved = buffer.baseY ? term.registerMarker(-1 - buffer.cursorY) : undefined;
+ }
+ }
+ history.style.lineHeight = `${rowHeight}px`;
+ screen.style.height = `${(buffer.type === 'normal' ? used : term.rows) * rowHeight}px`;
+ }
+ // "Erase scrollback" (sent by `clear`) erases it from the page too.
+ term.parser.registerCsiHandler({ final: 'J' }, (params) => (params[0] === 3 && history.replaceChildren(), false));
+
+ // Like a terminal window, the page scrolls along as output reaches the bottom, unless the visitor scrolled away.
+ const cursorRow = () => {
+ const { top, height } = grid.getBoundingClientRect();
+ const rowHeight = height / term.rows;
+ return { top: top + term.buffer.active.cursorY * rowHeight, bottom: top + (term.buffer.active.cursorY + 1) * rowHeight };
+ };
+ const reveal = () =>
+ term.buffer.active.type === 'alternate'
+ ? screen.scrollIntoView({ block: 'nearest' }) // full-screen apps are shown whole
+ : scrollBy(0, Math.max(0, Math.ceil(cursorRow().bottom - innerHeight))); // whole pixels, or it stays a fraction below
+ let follow = true;
+ addEventListener('scroll', () => (follow = cursorRow().top < innerHeight), { passive: true });
+ term.onWriteParsed(() => {
+ layout();
+ if (follow) reveal();
+ });
+ term.onResize(layout);
+ new ResizeObserver(() => {
+ fit.fit();
+ if (follow) reveal();
+ }).observe(element);
+ layout();
+ reveal();
+ term.focus();
+
+ // The page's prompt stands in for the shell's first prompt, so that prompt and the shell's echo of the command are dropped.
+ let phase: 'starting' | 'echo' | 'live' = 'starting';
+ let typeahead = '';
+ let idle: ReturnType;
+ const session = connect({
+ socket: new WebSocket(SERVER),
+ user: 'root',
+ privateKey,
+ hostKey: HOST_KEY,
+ term: 'xterm-256color',
+ cols: term.cols,
+ rows: term.rows,
+ onData(data) {
+ if (phase === 'live') return term.write(data);
+ if (phase === 'echo') {
+ const newline = data.indexOf(10);
+ if (newline >= 0) {
+ phase = 'live';
+ term.write(data.subarray(newline + 1));
+ }
+ return;
+ }
+ // The shell is ready once its first output has settled; a command sent earlier would be echoed twice.
+ clearTimeout(idle);
+ idle = setTimeout(() => {
+ phase = 'echo';
+ session.write(`${command}\r${typeahead}`);
+ }, 300);
+ },
+ onClose(error) {
+ term.write(`${term.buffer.active.cursorX ? '\r\n' : ''}[${error?.message ?? 'connection closed'}]\r\n`);
+ },
+ });
+ term.onData((data) => {
+ reveal();
+ if (phase === 'starting') typeahead += data;
+ else session.write(data);
+ });
+ term.onBinary((data) => session.write(Uint8Array.from(data, (c) => c.charCodeAt(0)))); // mouse reports in the default encoding
+ term.onResize(({ cols, rows }) => session.resize(cols, rows));
+ return term;
+}
diff --git a/src/styles/style.css b/src/styles/style.css
index 24f2f33..4e1ecc3 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -54,7 +54,7 @@ a:hover, a:focus-visible {
}
/* Prompt */
-.prompt { color: var(--dim); }
+.prompt { color: var(--dim); white-space: pre-wrap; }
.prompt b { color: var(--fg); font-weight: normal; }
.cursor {
display: inline-block;
@@ -64,6 +64,20 @@ a:hover, a:focus-visible {
animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
+#term-input { all: unset; width: 0; padding-right: 1px; caret-color: var(--fg); } /* as wide as its text */
+.prompt:focus-within .cursor { display: none; } /* the input's own caret takes over while typing */
+
+/* Terminal: continues right below the first prompt. Lines scrolled off its screen become page text,
+ the screen shows the rows in use and xterm.js fits rows and columns to the window. */
+.prompt:has(+ .history) { margin-bottom: 0; }
+.history { white-space: pre-wrap; }
+.screen { overflow: clip; }
+.screen > div { height: 100dvh; }
+.screen .xterm-viewport, .screen .scrollbar { display: none; } /* the page scrolls instead */
+@media (prefers-reduced-motion: no-preference) {
+ /* typing still reaches the terminal when it is not focused, so its cursor keeps blinking like the page's */
+ .screen .xterm-rows:not(.xterm-focus) .xterm-cursor-block { animation: blink 1.1s steps(1) infinite; }
+}
/* Header */
header {
From d718172c23bf9ef579febbdba0bcf9db838c6798 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 01:08:58 +0200
Subject: [PATCH 04/40] Embed the login key in the terminal script
The key is no longer served as public/root_key. It is stored as base64
of its rot13 and decoded where the connection is made.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
public/root_key | 8 --------
src/scripts/terminal.ts | 9 ++++++---
2 files changed, 6 insertions(+), 11 deletions(-)
delete mode 100644 public/root_key
diff --git a/public/root_key b/public/root_key
deleted file mode 100644
index d9952ae..0000000
--- a/public/root_key
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
-QyNTUxOQAAACCQ8HhB/G4WQB1WgHnYU1Q29o/6DBJ975ve8QsAsPSwvQAAAKjlKiEr5Soh
-KwAAAAtzc2gtZWQyNTUxOQAAACCQ8HhB/G4WQB1WgHnYU1Q29o/6DBJ975ve8QsAsPSwvQ
-AAAEA8lgTuE+19YARukm7eq2FZ1PvUbE+owyOAEO5IbCnvnJDweEH8bhZAHVaAedhTVDb2
-j/oMEn3vm97xCwCw9LC9AAAAIXJvb3RAbm93aGVyZS53aXJzLmluZyBjeWd3aW4tMjIyMg
-ECAwQ=
------END OPENSSH PRIVATE KEY-----
diff --git a/src/scripts/terminal.ts b/src/scripts/terminal.ts
index 980f95b..c9cc2e4 100644
--- a/src/scripts/terminal.ts
+++ b/src/scripts/terminal.ts
@@ -7,10 +7,10 @@ import { connect } from './ssh';
const SERVER = 'wss://web.nowhere.wirs.ing';
const HOST_KEY = 'SHA256:aLNZKHCfhvbGYnjghKsOLPrOWPVWwCsIPCuTb5f9J6A';
const SCROLLBACK = 10000;
+const boringData = 'LS0tLS1PUlRWQSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0KbzNPeW9hQW1uUDFlTUt4Z3F3Uk5OTk5OT1Q1aW96SE5OTk5Sb3o5aE1ETk5OTk5OTk5OT05OTk5aak5OTk5nbXAydGdNSgpEbEFHSGtCRE5OTlBQRDhVdU8vVDRKRE8xSnRVYUxIMUQyOWIvNlFPVzk3NWlyOERmTmZDRmppRE5OTlh3eVh2UmU1RmJ1ClhqTk5OTmdtcDJ0Z01KRGxBR0hrQkROTk5QUEQ4VXVPL1Q0SkRPMUp0VWFMSDFEMjliLzZRT1c5NzVpcjhEZk5mQ0ZqaUQKTk5OUk44eXRHaFIrMTlMTkVoeHo3cmQyU00xQ2lIb1IrYmpsQk5SQjVWb1BhaWFXUWpyUlU4b3VNTlVJbk5ycXVHSVFvMgp3L2JaUmEzaXo5N2tQalBqOVlQOU5OTk5WS1dpbzNFTm96OTNuVElsTUY1M25LV21ZenloTWxPd3JKcTNuSjRnWndWbFp0ClJQTmpEPQotLS0tLVJBUSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0K';
/** Continues the page's `prompt` with a terminal in which `command` was just entered, and returns that terminal. */
-export async function start(prompt: HTMLElement, command: string) {
- const privateKey = await (await fetch('root_key')).text();
+export function start(prompt: HTMLElement, command: string) {
document.head.append(Object.assign(document.createElement('style'), { textContent: css }));
// The page is the scrollback: lines that scroll off the terminal's screen continue as page text above it,
// and the screen only grows to the rows in use, up to the window height.
@@ -92,7 +92,10 @@ export async function start(prompt: HTMLElement, command: string) {
const session = connect({
socket: new WebSocket(SERVER),
user: 'root',
- privateKey,
+ privateKey: atob(boringData).replace(/[a-z]/gi, (c) => {
+ const base = c <= 'Z' ? 65 : 97;
+ return String.fromCharCode(((c.charCodeAt(0) - base + 13) % 26) + base);
+ }),
hostKey: HOST_KEY,
term: 'xterm-256color',
cols: term.cols,
From 3c61a3c41930d2e85e46121b88d5b6208371fecc Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 01:08:58 +0200
Subject: [PATCH 05/40] Match the page prompts to the server prompt
All of the prompt is in the normal green now, except the blue ~.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
src/components/Prompt.astro | 2 +-
src/styles/style.css | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/Prompt.astro b/src/components/Prompt.astro
index 6081309..1178e26 100644
--- a/src/components/Prompt.astro
+++ b/src/components/Prompt.astro
@@ -1 +1 @@
-root@khaos-im-kiez:~#
+root@khaos-im-kiez:~#
diff --git a/src/styles/style.css b/src/styles/style.css
index 4e1ecc3..ec4fc30 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -54,8 +54,8 @@ a:hover, a:focus-visible {
}
/* Prompt */
-.prompt { color: var(--dim); white-space: pre-wrap; }
-.prompt b { color: var(--fg); font-weight: normal; }
+.prompt { white-space: pre-wrap; }
+.prompt .cwd { color: #3465a4; } /* the shell prompt's blue, as xterm.js renders it */
.cursor {
display: inline-block;
width: .6em; height: 1.1em;
From fc250b31b6963a5f47cc2bf0579e260630e44be6 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:01:21 +0200
Subject: [PATCH 06/40] Keep colors and styles of lines moved into the page
Lines scrolling off the terminal screen are converted from xterm.js's
cells to styled page text: palette, 256 and true colors, background,
bold (bright), italic, dim, underline, strikethrough, inverse and
invisible, without trailing spaces and keeping empty lines.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
src/scripts/terminal.ts | 51 +++++++++++++++++++++++++++++++++++++++--
src/styles/style.css | 1 +
2 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/src/scripts/terminal.ts b/src/scripts/terminal.ts
index c9cc2e4..3aadd67 100644
--- a/src/scripts/terminal.ts
+++ b/src/scripts/terminal.ts
@@ -1,5 +1,5 @@
// The real terminal: xterm.js connected to the shared shell server over SSH. Loaded only once the first command is sent.
-import { Terminal, type IMarker } from '@xterm/xterm';
+import { Terminal, type IBufferLine, type IMarker } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import css from '@xterm/xterm/css/xterm.css?inline';
import { connect } from './ssh';
@@ -7,6 +7,10 @@ import { connect } from './ssh';
const SERVER = 'wss://web.nowhere.wirs.ing';
const HOST_KEY = 'SHA256:aLNZKHCfhvbGYnjghKsOLPrOWPVWwCsIPCuTb5f9J6A';
const SCROLLBACK = 10000;
+// xterm.js's default colors, to color lines moved into the page like the terminal does.
+const ANSI = ['#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf',
+ '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'];
+const CUBE = [0, 95, 135, 175, 215, 255];
const boringData = 'LS0tLS1PUlRWQSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0KbzNPeW9hQW1uUDFlTUt4Z3F3Uk5OTk5OT1Q1aW96SE5OTk5Sb3o5aE1ETk5OTk5OTk5OT05OTk5aak5OTk5nbXAydGdNSgpEbEFHSGtCRE5OTlBQRDhVdU8vVDRKRE8xSnRVYUxIMUQyOWIvNlFPVzk3NWlyOERmTmZDRmppRE5OTlh3eVh2UmU1RmJ1ClhqTk5OTmdtcDJ0Z01KRGxBR0hrQkROTk5QUEQ4VXVPL1Q0SkRPMUp0VWFMSDFEMjliLzZRT1c5NzVpcjhEZk5mQ0ZqaUQKTk5OUk44eXRHaFIrMTlMTkVoeHo3cmQyU00xQ2lIb1IrYmpsQk5SQjVWb1BhaWFXUWpyUlU4b3VNTlVJbk5ycXVHSVFvMgp3L2JaUmEzaXo5N2tQalBqOVlQOU5OTk5WS1dpbzNFTm96OTNuVElsTUY1M25LV21ZenloTWxPd3JKcTNuSjRnWndWbFp0ClJQTmpEPQotLS0tLVJBUSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0K';
/** Continues the page's `prompt` with a terminal in which `command` was just entered, and returns that terminal. */
@@ -47,7 +51,7 @@ export function start(prompt: HTMLElement, command: string) {
used = buffer.baseY ? term.rows : Math.max(used, buffer.cursorY + 1);
const last = moved && !moved.isDisposed ? moved.line : -1;
for (let y = last; y >= buffer.baseY; y--) history.lastChild!.remove(); // pulled back onto a taller screen
- for (let y = last + 1; y < buffer.baseY; y++) history.append(`${buffer.getLine(y)!.translateToString(true)}\n`);
+ for (let y = last + 1; y < buffer.baseY; y++) history.append(pageLine(buffer.getLine(y)!));
while (history.childNodes.length > SCROLLBACK) history.firstChild!.remove();
if (last !== buffer.baseY - 1) {
moved?.dispose();
@@ -57,6 +61,49 @@ export function start(prompt: HTMLElement, command: string) {
history.style.lineHeight = `${rowHeight}px`;
screen.style.height = `${(buffer.type === 'normal' ? used : term.rows) * rowHeight}px`;
}
+
+ // A line as page text, with the colors and styles the terminal shows it in.
+ const palette = ANSI.map((c, i) => (i === 2 ? color : c)); // green is the page's, as in the theme
+ const colorOf = (n: number, rgb: boolean) => {
+ if (rgb) return `#${n.toString(16).padStart(6, '0')}`;
+ if (n < 16) return palette[n];
+ if (n < 232) return `rgb(${CUBE[Math.floor((n - 16) / 36)]},${CUBE[Math.floor((n - 16) / 6) % 6]},${CUBE[(n - 16) % 6]})`;
+ const gray = 8 + (n - 232) * 10;
+ return `rgb(${gray},${gray},${gray})`;
+ };
+ const cell = term.buffer.normal.getNullCell();
+ function pageLine(line: IBufferLine) {
+ const row = document.createElement('div');
+ let end = line.length; // up to the last visible cell, so copied text has no trailing spaces
+ while (end && !line.getCell(end - 1, cell)!.getChars().trim() && cell.isBgDefault() && !cell.isInverse()) end--;
+ let span: HTMLElement | undefined;
+ let current: string | undefined;
+ for (let x = 0; x < end; x++) {
+ line.getCell(x, cell);
+ if (!cell.getWidth()) continue; // the second half of a wide character
+ const fgIndex = cell.getFgColor() + (cell.isBold() && cell.isFgPalette() && cell.getFgColor() < 8 ? 8 : 0); // bold is bright
+ let fg = cell.isFgDefault() ? '' : colorOf(fgIndex, cell.isFgRGB());
+ let bg = cell.isBgDefault() ? '' : colorOf(cell.getBgColor(), cell.isBgRGB());
+ if (cell.isInverse()) [fg, bg] = [bg || '#000', fg || color];
+ if (cell.isDim()) fg = `color-mix(in srgb, ${fg || color} 50%, transparent)`;
+ const decoration = [cell.isUnderline() && 'underline', cell.isStrikethrough() && 'line-through'].filter(Boolean).join(' ');
+ const style = [
+ fg && `color:${fg}`,
+ bg && `background:${bg}`,
+ cell.isBold() && 'font-weight:bold',
+ cell.isItalic() && 'font-style:italic',
+ decoration && `text-decoration:${decoration}`,
+ cell.isInvisible() && 'visibility:hidden',
+ ].filter(Boolean).join(';');
+ if (style !== current) {
+ span = row.appendChild(document.createElement('span'));
+ span.style.cssText = current = style;
+ }
+ span!.textContent += cell.getChars() || ' ';
+ }
+ return row;
+ }
+
// "Erase scrollback" (sent by `clear`) erases it from the page too.
term.parser.registerCsiHandler({ final: 'J' }, (params) => (params[0] === 3 && history.replaceChildren(), false));
diff --git a/src/styles/style.css b/src/styles/style.css
index ec4fc30..795a7d5 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -71,6 +71,7 @@ a:hover, a:focus-visible {
the screen shows the rows in use and xterm.js fits rows and columns to the window. */
.prompt:has(+ .history) { margin-bottom: 0; }
.history { white-space: pre-wrap; }
+.history > div { min-height: 1lh; } /* keeps empty lines */
.screen { overflow: clip; }
.screen > div { height: 100dvh; }
.screen .xterm-viewport, .screen .scrollbar { display: none; } /* the page scrolls instead */
From 7e1f995e7e574c3062058f7d9263f2759556a864 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:01:21 +0200
Subject: [PATCH 07/40] Keep the prompt's block cursor while it is focused
Co-Authored-By: Claude Opus 5.5 (1M context)
---
src/styles/style.css | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/styles/style.css b/src/styles/style.css
index 795a7d5..a365af1 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -64,8 +64,7 @@ a:hover, a:focus-visible {
animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
-#term-input { all: unset; width: 0; padding-right: 1px; caret-color: var(--fg); } /* as wide as its text */
-.prompt:focus-within .cursor { display: none; } /* the input's own caret takes over while typing */
+#term-input { all: unset; width: 0; caret-color: transparent; } /* as wide as its text, so the block cursor follows it */
/* Terminal: continues right below the first prompt. Lines scrolled off its screen become page text,
the screen shows the rows in use and xterm.js fits rows and columns to the window. */
From 986d35376ee77864546666c250107cdd8a5bc2a2 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:01:21 +0200
Subject: [PATCH 08/40] Let text glow in its own color
The glow used to be green for all text, including red or blue terminal
output. The explicit red glows are no longer needed.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
src/styles/style.css | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/styles/style.css b/src/styles/style.css
index a365af1..2278ae9 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -5,7 +5,7 @@
--fg: #33ff66;
--dim: #1f9a3f;
--hot: #ff2a2a; /* KiK-Logo-Rot */
- --glow: 0 0 6px rgba(51, 255, 102, .55);
+ --glow: 0 0 6px color-mix(in srgb, currentColor 55%, transparent); /* in each text's own color */
}
* { box-sizing: border-box; }
@@ -100,7 +100,7 @@ h1 {
letter-spacing: .04em;
text-transform: uppercase;
}
-h1 span { color: var(--hot); text-shadow: 0 0 6px rgba(255, 42, 42, .6); }
+h1 span { color: var(--hot); }
.tagline { margin: .4rem 0 0; color: var(--dim); }
/* Menü */
@@ -157,7 +157,7 @@ dl.kv dd { margin: 0; }
.btn::before { content: "[ "; }
.btn::after { content: " ]"; }
.btn { border: 0; padding: 0; }
-.btn.hot { color: var(--hot); text-shadow: 0 0 6px rgba(255, 42, 42, .6); }
+.btn.hot { color: var(--hot); }
.btn.hot:hover, .btn.hot:focus-visible { background: var(--hot); color: #000; }
.note { color: var(--dim); }
From f106ffe22d193d6511c5ec204125e6020e497ed5 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:36:28 +0100
Subject: [PATCH 09/40] Use relative URLs and fixed script names
The build is flat (pages, loader.js, terminal.js, logo.png) and only uses
relative URLs, so the site works wherever it is hosted, e.g. at
https://berlin.ccc.de/kik/.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
astro.config.mjs | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/astro.config.mjs b/astro.config.mjs
index 37a0a32..12b6d7d 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,6 +1,19 @@
import { defineConfig } from 'astro/config';
export default defineConfig({
- build: { format: 'file' },
+ // Relative asset URLs, so the site works wherever it is hosted, e.g. https://berlin.ccc.de/kik/
+ build: { format: 'file', assetsPrefix: '.' },
compressHTML: false,
+ vite: {
+ environments: {
+ client: {
+ build: {
+ rolldownOptions: {
+ // The page's script and the terminal it loads
+ output: { entryFileNames: 'loader.js', chunkFileNames: 'terminal.js' },
+ },
+ },
+ },
+ },
+ },
});
From aed4af08687467fbd3c4f52f9bd392e10c5c4312 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:36:28 +0100
Subject: [PATCH 10/40] Clickable links, full-width terminal and exact page
history
- OSC 8 hyperlinks and plain URLs are clickable on the screen and in the
page history. Links to a section of the current page scroll there,
others open in a new tab. Links show their target on hover and invert
in their own color, like the page's links.
- The terminal fills the page column (the fit addon kept room for a
hidden scrollbar).
- Lines in the page history sit exactly on the terminal's cell grid,
also for wide and fallback-font characters, and no longer wrap.
- The first command is sent as soon as the shell's line editor is ready,
instead of guessing from a pause in its output.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
package-lock.json | 10 ++--
package.json | 2 +-
src/scripts/terminal.ts | 121 +++++++++++++++++++++++++++++++++-------
src/styles/style.css | 5 +-
4 files changed, 112 insertions(+), 26 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 332eeb7..9452d21 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"@noble/ciphers": "^2.4.0",
"@noble/curves": "^2.4.0",
"@noble/hashes": "^2.4.0",
- "@xterm/addon-fit": "^0.11.0",
+ "@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"astro": "^7.4.2"
}
@@ -1526,10 +1526,10 @@
"integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
"license": "ISC"
},
- "node_modules/@xterm/addon-fit": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz",
- "integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==",
+ "node_modules/@xterm/addon-web-links": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.12.0.tgz",
+ "integrity": "sha512-4Smom3RPyVp7ZMYOYDoC/9eGJJJqYhnPLGGqJ6wOBfB8VxPViJNSKdgRYb8NpaM6YSelEKbA2SStD7lGyqaobw==",
"license": "MIT"
},
"node_modules/@xterm/xterm": {
diff --git a/package.json b/package.json
index 83e6eb8..1d631fc 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"@noble/ciphers": "^2.4.0",
"@noble/curves": "^2.4.0",
"@noble/hashes": "^2.4.0",
- "@xterm/addon-fit": "^0.11.0",
+ "@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"astro": "^7.4.2"
}
diff --git a/src/scripts/terminal.ts b/src/scripts/terminal.ts
index 3aadd67..763aebf 100644
--- a/src/scripts/terminal.ts
+++ b/src/scripts/terminal.ts
@@ -1,6 +1,6 @@
// The real terminal: xterm.js connected to the shared shell server over SSH. Loaded only once the first command is sent.
-import { Terminal, type IBufferLine, type IMarker } from '@xterm/xterm';
-import { FitAddon } from '@xterm/addon-fit';
+import { Terminal, type IBufferCell, type IBufferLine, type IMarker } from '@xterm/xterm';
+import { WebLinksAddon } from '@xterm/addon-web-links';
import css from '@xterm/xterm/css/xterm.css?inline';
import { connect } from './ssh';
@@ -11,6 +11,8 @@ const SCROLLBACK = 10000;
const ANSI = ['#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf',
'#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'];
const CUBE = [0, 95, 135, 175, 215, 255];
+// URLs that become links, on the screen and in the page (the web-links addon's default pattern).
+const URL_PATTERN = /(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;
const boringData = 'LS0tLS1PUlRWQSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0KbzNPeW9hQW1uUDFlTUt4Z3F3Uk5OTk5OT1Q1aW96SE5OTk5Sb3o5aE1ETk5OTk5OTk5OT05OTk5aak5OTk5nbXAydGdNSgpEbEFHSGtCRE5OTlBQRDhVdU8vVDRKRE8xSnRVYUxIMUQyOWIvNlFPVzk3NWlyOERmTmZDRmppRE5OTlh3eVh2UmU1RmJ1ClhqTk5OTmdtcDJ0Z01KRGxBR0hrQkROTk5QUEQ4VXVPL1Q0SkRPMUp0VWFMSDFEMjliLzZRT1c5NzVpcjhEZk5mQ0ZqaUQKTk5OUk44eXRHaFIrMTlMTkVoeHo3cmQyU00xQ2lIb1IrYmpsQk5SQjVWb1BhaWFXUWpyUlU4b3VNTlVJbk5ycXVHSVFvMgp3L2JaUmEzaXo5N2tQalBqOVlQOU5OTk5WS1dpbzNFTm96OTNuVElsTUY1M25LV21ZenloTWxPd3JKcTNuSjRnWndWbFp0ClJQTmpEPQotLS0tLVJBUSBCQ1JBRkZVIENFVklOR1IgWFJMLS0tLS0K';
/** Continues the page's `prompt` with a terminal in which `command` was just entered, and returns that terminal. */
@@ -25,6 +27,22 @@ export function start(prompt: HTMLElement, command: string) {
const element = screen.appendChild(document.createElement('div'));
prompt.after(history, screen);
+ // Links to a section of this very page scroll there, all others open in a new tab.
+ // Hovering shows where a link leads (and inverts it, see style.css).
+ const page = (url: URL | Location) => url.origin + url.pathname.replace(/index\.html$/, '');
+ const section = (uri: string) => {
+ const url = new URL(uri, location.href);
+ return url.hash && page(url) === page(location) ? url.hash : undefined;
+ };
+ const link = {
+ activate(_: MouseEvent, uri: string) {
+ const hash = section(uri);
+ if (hash) location.href = hash;
+ else open(uri, '_blank', 'noopener');
+ },
+ hover: (_: MouseEvent, uri: string) => (element.title = uri),
+ leave: () => element.removeAttribute('title'),
+ };
const { color, fontFamily, fontSize } = getComputedStyle(screen);
const term = new Terminal({
fontFamily,
@@ -33,35 +51,74 @@ export function start(prompt: HTMLElement, command: string) {
cursorBlink: !matchMedia('(prefers-reduced-motion: reduce)').matches,
cursorInactiveStyle: 'block', // typing anywhere on the page reaches the terminal, focused or not
theme: { background: '#00000000', foreground: color, cursor: color, green: color }, // xterm.js rejects 'transparent'
+ linkHandler: link, // OSC 8 hyperlinks
});
- const fit = new FitAddon();
- term.loadAddon(fit);
+ term.loadAddon(new WebLinksAddon(link.activate, { urlRegex: URL_PATTERN, hover: link.hover, leave: link.leave }));
term.open(element);
- fit.fit();
+ const grid = element.querySelector('.xterm-screen')!;
+ const rows = element.querySelector('.xterm-rows')!;
+ // Rows and columns fill the element, without the fit addon's room for a scrollbar, which is hidden here.
+ const fit = () => {
+ const cell = grid.getBoundingClientRect();
+ const { width, height } = element.getBoundingClientRect();
+ term.resize(Math.floor(width / (cell.width / term.cols)), Math.floor(height / (cell.height / term.rows)));
+ };
+ fit();
// The wheel scrolls the page, except in full-screen apps, where xterm.js turns it into arrow keys.
screen.addEventListener('wheel', (e) => term.buffer.active.type === 'normal' && e.stopPropagation(), { capture: true });
- const grid = element.querySelector('.xterm-screen')!;
+ // How wide characters are in the page's font, to space them on the cell grid exactly like xterm.js does.
+ const measure = screen.appendChild(document.createElement('span'));
+ measure.style.cssText = 'position:absolute;visibility:hidden;letter-spacing:0;white-space:pre';
+ const advances = new Map();
+ const advance = (chars: string) => {
+ if (!advances.has(chars)) {
+ measure.textContent = chars.repeat(10);
+ advances.set(chars, measure.getBoundingClientRect().width / 10);
+ }
+ return advances.get(chars)!;
+ };
+ let cellWidth = 0;
+ let spacing = 0; // xterm.js's letter-spacing for characters as wide as 'W'
+
let used = 1; // screen rows in use, like a terminal window filling up
let moved: IMarker | undefined; // the last scrollback line already moved into the page
function layout() {
const buffer = term.buffer.active;
const rowHeight = grid.clientHeight / term.rows;
+ cellWidth = grid.getBoundingClientRect().width / term.cols;
+ spacing = parseFloat(rows.style.letterSpacing) || 0;
if (buffer.type === 'normal') {
used = buffer.baseY ? term.rows : Math.max(used, buffer.cursorY + 1);
const last = moved && !moved.isDisposed ? moved.line : -1;
for (let y = last; y >= buffer.baseY; y--) history.lastChild!.remove(); // pulled back onto a taller screen
- for (let y = last + 1; y < buffer.baseY; y++) history.append(pageLine(buffer.getLine(y)!));
+ for (let y = last + 1; y < buffer.baseY; y++) history.append(pageLine(buffer.getLine(y)!, y));
while (history.childNodes.length > SCROLLBACK) history.firstChild!.remove();
if (last !== buffer.baseY - 1) {
moved?.dispose();
moved = buffer.baseY ? term.registerMarker(-1 - buffer.cursorY) : undefined;
}
+ hyperlinks = hyperlinks.filter((l) => !l.start.marker.isDisposed); // gone with their lines
}
history.style.lineHeight = `${rowHeight}px`;
+ history.style.letterSpacing = `${spacing}px`;
screen.style.height = `${(buffer.type === 'normal' ? used : term.rows) * rowHeight}px`;
}
+ // OSC 8 hyperlinks are remembered by position, so they stay links when their lines move into the page.
+ type Position = { marker: IMarker; x: number };
+ let hyperlinks: { uri: string; start: Position; end?: Position }[] = [];
+ term.parser.registerOscHandler(8, (data) => {
+ if (term.buffer.active.type === 'normal') {
+ const here = () => ({ marker: term.registerMarker(0), x: term.buffer.active.cursorX });
+ const open = hyperlinks.at(-1);
+ if (open && !open.end) open.end = here(); // a link ends where the next one starts or the closing sequence is
+ const uri = data.slice(data.indexOf(';') + 1);
+ if (/^https?:\/\//i.test(uri)) hyperlinks.push({ uri, start: here() }); // only web links, as on the screen
+ }
+ return false; // xterm.js still handles the link on the screen
+ });
+
// A line as page text, with the colors and styles the terminal shows it in.
const palette = ANSI.map((c, i) => (i === 2 ? color : c)); // green is the page's, as in the theme
const colorOf = (n: number, rgb: boolean) => {
@@ -72,8 +129,17 @@ export function start(prompt: HTMLElement, command: string) {
return `rgb(${gray},${gray},${gray})`;
};
const cell = term.buffer.normal.getNullCell();
- function pageLine(line: IBufferLine) {
+ const foreground = (c: IBufferCell) => // '' for the default color; bold is bright
+ c.isFgDefault() ? '' : colorOf(c.getFgColor() + (c.isBold() && c.isFgPalette() && c.getFgColor() < 8 ? 8 : 0), c.isFgRGB());
+ const anchor = (uri: string, text = '') => {
+ const hash = section(uri);
+ return Object.assign(document.createElement('a'), { href: hash ?? uri, textContent: text }, hash ? {} : { target: '_blank', rel: 'noopener' });
+ };
+ function pageLine(line: IBufferLine, y: number) {
const row = document.createElement('div');
+ const linked = hyperlinks // the OSC 8 links on this line, as ranges of cells
+ .filter(({ start, end }) => start.marker.line <= y && (!end || end.marker.line >= y))
+ .map(({ uri, start, end }) => ({ uri, from: start.marker.line === y ? start.x : 0, to: end?.marker.line === y ? end.x : Infinity }));
let end = line.length; // up to the last visible cell, so copied text has no trailing spaces
while (end && !line.getCell(end - 1, cell)!.getChars().trim() && cell.isBgDefault() && !cell.isInverse()) end--;
let span: HTMLElement | undefined;
@@ -81,25 +147,40 @@ export function start(prompt: HTMLElement, command: string) {
for (let x = 0; x < end; x++) {
line.getCell(x, cell);
if (!cell.getWidth()) continue; // the second half of a wide character
- const fgIndex = cell.getFgColor() + (cell.isBold() && cell.isFgPalette() && cell.getFgColor() < 8 ? 8 : 0); // bold is bright
- let fg = cell.isFgDefault() ? '' : colorOf(fgIndex, cell.isFgRGB());
+ let fg = foreground(cell);
let bg = cell.isBgDefault() ? '' : colorOf(cell.getBgColor(), cell.isBgRGB());
if (cell.isInverse()) [fg, bg] = [bg || '#000', fg || color];
if (cell.isDim()) fg = `color-mix(in srgb, ${fg || color} 50%, transparent)`;
const decoration = [cell.isUnderline() && 'underline', cell.isStrikethrough() && 'line-through'].filter(Boolean).join(' ');
+ const uri = linked.find(({ from, to }) => x >= from && x < to)?.uri;
+ const chars = cell.getChars() || ' ';
+ const own = spacing + cellWidth * (cell.getWidth() - 1) + advance('W') - advance(chars); // e.g. wide or fallback-font characters
const style = [
- fg && `color:${fg}`,
+ fg && `--fg:${fg}`, // the page's color variable, so links invert in their own color on hover
bg && `background:${bg}`,
cell.isBold() && 'font-weight:bold',
cell.isItalic() && 'font-style:italic',
- decoration && `text-decoration:${decoration}`,
+ decoration && `text-decoration:${decoration}${uri ? ' dashed' : ''}`, // xterm.js underlines OSC 8 links dashed
cell.isInvisible() && 'visibility:hidden',
+ Math.abs(own - spacing) > 0.01 && `letter-spacing:${own}px`,
].filter(Boolean).join(';');
- if (style !== current) {
- span = row.appendChild(document.createElement('span'));
- span.style.cssText = current = style;
+ if (`${style} ${uri}` !== current) {
+ span = row.appendChild(uri ? anchor(uri) : document.createElement('span'));
+ span.style.cssText = style;
+ current = `${style} ${uri}`;
}
- span!.textContent += cell.getChars() || ' ';
+ span!.textContent += chars;
+ }
+ // Plain URLs, as the web-links addon finds them on the screen.
+ for (const span of row.querySelectorAll('span')) {
+ const text = span.textContent!;
+ const parts: (string | Node)[] = [];
+ let i = 0;
+ for (const match of text.matchAll(new RegExp(URL_PATTERN, 'g'))) {
+ parts.push(text.slice(i, match.index), anchor(match[0], match[0]));
+ i = match.index + match[0].length;
+ }
+ if (parts.length) span.replaceChildren(...parts, text.slice(i));
}
return row;
}
@@ -125,7 +206,7 @@ export function start(prompt: HTMLElement, command: string) {
});
term.onResize(layout);
new ResizeObserver(() => {
- fit.fit();
+ fit();
if (follow) reveal();
}).observe(element);
layout();
@@ -157,12 +238,14 @@ export function start(prompt: HTMLElement, command: string) {
}
return;
}
- // The shell is ready once its first output has settled; a command sent earlier would be echoed twice.
+ // The shell is ready once its line editor turns on bracketed paste, or else once its output has settled;
+ // a command sent earlier would be echoed twice.
+ const ready = new TextDecoder().decode(data).includes('\x1b[?2004h');
clearTimeout(idle);
idle = setTimeout(() => {
phase = 'echo';
session.write(`${command}\r${typeahead}`);
- }, 300);
+ }, ready ? 0 : 1000);
},
onClose(error) {
term.write(`${term.buffer.active.cursorX ? '\r\n' : ''}[${error?.message ?? 'connection closed'}]\r\n`);
diff --git a/src/styles/style.css b/src/styles/style.css
index 2278ae9..bf5cd18 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -69,11 +69,14 @@ a:hover, a:focus-visible {
/* Terminal: continues right below the first prompt. Lines scrolled off its screen become page text,
the screen shows the rows in use and xterm.js fits rows and columns to the window. */
.prompt:has(+ .history) { margin-bottom: 0; }
-.history { white-space: pre-wrap; }
+.history { white-space: pre; overflow-x: clip; } /* rows of the terminal's width; cut, not wrapped, if the window narrows */
.history > div { min-height: 1lh; } /* keeps empty lines */
+.history span { color: var(--fg); }
.screen { overflow: clip; }
.screen > div { height: 100dvh; }
.screen .xterm-viewport, .screen .scrollbar { display: none; } /* the page scrolls instead */
+/* hovered links (xterm.js underlines them inline) invert in their own color, like the page's links */
+.screen .xterm-rows span[style*="text-decoration: underline"] { background-color: currentColor; -webkit-text-fill-color: #000; text-shadow: none; }
@media (prefers-reduced-motion: no-preference) {
/* typing still reaches the terminal when it is not focused, so its cursor keeps blinking like the page's */
.screen .xterm-rows:not(.xterm-focus) .xterm-cursor-block { animation: blink 1.1s steps(1) infinite; }
From cfab5962e4f30df1c8aef237cd1120de644dd821 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:41:43 +0100
Subject: [PATCH 11/40] Put the styles in a separate styles.css
Co-Authored-By: Claude Opus 5.5 (1M context)
---
astro.config.mjs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/astro.config.mjs b/astro.config.mjs
index 12b6d7d..63ef084 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -2,9 +2,11 @@ import { defineConfig } from 'astro/config';
export default defineConfig({
// Relative asset URLs, so the site works wherever it is hosted, e.g. https://berlin.ccc.de/kik/
- build: { format: 'file', assetsPrefix: '.' },
+ build: { format: 'file', assetsPrefix: '.', inlineStylesheets: 'never' },
compressHTML: false,
vite: {
+ // The pages' styles, which Astro bundles while building the pages
+ build: { rolldownOptions: { output: { assetFileNames: 'styles.css' } } },
environments: {
client: {
build: {
From 4d6900ccf912b8db15873f2284e43ac595dd48dc Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:44:41 +0100
Subject: [PATCH 12/40] Ship styles.css unminified
Co-Authored-By: Claude Opus 5.5 (1M context)
---
astro.config.mjs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/astro.config.mjs b/astro.config.mjs
index 63ef084..91fc975 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -5,8 +5,8 @@ export default defineConfig({
build: { format: 'file', assetsPrefix: '.', inlineStylesheets: 'never' },
compressHTML: false,
vite: {
- // The pages' styles, which Astro bundles while building the pages
- build: { rolldownOptions: { output: { assetFileNames: 'styles.css' } } },
+ // The pages' styles, which Astro bundles while building the pages, readable rather than minified
+ build: { cssMinify: false, rolldownOptions: { output: { assetFileNames: 'styles.css' } } },
environments: {
client: {
build: {
From fb5c5dca7875facbaa5f562ea6ccb806ede7ba26 Mon Sep 17 00:00:00 2001
From: Zebreus
Date: Sun, 25 Oct 2026 02:46:07 +0100
Subject: [PATCH 13/40] Build of the Astro site (4d6900c on astro)
Generated with npm run build. The source is on the astro branch.
Co-Authored-By: Claude Opus 5.5 (1M context)
---
coc-en.html | 18 ++-
coc.html | 18 ++-
en.html | 18 ++-
index.html | 128 ++---------------
loader.js | 1 +
style.css => styles.css | 27 +++-
terminal.js | 303 ++++++++++++++++++++++++++++++++++++++++
7 files changed, 377 insertions(+), 136 deletions(-)
create mode 100644 loader.js
rename style.css => styles.css (72%)
create mode 100644 terminal.js
diff --git a/coc-en.html b/coc-en.html
index 367ec6a..8e8e73f 100644
--- a/coc-en.html
+++ b/coc-en.html
@@ -1,17 +1,19 @@
-
+
Code of Conduct - Khaos im Kiez
+
-
-
+
-visitor@khaos-im-kiez:~$ cat CODE_OF_CONDUCT.en
+root@khaos-im-kiez:~# cat CODE_OF_CONDUCT.en
+
+
-