From 92fa0f8f37da41c987d0dae2cc7df5bcbdb09e9c Mon Sep 17 00:00:00 2001 From: hanyixuanten Date: Sun, 25 Oct 2026 11:23:17 +0000 Subject: [PATCH] feat: initial class history template --- .env.example | 22 + .github/labeler.yml | 9 + .github/workflows/labeler.yml | 16 + .gitignore | 24 + .vscode/extensions.json | 4 + .vscode/launch.json | 11 + README.md | 148 + astro.config.mjs | 14 + functions/api/messages.js | 169 + functions/api/submit.ts | 480 +++ package-lock.json | 4229 +++++++++++++++++++++ package.json | 21 + public/css/index.css | 1126 ++++++ public/css/pages.css | 600 +++ public/js/index.js | 282 ++ public/js/music-random.js | 192 + public/js/music-shuffle.js | 60 + public/js/pages.js | 85 + public/pages/static/README.md | 3 + public/pages/static/cover-placeholder.svg | 11 + src/content.config.ts | 28 + src/content/20250101.md | 33 + src/layouts/PostLayout.astro | 193 + src/pages/chronicle.astro | 206 + src/pages/contribute.astro | 948 +++++ src/pages/index.astro | 256 ++ src/pages/music-contribute.astro | 864 +++++ src/pages/music.astro | 541 +++ src/pages/pages/[...slug].astro | 53 + src/plugins/markdown-reveal.mjs | 51 + src/site.config.ts | 22 + src/songs/20250101-example.json | 8 + tsconfig.json | 5 + 33 files changed, 10714 insertions(+) create mode 100644 .env.example create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/labeler.yml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 README.md create mode 100644 astro.config.mjs create mode 100644 functions/api/messages.js create mode 100644 functions/api/submit.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/css/index.css create mode 100644 public/css/pages.css create mode 100644 public/js/index.js create mode 100644 public/js/music-random.js create mode 100644 public/js/music-shuffle.js create mode 100644 public/js/pages.js create mode 100644 public/pages/static/README.md create mode 100644 public/pages/static/cover-placeholder.svg create mode 100644 src/content.config.ts create mode 100644 src/content/20250101.md create mode 100644 src/layouts/PostLayout.astro create mode 100644 src/pages/chronicle.astro create mode 100644 src/pages/contribute.astro create mode 100644 src/pages/index.astro create mode 100644 src/pages/music-contribute.astro create mode 100644 src/pages/music.astro create mode 100644 src/pages/pages/[...slug].astro create mode 100644 src/plugins/markdown-reveal.mjs create mode 100644 src/site.config.ts create mode 100644 src/songs/20250101-example.json create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4fa310a --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# 复制为 .env 使用。注意: +# - PUBLIC_TURNSTILE_SITE_KEY 是构建时变量,本地构建需要; +# - GITHUB_* / TURNSTILE_SECRET_KEY 是 Cloudflare Pages Functions 的 +# 运行时变量,本地 .env 不会生效,需在 Pages 控制台配置(见 README)。 + +# ---- 投稿后端:GitHub App(详见 README「创建 GitHub App」一节) ---- +GITHUB_APP_ID= +GITHUB_INSTALLATION_ID= +GITHUB_PRIVATE_KEY= +GITHUB_OWNER= +GITHUB_REPO= + +# ---- 可选覆盖项(不填使用 functions/api/submit.ts 里的默认值) ---- +# GITHUB_BASE_BRANCH=main +# CONTENT_DIR=src/content +# MEDIA_DIR=public/pages/static +# MEDIA_URL_PREFIX=/pages/static +# SONGS_DIR=src/songs + +# ---- 可选:Cloudflare Turnstile 人机验证(两个都配置才启用) ---- +# TURNSTILE_SECRET_KEY= +# PUBLIC_TURNSTILE_SITE_KEY= diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..b56cbc1 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,9 @@ +version: 1 +labels: + # 班史投稿:chronicle/* 分支(班史投稿表单创建) + - label: "班史投稿" + branch: "^chronicle/" + + # 音乐投稿:music/* 分支(音乐投稿表单创建) + - label: "音乐投稿" + branch: "^music/" diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..51be4c2 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,16 @@ +name: Label PR + +on: + pull_request: + types: [opened, reopened] + +jobs: + label: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: srvaroa/labeler@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16d54bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..3588364 --- /dev/null +++ b/README.md @@ -0,0 +1,148 @@ +# 班史模板 class-history-template + +一个可直接部署的班级纪念册模板,基于 **Astro 7 + Cloudflare Pages**。 + +功能一览: + +- 🏠 **首页**:班级简介、人物志、荣誉墙、记忆墙(均为示例文案,可自行替换) +- 📖 **班史列表 / 文章页**:`src/content/*.md` 自动生成,按日期升序排列,支持封面、摘要、上下篇导航 +- 🎵 **班级歌单**:`src/songs/*.json` 自动生成,支持每日随机排序、随机抽歌 +- 💬 **留言墙**:Cloudflare D1 数据库存储 +- 📝 **在线投稿**:班史 / 音乐两种表单,提交后自动建分支并发 PR,管理员审核合并后上线(由 GitHub App 驱动) + +## 目录结构 + +``` +├── functions/api/ # Cloudflare Pages Functions +│ ├── submit.ts # 投稿 → GitHub PR +│ └── messages.js # 留言墙(需绑定 D1) +├── public/ +│ ├── css/ js/ # 样式与脚本 +│ └── pages/static/ # 文章引用的静态资源(封面图、照片等) +├── src/ +│ ├── content/ # 班史文章(YYYYMMDD.md) +│ ├── songs/ # 歌单(*.json) +│ ├── pages/ # 页面 +│ ├── layouts/ # 文章页布局 +│ ├── plugins/ # markdown 入场动画插件 +│ └── site.config.ts # ★ 班级信息配置 +└── .env.example # 环境变量示例 +``` + +## 快速开始 + +需要 Node.js ≥ 22.12。 + +```bash +npm install +npm run dev # http://localhost:4321 +``` + +注意:`npm run dev` 只渲染页面,`/api/*` 由 Pages Functions 提供服务,只有线上可用——本地留言墙会显示「加载失败」、投稿提交会报错,属正常现象。需要本地调试 API 时可用 `npx wrangler pages dev`。 + +## 定制班级信息 + +1. **`src/site.config.ts`**:班级名、顶栏 logo、首屏徽章、统计数字,改这一个文件即可。 +2. **`src/pages/index.astro`**:班级简介、人物志、荣誉、记忆墙的示例文案(搜索 `20XX` 和各区块的中文示例)。 +3. **`public/js/index.js`**:首屏打字机轮播文案(`lines` 数组)。 +4. 主题色(金色 `#e6c068`)在 `public/css/*.css` 中定义。 + +## 内容格式 + +### 班史文章 `src/content/YYYYMMDD.md` + +文件名用日期(同日多篇加 `-1`、`-2` 后缀),frontmatter 字段: + +| 字段 | 必填 | 说明 | +| -------- | ---- | --------------------------------------- | +| `title` | ✓ | 标题 | +| `date` | ✓ | 日期 `YYYY-MM-DD`,决定排序 | +| `summary`| | 摘要,显示在列表页和文章页副标题 | +| `author` | | 记录人 | +| `cover` | | 封面图路径,如 `/pages/static/xxx.png` | + +正文支持完整 Markdown,含 `
` 折叠块。 + +### 歌曲 `src/songs/*.json` + +```json +{ + "title": "歌名", + "artist": "歌手", + "date": "20250901", + "link": "https://...", + "note": "这首歌和班级的故事", + "author": "推荐人" +} +``` + +`title`、`artist` 必填;`link` 须以 `http(s)://` 开头。 + +> 模板自带一篇示例文章(`src/content/20250101.md`)、一首示例歌曲(`src/songs/20250101-example.json`)和一张占位封面(`public/pages/static/cover-placeholder.svg`),正式使用前请删除前两者。 + +## 部署(Cloudflare Pages) + +1. 推送到 GitHub 仓库。 +2. Cloudflare Dashboard → Workers & Pages → Create → Pages → 连接该仓库: + - Build command:`npm run build` + - Build output directory:`dist` + - 环境变量加 `NODE_VERSION = 22.12.0` +3. `functions/` 目录会被自动部署为 Pages Functions。 + +### 创建 GitHub App(投稿功能需要) + +1. GitHub → Settings → Developer settings → **GitHub Apps** → New GitHub App。 + - Homepage URL 随意填(如仓库地址);不需要回调与 webhook。 + - Repository permissions:**Contents → Read and write**,**Pull requests → Read and write**。 +2. 创建后点 **Generate a private key**,下载 `.pem` 文件。 +3. 左侧 **Install App**,安装到你的仓库;安装页 URL 中的数字即 **Installation ID**(如 `https://github.com/settings/installations/12345` 中的 `12345`)。 +4. 在 Pages 项目 → Settings → Variables and Secrets 中配置环境变量(Production 与 Preview 都要): + +| 变量 | 必填 | 说明 | +| ----------------------- | ---- | ------------------------------------------------- | +| `GITHUB_APP_ID` | ✓ | GitHub App 的 App ID | +| `GITHUB_INSTALLATION_ID`| ✓ | 安装后的 Installation ID | +| `GITHUB_PRIVATE_KEY` | ✓ | `.pem` 私钥全文(含 BEGIN/END 行) | +| `GITHUB_OWNER` | ✓ | 仓库所有者(用户名或组织名) | +| `GITHUB_REPO` | ✓ | 仓库名 | +| `GITHUB_BASE_BRANCH` | | 投稿目标分支,默认 `main` | +| `CONTENT_DIR` 等 | | 投稿落盘目录,默认值见 `functions/api/submit.ts` | + +### 留言墙(D1 数据库) + +1. Dashboard → Storage & Databases → **D1** → 创建数据库。 +2. 在控制台执行建表: + + ```sql + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + text TEXT NOT NULL, + time TEXT NOT NULL, + ip TEXT, + created_at INTEGER NOT NULL + ); + ``` + +3. Pages 项目 → Settings → Functions → **D1 database bindings**,绑定名必须为 **`DB`**。 + +### 人机验证(可选,Cloudflare Turnstile) + +Dashboard → Turnstile → 添加站点,拿到一对 key: + +- `PUBLIC_TURNSTILE_SITE_KEY`:**构建时**变量(也写入本地 `.env` 供本地构建); +- `TURNSTILE_SECRET_KEY`:运行时变量。 + +两个都配置后投稿表单才启用人机验证;不配置则跳过。 + +## 投稿流程 + +表单提交 → `/api/submit` 用 GitHub App 建分支(`chronicle/*` 或 `music/*`)并开 PR → 管理员在 GitHub 审核合并 → Pages 自动重新构建,内容上线。`.github/labeler.yml` 会给投稿 PR 自动打标签。 + +## 常用命令 + +```bash +npm run dev # 本地开发 +npm run build # 构建到 dist/ +npm run preview # 预览构建产物 +``` diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..90929b8 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,14 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import { satteri } from '@astrojs/markdown-satteri'; +import markdownReveal from './src/plugins/markdown-reveal.mjs'; + +// https://astro.build/config +export default defineConfig({ + markdown: { + // Astro 7 的默认 markdown 处理器是 Sätteri(@astrojs/markdown-remark + // 已不再默认安装)。这里在它的 hast 阶段挂上插件,让 markdown 转 + // HTML 时自动给正文段落补 .reveal,源文件不用手写 class。 + processor: satteri({ features: { rawHtml: true }, hastPlugins: [markdownReveal] }), + }, +}); diff --git a/functions/api/messages.js b/functions/api/messages.js new file mode 100644 index 0000000..ce6bee6 --- /dev/null +++ b/functions/api/messages.js @@ -0,0 +1,169 @@ +/** + * Cloudflare Pages Functions + * GET /api/messages → 返回最新留言列表 + * POST /api/messages → 新增一条留言 + * 依赖绑定:环境变量 DB(D1 数据库) + */ + +const MAX_NAME = 12; +const MAX_TEXT = 120; +const MAX_LIST = 200; // 列表最多返回多少条 +const COOLDOWN = 20; // 同一 IP 两条留言的最小间隔(秒) + +/* ---------- 工具 ---------- */ +function json(data, status = 200) { + return new Response(JSON.stringify(data), { + status, + headers: { + 'Content-Type': 'application/json; charset=utf-8', + 'Cache-Control': 'no-store', + // 如果前端和接口不同域,可加上 CORS 头;同域可删掉 + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + } + }); +} + +function today() { + const d = new Date(); + const p = n => String(n).padStart(2, '0'); + return `${d.getFullYear()}.${p(d.getMonth() + 1)}.${p(d.getDate())}`; +} + +/* 清理文本:去掉控制字符、折叠多余空白 */ +function clean(str, max) { + return String(str ?? '') + .replace(/[\u0000-\u001F\u007F]/g, '') + .replace(/\s+/g, ' ') + .trim() + .slice(0, max); +} + +/* ---------- OPTIONS(预检) ---------- */ +export async function onRequestOptions() { + return new Response(null, { + status: 204, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type', + 'Access-Control-Max-Age': '86400' + } + }); +} + +/* ---------- GET:拉取列表 ---------- */ +export async function onRequestGet({ env }) { + if (!env.DB) return json({ ok: false, error: '数据库未绑定' }, 500); + + try { + const { results } = await env.DB + .prepare( + `SELECT id, name, text, time + FROM messages + ORDER BY created_at DESC, id DESC + LIMIT ?` + ) + .bind(MAX_LIST) + .all(); + + return json({ ok: true, data: results ?? [] }); + } catch (err) { + console.error('[GET /api/messages]', err); + return json({ ok: false, error: '读取失败,请稍后再试' }, 500); + } +} + +/* ---------- POST:新增留言 ---------- */ +export async function onRequestPost({ request, env }) { + if (!env.DB) return json({ ok: false, error: '数据库未绑定' }, 500); + + // 1. 解析请求体 + let body; + try { + body = await request.json(); + } catch { + return json({ ok: false, error: '请求格式错误' }, 400); + } + + // 2. 校验内容 + const name = clean(body.name, MAX_NAME) || '匿名同学'; + const text = clean(body.text, MAX_TEXT); + + if (!text) { + return json({ ok: false, error: '内容不能为空' }, 400); + } + if (String(body.text ?? '').length > 500) { + return json({ ok: false, error: '内容过长' }, 400); + } + + // 3. 简单限流:同一 IP 冷却时间内只能发一条 + const ip = + request.headers.get('CF-Connecting-IP') || + request.headers.get('X-Forwarded-For') || + ''; + const now = Math.floor(Date.now() / 1000); + + try { + if (ip) { + const last = await env.DB + .prepare( + `SELECT created_at FROM messages + WHERE ip = ? + ORDER BY created_at DESC + LIMIT 1` + ) + .bind(ip) + .first(); + + if (last && now - last.created_at < COOLDOWN) { + const wait = COOLDOWN - (now - last.created_at); + return json( + { ok: false, error: `发得太快啦,请等 ${wait} 秒` }, + 429 + ); + } + } + + // 4. 写入数据库 + const time = today(); + const res = await env.DB + .prepare( + `INSERT INTO messages (name, text, time, ip, created_at) + VALUES (?, ?, ?, ?, ?)` + ) + .bind(name, text, time, ip, now) + .run(); + + // 5. 顺手裁剪:只保留最近 500 条,避免无限增长 + // 如果不需要可以删掉这一段 + try { + await env.DB + .prepare( + `DELETE FROM messages + WHERE id NOT IN ( + SELECT id FROM messages + ORDER BY created_at DESC, id DESC + LIMIT 500 + )` + ) + .run(); + } catch (e) { + console.warn('[cleanup]', e); + } + + return json({ + ok: true, + data: { + id: res.meta?.last_row_id ?? null, + name, + text, + time + } + }); + } catch (err) { + console.error('[POST /api/messages]', err); + return json({ ok: false, error: '保存失败,请稍后再试' }, 500); + } +} \ No newline at end of file diff --git a/functions/api/submit.ts b/functions/api/submit.ts new file mode 100644 index 0000000..b1bb4c3 --- /dev/null +++ b/functions/api/submit.ts @@ -0,0 +1,480 @@ +// functions/api/submit.ts +interface Env { + GITHUB_APP_ID: string; + GITHUB_INSTALLATION_ID: string; + GITHUB_PRIVATE_KEY: string; + GITHUB_OWNER: string; + GITHUB_REPO: string; + GITHUB_BASE_BRANCH?: string; // 默认 main + CONTENT_DIR?: string; // 默认 src/content(对齐 Pages CMS 的 path) + MEDIA_DIR?: string; // 默认 public/pages/static + MEDIA_URL_PREFIX?: string; // 默认 /pages/static + SONGS_DIR?: string; // 默认 src/songs(音乐投稿的目标目录) + TURNSTILE_SECRET_KEY?: string; // Turnstile 私钥;未设置则跳过校验(本地开发) +} + +const enc = new TextEncoder(); + +// ---------- 编码/加密工具 ---------- +function b64url(bytes: Uint8Array | ArrayBuffer): string { + const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes); + let bin = ''; + const chunk = 0x8000; + for (let i = 0; i < arr.length; i += chunk) { + bin += String.fromCharCode(...arr.subarray(i, i + chunk)); + } + return btoa(bin).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); +} +const b64utf8 = (s: string) => b64url(enc.encode(s)); + +function abToBase64(buf: ArrayBuffer): string { + const arr = new Uint8Array(buf); + let bin = ''; + const chunk = 0x8000; + for (let i = 0; i < arr.length; i += chunk) bin += String.fromCharCode(...arr.subarray(i, i + chunk)); + return btoa(bin); +} + +function pemToArrayBuffer(pem: string): ArrayBuffer { + const fixed = pem.includes('\n') + ? pem + : pem.replace(/-----BEGIN [^-]+-----\s*/, '-----BEGIN PRIVATE KEY-----\n') + .replace(/\s*-----END PRIVATE KEY-----/, '\n-----END PRIVATE KEY-----'); + const b64 = fixed + .replace(/-----BEGIN [^-]+-----/, '') + .replace(/-----END [^-]+-----/, '') + .replace(/\s+/g, ''); + const bin = atob(b64); + const buf = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i); + return buf.buffer; +} + +async function makeAppJwt(appId: string, pem: string) { + const now = Math.floor(Date.now() / 1000); + const head = b64utf8(JSON.stringify({ alg: 'RS256', typ: 'JWT' })); + const body = b64utf8(JSON.stringify({ iat: now - 60, exp: now + 540, iss: appId })); + const data = `${head}.${body}`; + const key = await crypto.subtle.importKey( + 'pkcs8', pemToArrayBuffer(pem), + { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign'], + ); + const sig = await crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, enc.encode(data)); + return `${data}.${b64url(sig)}`; +} + +async function getInstallationToken(env: Env): Promise { + const jwt = await makeAppJwt(env.GITHUB_APP_ID, env.GITHUB_PRIVATE_KEY); + const res = await fetch( + `https://api.github.com/app/installations/${env.GITHUB_INSTALLATION_ID}/access_tokens`, + { + method: 'POST', + headers: { + authorization: `Bearer ${jwt}`, + accept: 'application/vnd.github+json', + 'user-agent': 'astro-chronicle-fn', + }, + }, + ); + if (!res.ok) throw new Error(`installation token failed: ${res.status} ${await res.text()}`); + return (await res.json()).token as string; +} + +// ---------- Turnstile ---------- +async function verifyTurnstile( + secret: string, + token: string, + remoteIp?: string, +): Promise { + const body = new URLSearchParams({ secret, response: token }); + if (remoteIp) body.set('remoteip', remoteIp); + + const res = await fetch( + 'https://challenges.cloudflare.com/turnstile/v0/siteverify', + { + method: 'POST', + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + body, + }, + ); + if (!res.ok) return false; + const data = (await res.json()) as { success?: boolean }; + return data.success === true; +} + +// ---------- GitHub REST ---------- +function gh(token: string) { + return async function api(path: string, init: RequestInit = {}): Promise { + const res = await fetch(`https://api.github.com${path}`, { + ...init, + headers: { + authorization: `Bearer ${token}`, + accept: 'application/vnd.github+json', + 'user-agent': 'astro-chronicle-fn', + 'content-type': 'application/json', + ...(init.headers || {}), + }, + }); + if (res.status === 404) return null; // 用于探测文件是否存在 + if (!res.ok) throw new Error(`GitHub ${path} → ${res.status}: ${await res.text()}`); + return res.json() as Promise; + }; +} + +// ---------- 业务辅助 ---------- +const yyyymmdd = (iso: string) => iso.replace(/-/g, ''); + +function extFromMime(mime: string): string { + const m = mime.toLowerCase(); + if (m.includes('png')) return 'png'; + if (m.includes('jpeg') || m.includes('jpg')) return 'jpg'; + if (m.includes('webp')) return 'webp'; + if (m.includes('gif')) return 'gif'; + if (m.includes('avif')) return 'avif'; + if (m.includes('svg')) return 'svg'; + return 'bin'; +} + +function yamlQuote(s: string): string { + // 始终用 JSON 字符串(YAML 兼容) + return JSON.stringify(s); +} + +// 生成 frontmatter + 正文(严格对齐 Pages CMS 字段) +function renderMarkdown(f: { + title: string; date: string; summary?: string; + author?: string; cover?: string; body: string; +}) { + const fm = ['---', `title: ${yamlQuote(f.title)}`, `date: ${yamlQuote(f.date)}`]; + if (f.summary) fm.push(`summary: ${yamlQuote(f.summary)}`); + if (f.author) fm.push(`author: ${yamlQuote(f.author)}`); + if (f.cover) fm.push(`cover: ${yamlQuote(f.cover)}`); + fm.push('---'); + return `${fm.join('\n')}\n\n${f.body.trim()}\n`; +} + +// ---------- 音乐投稿 ---------- +function renderSongJson(f: { + title: string; artist: string; link?: string; + note?: string; author?: string; date: string; +}) { + const obj: Record = { + title: f.title, + artist: f.artist, + date: f.date, + }; + if (f.link) obj.link = f.link; + if (f.note) obj.note = f.note; + if (f.author) obj.author = f.author; + return JSON.stringify(obj, null, 2) + '\n'; +} + +async function handleSongSubmit( + env: Env, fd: FormData, json: (data: unknown, status?: number) => Response, +): Promise { + const title = (fd.get('title') as string | null)?.trim() ?? ''; + const artist = (fd.get('artist') as string | null)?.trim() ?? ''; + const link = (fd.get('link') as string | null)?.trim() ?? ''; + const note = (fd.get('note') as string | null)?.trim() ?? ''; + const author = (fd.get('author') as string | null)?.trim() ?? ''; + const message = (fd.get('message') as string | null)?.trim() ?? ''; + + if (!title) return json({ error: '歌名不能为空' }, 400); + if (!artist) return json({ error: '歌手不能为空' }, 400); + if (title.length > 200) return json({ error: '歌名过长' }, 400); + if (artist.length > 120) return json({ error: '歌手名过长' }, 400); + if (note.length > 500) return json({ error: '备注过长' }, 400); + if (link && !/^https?:\/\//i.test(link)) { + return json({ error: '链接必须以 http:// 或 https:// 开头' }, 400); + } + + const baseBranch = env.GITHUB_BASE_BRANCH ?? 'main'; + const songsDir = env.SONGS_DIR ?? 'src/songs'; + const owner = env.GITHUB_OWNER; + const repo = env.GITHUB_REPO; + + const token = await getInstallationToken(env); + const api = gh(token); + + // 歌曲文件名:YYYYMMDD-<随机>,避免冲突 + const today = new Date(); + const pad2 = (n: number) => String(n).padStart(2, '0'); + const ymd = `${today.getFullYear()}${pad2(today.getMonth() + 1)}${pad2(today.getDate())}`; + const songPath = `${songsDir}/${ymd}-${Math.random().toString(36).slice(2, 8)}.json`; + + const content = renderSongJson({ title, artist, link, note, author, date: ymd }); + + const baseRef = await api<{ object: { sha: string } }>( + `/repos/${owner}/${repo}/git/ref/heads/${baseBranch}`, + ); + if (!baseRef) throw new Error(`分支不存在: ${baseBranch}`); + const baseCommitSha = baseRef.object.sha; + const baseCommit = await api<{ tree: { sha: string } }>( + `/repos/${owner}/${repo}/git/commits/${baseCommitSha}`, + ); + if (!baseCommit) throw new Error('无法获取 base commit'); + + const blob = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/blobs`, { + method: 'POST', + body: JSON.stringify({ content, encoding: 'utf-8' }), + }); + if (!blob) throw new Error('创建歌曲 blob 失败'); + + const newTree = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/trees`, { + method: 'POST', + body: JSON.stringify({ + base_tree: baseCommit.tree.sha, + tree: [{ path: songPath, mode: '100644', type: 'blob', sha: blob.sha }], + }), + }); + if (!newTree) throw new Error('创建 tree 失败'); + + const commitMsg = `feat(music): add "${title}" - ${artist}` + + (author ? ` by ${author}` : ''); + const newCommit = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/commits`, { + method: 'POST', + body: JSON.stringify({ + message: commitMsg, + tree: newTree.sha, + parents: [baseCommitSha], + }), + }); + if (!newCommit) throw new Error('创建 commit 失败'); + + const branch = `music/${ymd}-${Math.random().toString(36).slice(2, 7)}`; + await api(`/repos/${owner}/${repo}/git/refs`, { + method: 'POST', + body: JSON.stringify({ ref: `refs/heads/${branch}`, sha: newCommit.sha }), + }); + + const prBody = [ + '**投稿类型:** 🎵 音乐', + `**歌名:** ${title}`, + `**歌手:** ${artist}`, + author ? `**推荐人:** ${author}` : '', + link ? `**链接:** ${link}` : '', + note ? `**备注:** ${note}` : '', + '', + `**目标文件:** \`${songPath}\``, + '', + message ? `**留言:**\n\n${message}` : '', + '', + '---', + '由音乐投稿表单自动创建,请审核后合并。', + ].filter(Boolean).join('\n'); + + const pr = await api<{ html_url: string; number: number }>( + `/repos/${owner}/${repo}/pulls`, + { + method: 'POST', + body: JSON.stringify({ + title: `🎵 音乐投稿:${title} - ${artist}`, + head: branch, + base: baseBranch, + body: prBody, + }), + }, + ); + if (!pr) throw new Error('创建 PR 失败'); + + return json({ prUrl: pr.html_url, number: pr.number, file: songPath }); +} + +// ---------- 主处理 ---------- +export const onRequestPost: PagesFunction = async ({ request, env }) => { + const json = (data: unknown, status = 200) => + new Response(JSON.stringify(data), { + status, + headers: { 'content-type': 'application/json; charset=utf-8' }, + }); + + try { + // 1) 解析 multipart + const ct = request.headers.get('content-type') || ''; + if (!ct.includes('multipart/form-data')) { + return json({ error: '需要 multipart/form-data' }, 400); + } + const fd = await request.formData(); + + // 1.5) Turnstile 人机验证(配置了 secret 才启用) + const turnstileSecret = env.TURNSTILE_SECRET_KEY?.trim(); + if (turnstileSecret) { + const raw = fd.get('cf-turnstile-response'); + const token = typeof raw === 'string' ? raw.trim() : ''; + if (!token) { + return json({ error: '请先完成人机验证' }, 400); + } + const ip = request.headers.get('CF-Connecting-IP') ?? undefined; + const ok = await verifyTurnstile(turnstileSecret, token, ip); + if (!ok) { + return json({ error: '人机验证未通过,请刷新页面后重试' }, 403); + } + } + + // 1.7) 音乐投稿分支(type=music) + const submitType = (fd.get('type') as string | null)?.trim() ?? 'chronicle'; + if (submitType === 'music') { + return await handleSongSubmit(env, fd, json); + } + + const title = (fd.get('title') as string | null)?.trim() ?? ''; + const date = (fd.get('date') as string | null)?.trim() ?? ''; + const summary = (fd.get('summary') as string | null)?.trim() ?? ''; + const author = (fd.get('author') as string | null)?.trim() ?? ''; + const message = (fd.get('message') as string | null)?.trim() ?? ''; + const body = (fd.get('body') as string | null)?.trim() ?? ''; + const cover = fd.get('cover'); + + if (!title) return json({ error: '标题不能为空' }, 400); + if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) return json({ error: '日期格式应为 YYYY-MM-DD' }, 400); + if (!body) return json({ error: '正文不能为空' }, 400); + if (title.length > 200) return json({ error: '标题过长' }, 400); + if (body.length > 200_000) return json({ error: '正文过长' }, 400); + + const baseBranch = env.GITHUB_BASE_BRANCH ?? 'main'; + const contentDir = env.CONTENT_DIR ?? 'src/content'; + const mediaDir = env.MEDIA_DIR ?? 'public/pages/static'; + const mediaUrl = env.MEDIA_URL_PREFIX ?? '/pages/static'; + const owner = env.GITHUB_OWNER; + const repo = env.GITHUB_REPO; + + const token = await getInstallationToken(env); + const api = gh(token); + + // 2) 处理封面图(若有) + let coverPath: string | undefined; // 仓库内路径 + let coverUrl: string | undefined; // markdown 引用 + let coverBlob: { content: string; encoding: 'base64' } | undefined; + + if (cover instanceof File && cover.size > 0) { + if (cover.size > 5 * 1024 * 1024) return json({ error: '封面图超过 5 MB' }, 413); + if (!cover.type.startsWith('image/')) return json({ error: '封面必须是图片' }, 400); + + const ext = extFromMime(cover.type); + const base = `${yyyymmdd(date)}-cover`; + coverPath = `${mediaDir}/${base}.${ext}`; + coverUrl = `${mediaUrl}/${base}.${ext}`; + + const buf = await cover.arrayBuffer(); + coverBlob = { content: abToBase64(buf), encoding: 'base64' }; + } + + // 3) 决定文章文件名(同日冲突 → -1, -2, …) + let articleName = `${yyyymmdd(date)}.md`; + let articlePath = `${contentDir}/${articleName}`; + let n = 0; + // 注意:Contents API 的 GET 返回 404 表示不存在;gh() 已把 404 转成 null + while (await api(`/repos/${owner}/${repo}/contents/${encodeURIComponent(articlePath)}?ref=${baseBranch}`)) { + n += 1; + articleName = `${yyyymmdd(date)}-${n}.md`; + articlePath = `${contentDir}/${articleName}`; + if (n > 50) return json({ error: '同日投稿过多' }, 409); + } + + const markdown = renderMarkdown({ + title, date, summary, author, cover: coverUrl, body, + }); + + // 4) 从 base 分支拿 commit & tree + const baseRef = await api<{ object: { sha: string } }>( + `/repos/${owner}/${repo}/git/ref/heads/${baseBranch}`, + ); + if (!baseRef) throw new Error(`分支不存在: ${baseBranch}`); + const baseCommitSha = baseRef.object.sha; + + const baseCommit = await api<{ tree: { sha: string } }>( + `/repos/${owner}/${repo}/git/commits/${baseCommitSha}`, + ); + if (!baseCommit) throw new Error('无法获取 base commit'); + const baseTreeSha = baseCommit.tree.sha; + + // 5) 上传 blobs + const treeEntries: Array<{ + path: string; mode: '100644'; type: 'blob'; sha: string; + }> = []; + + // markdown blob(utf-8) + const mdBlob = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/blobs`, { + method: 'POST', + body: JSON.stringify({ content: markdown, encoding: 'utf-8' }), + }); + if (!mdBlob) throw new Error('创建 markdown blob 失败'); + treeEntries.push({ path: articlePath, mode: '100644', type: 'blob', sha: mdBlob.sha }); + + // 封面 blob(base64) + if (coverBlob && coverPath) { + const imgBlob = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/blobs`, { + method: 'POST', + body: JSON.stringify(coverBlob), + }); + if (!imgBlob) throw new Error('创建封面 blob 失败'); + treeEntries.push({ path: coverPath, mode: '100644', type: 'blob', sha: imgBlob.sha }); + } + + // 6) 建 tree / commit / 分支 + const newTree = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/trees`, { + method: 'POST', + body: JSON.stringify({ base_tree: baseTreeSha, tree: treeEntries }), + }); + if (!newTree) throw new Error('创建 tree 失败'); + + const commitMsg = `feat(chronicle): add "${title}" (${date})` + + (author ? ` by ${author}` : ''); + + const newCommit = await api<{ sha: string }>(`/repos/${owner}/${repo}/git/commits`, { + method: 'POST', + body: JSON.stringify({ + message: commitMsg, + tree: newTree.sha, + parents: [baseCommitSha], + }), + }); + if (!newCommit) throw new Error('创建 commit 失败'); + + const branch = `chronicle/${yyyymmdd(date)}-${Math.random().toString(36).slice(2, 7)}`; + await api(`/repos/${owner}/${repo}/git/refs`, { + method: 'POST', + body: JSON.stringify({ ref: `refs/heads/${branch}`, sha: newCommit.sha }), + }); + + // 7) 创建 PR + const prBody = [ + `**标题:** ${title}`, + `**日期:** ${date}`, + author ? `**记录人:** ${author}` : '', + summary ? `**摘要:** ${summary}` : '', + coverUrl ? `**封面:** \`${coverUrl}\`` : '', + '', + `**目标文件:** \`${articlePath}\``, + '', + message ? `**留言:**\n\n${message}` : '', + '', + '---', + '由 Astro 投稿表单自动创建,请审核后合并。', + ].filter(Boolean).join('\n'); + + const pr = await api<{ html_url: string; number: number }>( + `/repos/${owner}/${repo}/pulls`, + { + method: 'POST', + body: JSON.stringify({ + title: `📝 班史投稿:${title}`, + head: branch, + base: baseBranch, + body: prBody, + }), + }, + ); + if (!pr) throw new Error('创建 PR 失败'); + + return json({ + prUrl: pr.html_url, + number: pr.number, + file: articlePath, + cover: coverUrl ?? null, + }); + } catch (err: any) { + console.error(err); + return json({ error: err?.message ?? '服务异常' }, 500); + } +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..10955b7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4229 @@ +{ + "name": "class-history-template", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "class-history-template", + "version": "0.0.1", + "dependencies": { + "@astrojs/markdown-satteri": "0.4.2", + "astro": "^7.3.5" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding/-/compiler-binding-0.5.1.tgz", + "integrity": "sha512-oczyolLUl9mNrtuBuNjuvn5thpHrFLXAHAWGTRg0JDHQ8cGVsVeFekOu2uSoQGgainJIi+A3/9m0DyYwz3Nlnw==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@astrojs/compiler-binding-android-arm64": "0.5.1", + "@astrojs/compiler-binding-darwin-arm64": "0.5.1", + "@astrojs/compiler-binding-darwin-x64": "0.5.1", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.5.1", + "@astrojs/compiler-binding-linux-arm64-musl": "0.5.1", + "@astrojs/compiler-binding-linux-x64-gnu": "0.5.1", + "@astrojs/compiler-binding-linux-x64-musl": "0.5.1", + "@astrojs/compiler-binding-wasm32-wasi": "0.5.1", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.5.1", + "@astrojs/compiler-binding-win32-x64-msvc": "0.5.1" + } + }, + "node_modules/@astrojs/compiler-binding-android-arm64": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-android-arm64/-/compiler-binding-android-arm64-0.5.1.tgz", + "integrity": "sha512-nMb2nMIJtcWLNH+fV75Enmi+jp4tIOYOfsv4XtpgdOWkqc9P4uSSdK5u1xb340AzrXo5V18SxLl/nc3vcqtamQ==", + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.5.1.tgz", + "integrity": "sha512-5k4+nZ/WRt+dcVow4z7rBuI7iv9A58h/uQ91YJe1PrTivbcCkq3u2Ynx/AZJwII4CsZawBCeGpojkFjutZBhBQ==", + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.5.1.tgz", + "integrity": "sha512-0Buw+YST9Ff2EqQyhRMQujuFq/dijLw3zXWhsvI0dJ2pGrT38iVoxTEca2eBX/PfhlwkVWSRJEKO5gMqKHyeHg==", + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.5.1.tgz", + "integrity": "sha512-x5LRpyCoMKuu3INr18cn42YhwSOaRpp9b5Ny3eJJ/sWVeejC16Zeshu1JlvlSmEZACLeWxU5JM0RX6T6nI+YyA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.5.1.tgz", + "integrity": "sha512-mL7tQEuDk3rGfaKmrO63nw6WBy1TPVioQGmVyjcAr+C+a/k3SVMYBytNSMqH9mZPT/Swj30JaZ2N842Z1NnOEQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.5.1.tgz", + "integrity": "sha512-uLGc9jtxwiDe4cQyhNPQim4ECiB/YzbWlXssfLAv8r374kArfTwBHjwR2+j+XVyF71yCx5mF9YNRclRqdNBgeg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.5.1.tgz", + "integrity": "sha512-G0cywinaQUc8v1MrytvYKUX7svTDMmYtOCZfxjwKPbJi59zIqM+Ll0rWgO0GQWLZH3XoPYo19ZwlP3Xt9ep9YA==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-wasm32-wasi": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.5.1.tgz", + "integrity": "sha512-yMhLL8asmLydoAdnEZxAw6eLfNDs3YJl6jqn0pjPt6zrb2U5qIDLnii4/twThpIFODKkQ6YDpBRTOz/vSfZCxw==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.3", + "@emnapi/runtime": "1.11.3", + "@napi-rs/wasm-runtime": "^1.2.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.5.1.tgz", + "integrity": "sha512-aClIG6poFt3Wf/bZykrEAX2nAnKvBHW6RXiKUa69QjBtWH0/FOlOAjnFcxRNlhej2AMWNYFx0o+LGjwMcH8P7Q==", + "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.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.5.1.tgz", + "integrity": "sha512-/E6uBCagY70YpWqssBC+/FuniNSloeQPRgj7l3LDWiqjxIyTLnIgX1sTt18FU7jrigetpSnC9cHAM6b6IxSgPw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@astrojs/compiler-rs": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@astrojs/compiler-rs/-/compiler-rs-0.5.1.tgz", + "integrity": "sha512-1k1acnX7DepIiea9U9/Y+d1hdAFfylu1ZQQkkYgRSwBOBAsXInolyZuh/2tax+83vu/A+hOYP6P3+265RvMTvw==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-binding": "0.5.1" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@astrojs/internal-helpers/-/internal-helpers-0.11.0.tgz", + "integrity": "sha512-3rzxJ+xbo0+8YyqOzLziIN32wmsHdCjEVz2sGOpRxJ+Ben/KiLph4ItxBy1abEL+E8fkRzqjg0rfXmaHJGw9JA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.3.0", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" + } + }, + "node_modules/@astrojs/markdown-satteri": { + "version": "0.4.2", + "resolved": "https://registry.npmmirror.com/@astrojs/markdown-satteri/-/markdown-satteri-0.4.2.tgz", + "integrity": "sha512-g4QehXnB/MzxQWnSf17NciFInMqEJy9948p8cc7zGg/r7995m0Ln5PMr3Xlnj24iey1LchaoZ3SzTOa3D4P/3w==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.11.0", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "satteri": "^0.10.3" + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@astrojs/prism/-/prism-4.0.2.tgz", + "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/@astrojs/telemetry/-/telemetry-3.3.3.tgz", + "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.4.0", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "package-manager-detector": "^1.6.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@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.9", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz", + "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-arm64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmmirror.com/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz", + "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-gnu": { + "version": "0.10.5", + "resolved": "https://registry.npmmirror.com/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz", + "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-linux-x64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmmirror.com/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz", + "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@bruits/satteri-wasm32-wasi": { + "version": "0.10.5", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@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.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "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.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "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.3" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "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.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "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.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "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.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "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.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "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.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "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.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "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.4", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "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.npmmirror.com/@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.4", + "resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz", + "integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==", + "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.npmmirror.com/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@oxc-project/types": { + "version": "0.151.0", + "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.151.0.tgz", + "integrity": "sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.11.tgz", + "integrity": "sha512-A5kXfGKvKWWZE0TtPrfsvT+q4Y5d1QG8gGUzpYjGydM+fARM9MuX90PrXYXe0XbsDVgyxxNzHo6giCj90bsFNw==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.11.tgz", + "integrity": "sha512-z6cTycz+iJ4PVkuL4HHW4DfTfoeU/2nqYYuSOrTmH7yHK5Y0LCOnA03V4ZNxavyVaU1oOqUgIg2klN/s+USGOA==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.11.tgz", + "integrity": "sha512-jShvqNtP6vDC6/A5JOAzbVV+DkgHqhl/ScVCJEbt+TUY6QYz7YnXcrg3sLtFBniro0f/Ld50ZwCWA6f7KYD1nQ==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.11.tgz", + "integrity": "sha512-f2i2xiNWq1Z1l2++q2fuhZRdLAT3aqxD6vRNm1RAxpUoBcdqNB3C0s1Bt+K+PbEx2F5F4gQp6hqKkphCY/xF9w==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.11.tgz", + "integrity": "sha512-4Ir5FSOKIAMr4r0kExpt1s3bMgzJU3rA45AYOHtQpls0oNeqcYBKrWMlckrYH4KCfGLfkfn1tN1dmZPMVsdXow==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.11.tgz", + "integrity": "sha512-/gnRDM+39BROzAN/k1OZjDPnDMcZxB/0EUxKjONO5yVkNEvlsoMDrxGNKgZi/ttFriS2gwlDNzB65pvNbFOXIQ==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.11.tgz", + "integrity": "sha512-PFaK8HwvAHbaKbBcDNQihjMKYvFnA5hiENx/l5tphTDz1E0WFp32l0A7aq7lyUwGsRw/xSrNIy/gIK4thrSCrw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.11.tgz", + "integrity": "sha512-AskzJUIKRLPxkruR1wLKewGbOw+EYfU/9lOrBFj4AFrEA8hPpKFnODWNu2WLaNs0QNkEb9QIJufmVZZIL/bJlg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.11.tgz", + "integrity": "sha512-qlUGAheh2yh8afH7QBgx0PrRHN85hKnNd78x8MeMhXivuevgd8vgf6/CstOzmNKY/lLTHvNTrPy98cLnAugzJw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.11.tgz", + "integrity": "sha512-secpEad+0vCbSfn8upFySkDskv+bGPk3THSDS9Y89yc4rb4kzqHp8Dmyd9BkQW4SnhNXBZCl/6CrO//hZahNJQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.11.tgz", + "integrity": "sha512-mOVBT3dPpkWm8XBWPmU4bf+U6dYDLeMo/9ojUmis4N0L5uu10qra5vOyngZ7/PSdoE4G9KvRt4bloRxNjLas7A==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.11.tgz", + "integrity": "sha512-Is78i9A8Ui4SqcxUwFJ9uMmjDn58IbVTjFWYdQestFEgeuEmHMLGNriXnVJKkwG2YiZjw8cP0zCTyDMdDGtOOg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.11.tgz", + "integrity": "sha512-dUCXneZ87INUMyQ0D+C0HrEBNUPNXHaPmU5GTjyKTJEiussw9Kaj5Ln8UztPe4epV/ffvgNBEadksdYhmW6xJA==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.11.tgz", + "integrity": "sha512-jByxb6qfd+bH1xUd0qnfFnb17i9sWBPY2tOavJ0l3tdr3OTu+Kvtm8cd/JV5nFt657b1VqGltxg9olOEfofXWw==", + "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.11", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.11.tgz", + "integrity": "sha512-/PzKqzAJ03i19oy2ItPvyvaVjOjBCNnfaJs8yvUdGBKmiESgnrJSQ2awd81QzFbbnAmu7YO9ZnJrDCb9VSJPRA==", + "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.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "license": "MIT" + }, + "node_modules/@shikijs/core": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", + "@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.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.4.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmmirror.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.4", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", + "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", + "license": "ISC" + }, + "node_modules/am-i-vibing": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/am-i-vibing/-/am-i-vibing-0.4.0.tgz", + "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "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.npmmirror.com/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.npmmirror.com/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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/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.3.5", + "resolved": "https://registry.npmmirror.com/astro/-/astro-7.3.5.tgz", + "integrity": "sha512-1p/ernaq/RuESbM5NMjWzbO6SiebMGrGcYlGjMfBhzzgM+n/X7AUmVyw8BqW2QYCdivpsHwJBcD1fqmlTZjZHg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler-rs": "^0.5.0", + "@astrojs/internal-helpers": "0.11.0", + "@astrojs/markdown-satteri": "0.4.2", + "@astrojs/telemetry": "3.3.3", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "am-i-vibing": "^0.4.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": "^5.8.1", + "diff": "^9.0.0", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.28.0", + "find-proc": "0.2.0", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "get-tsconfig": "5.0.0-beta.4", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.3.2", + "jsonc-parser": "^3.3.1", + "magic-string": "^1.0.0", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^1.0.1", + "obug": "^3.0.0", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.4", + "shiki": "^4.0.2", + "smol-toml": "^1.8.0", + "svgo": "^4.1.0", + "tinyclip": "^1.0.1", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.5", + "unstorage": "^1.17.5", + "verkit": "^0.4.0", + "vite": "^8.0.13", + "vitefu": "^1.1.2", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^22.0.0", + "zod": "^4.5.4" + }, + "bin": { + "astro": "bin/astro.mjs" + }, + "engines": { + "node": ">=22.12.0", + "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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.9.4", + "resolved": "https://registry.npmmirror.com/devalue/-/devalue-5.9.4.tgz", + "integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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": "2.3.2", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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/find-proc": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/find-proc/-/find-proc-0.2.0.tgz", + "integrity": "sha512-a6h2nTrgB3g5Wrn4au9Ux4kMk7IJtyF6oA8uGn+mk3weLZssUtc1cp6meHIzzuW2o1srrBAxzkmXLbqjRkgB6w==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.4", + "resolved": "https://registry.npmmirror.com/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", + "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.2.0", + "resolved": "https://registry.npmmirror.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "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.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "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.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "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.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.2", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-1.4.2.tgz", + "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.6.0" + } + }, + "node_modules/magicast": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.2", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "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.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/nanoid": { + "version": "3.3.19", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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/ohash": { + "version": "2.0.12", + "resolved": "https://registry.npmmirror.com/ohash/-/ohash-2.0.12.tgz", + "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==", + "license": "MIT" + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.3", + "resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-9.3.3.tgz", + "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "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.npmmirror.com/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.8.0", + "resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "license": "MIT" + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/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.28", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "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.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.11", + "resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.2.11.tgz", + "integrity": "sha512-qpSwIyz0jHQq5qXBTNxFmE6664rJ7O+4TvPFOiOaBSrz8IOHc1koKKSqTM2H6u1UG1+TveuC6vaDHKXFOvb1Kw==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.151.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.11", + "@rolldown/binding-android-arm64": "1.2.11", + "@rolldown/binding-darwin-arm64": "1.2.11", + "@rolldown/binding-darwin-x64": "1.2.11", + "@rolldown/binding-freebsd-x64": "1.2.11", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.11", + "@rolldown/binding-linux-arm64-gnu": "1.2.11", + "@rolldown/binding-linux-arm64-musl": "1.2.11", + "@rolldown/binding-linux-ppc64-gnu": "1.2.11", + "@rolldown/binding-linux-s390x-gnu": "1.2.11", + "@rolldown/binding-linux-x64-gnu": "1.2.11", + "@rolldown/binding-linux-x64-musl": "1.2.11", + "@rolldown/binding-openharmony-arm64": "1.2.11", + "@rolldown/binding-win32-arm64-msvc": "1.2.11", + "@rolldown/binding-win32-x64-msvc": "1.2.11" + } + }, + "node_modules/satteri": { + "version": "0.10.5", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.4", + "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "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.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/shiki": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/smol-toml": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/smol-toml/-/smol-toml-1.9.0.tgz", + "integrity": "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/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/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici": { + "version": "8.11.2", + "resolved": "https://registry.npmmirror.com/undici/-/undici-8.11.2.tgz", + "integrity": "sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==", + "license": "MIT", + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/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": "0.7.5", + "resolved": "https://registry.npmmirror.com/unifont/-/unifont-0.7.5.tgz", + "integrity": "sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ohash": "^2.0.11", + "undici": "^8.0.0" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.1.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "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.5", + "resolved": "https://registry.npmmirror.com/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "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", + "@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.4.1", + "resolved": "https://registry.npmmirror.com/verkit/-/verkit-0.4.1.tgz", + "integrity": "sha512-mMVzj0TXExtVdlDEq+Mzp0eyOuyznNpFobNM3uAqe3HVm/Ps2c+u17BligMkZjZCA6EiXpoon8iRTer3iu40SQ==", + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.1", + "resolved": "https://registry.npmmirror.com/vite/-/vite-8.3.1.tgz", + "integrity": "sha512-/bvH9E9tmCXRGp2uXY3WbOldqpTwFkbha/8ANaEQ6VkxhH60KyqLwgZq6lG2y+4uT55x9+9eUHMpQ7uGnOCKjA==", + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.9", + "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", + "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.npmmirror.com/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.npmmirror.com/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.5", + "resolved": "https://registry.npmmirror.com/zod/-/zod-4.6.5.tgz", + "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/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..e05e988 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "class-history-template", + "type": "module", + "version": "0.0.1", + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/markdown-satteri": "0.4.2", + "astro": "^7.3.5" + }, + "allowScripts": { + "esbuild": true + } +} diff --git a/public/css/index.css b/public/css/index.css new file mode 100644 index 0000000..b595dd5 --- /dev/null +++ b/public/css/index.css @@ -0,0 +1,1126 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --bg: #080c17; + --panel: rgba(255, 255, 255, .045); + --panel-hi: rgba(255, 255, 255, .08); + --line: rgba(230, 192, 104, .22); + --gold: #e6c068; + --gold-soft: #f4e0a8; + --blue: #6ea8fe; + --text: #e9ecf5; + --muted: #96a0b8; +} + +html { + scroll-behavior: smooth; +} + +body { + background: var(--bg); + color: var(--text); + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", sans-serif; + line-height: 1.8; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; +} + +::selection { + background: rgba(230, 192, 104, .3); + color: #fff; +} + +/* ===== 背景 ===== */ +#stars { + position: fixed; + inset: 0; + width: 100%; + height: 100%; + z-index: 0; + pointer-events: none; +} + +.glow { + position: fixed; + border-radius: 50%; + filter: blur(90px); + opacity: .35; + z-index: 0; + pointer-events: none; +} + +.glow.g1 { + width: 520px; + height: 520px; + background: #1b3a7a; + top: -180px; + left: -160px; +} + +.glow.g2 { + width: 460px; + height: 460px; + background: #5a3d1a; + bottom: -160px; + right: -140px; +} + +.glow.g3 { + width: 380px; + height: 380px; + background: #123f45; + top: 45%; + left: 60%; + opacity: .25; +} + +.wrap { + position: relative; + z-index: 2; +} + +/* ===== 顶部进度条 ===== */ +#progress { + position: fixed; + top: 0; + left: 0; + height: 2px; + width: 0; + background: linear-gradient(90deg, var(--gold), var(--blue)); + z-index: 99; + transition: width .1s linear; + box-shadow: 0 0 12px rgba(230, 192, 104, .7); +} + +/* ===== 通用 ===== */ +.container { + max-width: 1080px; + margin: 0 auto; + padding: 0 24px; +} + +section { + padding: 110px 0; + position: relative; +} + +.sec-tag { + display: inline-block; + font-size: 12px; + letter-spacing: .35em; + color: var(--gold); + text-transform: uppercase; + margin-bottom: 14px; + padding-left: 34px; + position: relative; +} + +.sec-tag::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + width: 24px; + height: 1px; + background: var(--gold); +} + +.sec-title { + font-size: clamp(26px, 4.4vw, 40px); + font-weight: 700; + letter-spacing: .06em; + line-height: 1.35; + margin-bottom: 18px; +} + +.sec-title em { + font-style: normal; + background: linear-gradient(100deg, var(--gold-soft), var(--gold) 45%, #b08a2e); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +.sec-desc { + color: var(--muted); + max-width: 620px; + font-size: 15.5px; +} + +/* 滚动出现 */ +.reveal { + opacity: 0; + transform: translateY(34px); + transition: opacity .9s cubic-bezier(.2, .7, .2, 1), transform .9s cubic-bezier(.2, .7, .2, 1); +} + +.reveal.visible { + opacity: 1; + transform: none; +} + +/* ===== 首屏 ===== */ +.hero { + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + padding: 100px 24px 80px; + position: relative; +} + +.hero-badge { + font-size: 12px; + letter-spacing: .5em; + color: var(--gold); + border: 1px solid var(--line); + border-radius: 100px; + padding: 8px 20px 8px 24px; + margin-bottom: 34px; + background: rgba(230, 192, 104, .05); + animation: fadeDown 1s .1s both; +} + +.hero h1 { + font-size: clamp(46px, 11vw, 110px); + font-weight: 800; + letter-spacing: .04em; + line-height: 1.05; + background: linear-gradient(180deg, #fff 10%, #e8d9a8 55%, #9c7c2e 100%); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + animation: fadeDown 1.2s .25s both; + filter: drop-shadow(0 8px 40px rgba(230, 192, 104, .22)); +} + +.hero .sub { + margin-top: 22px; + font-size: clamp(14px, 2.2vw, 18px); + color: var(--muted); + letter-spacing: .18em; + animation: fadeDown 1.2s .5s both; + min-height: 1.8em; +} + +.hero .sub .cursor { + display: inline-block; + width: 1px; + height: 1em; + background: var(--gold); + vertical-align: -.12em; + margin-left: 3px; + animation: blink 1s steps(1) infinite; +} + +.hero-line { + width: 1px; + height: 70px; + margin-top: 56px; + background: linear-gradient(180deg, transparent, var(--gold)); + animation: fadeDown 1.4s .8s both; +} + +.hero-line::after { + content: ''; + display: block; + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--gold); + margin: 0 auto; + transform: translateY(-2px); + animation: pulse 2s infinite; +} + +/* 首屏:班史列表入口按钮(线下方) */ +.hero-cta { + display: inline-flex; + align-items: center; + gap: 8px; + margin-top: 26px; + font-size: 14.5px; + font-weight: 600; + letter-spacing: .14em; + color: #241a05; + text-decoration: none; + background: linear-gradient(135deg, #f4e0a8, #e6c068 55%, #d3a94b); + border: none; + border-radius: 999px; + padding: 12px 34px; + cursor: pointer; + box-shadow: 0 10px 26px rgba(230, 192, 104, .25); + animation: fadeDown 1.4s 1s both; + transition: transform .2s ease, box-shadow .2s ease, filter .2s ease; +} + +.hero-cta:hover { + transform: translateY(-2px); + box-shadow: 0 14px 32px rgba(230, 192, 104, .38); + filter: brightness(1.05); +} + +.hero-cta:active { + transform: translateY(0); +} + +.hero-nav { + display: flex; + gap: 16px; + margin-top: 24px; + justify-content: center; +} + +.hero-nav .nav-link { + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 13.5px; + letter-spacing: .1em; + color: var(--gold); + text-decoration: none; + padding: 7px 16px; + border-radius: 100px; + border: 1px solid var(--line); + background: rgba(230, 192, 104, .05); + transition: .35s; +} + +.hero-nav .nav-link:hover { + background: var(--gold); + color: #151006; + transform: translateX(-3px); +} + +@keyframes blink { + + 0%, + 50% { + opacity: 1 + } + + 51%, + 100% { + opacity: 0 + } +} + +@keyframes pulse { + + 0%, + 100% { + opacity: .4; + transform: translateY(-2px) scale(1) + } + + 50% { + opacity: 1; + transform: translateY(-2px) scale(1.6) + } +} + +@keyframes fadeDown { + from { + opacity: 0; + transform: translateY(-18px) + } + + to { + opacity: 1; + transform: none + } +} + +/* ===== 简介 + 数据 ===== */ +.intro-grid { + display: grid; + grid-template-columns: 1.15fr .85fr; + gap: 56px; + align-items: center; +} + +.intro-text p { + color: #c3cad9; + font-size: 16px; + margin-bottom: 18px; +} + +.intro-text p:first-child::first-letter { + font-size: 2.6em; + float: left; + line-height: .9; + margin: 6px 12px 0 0; + color: var(--gold); + font-weight: 700; +} + +.stats { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +.stat { + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 16px; + padding: 24px 20px; + text-align: center; + transition: .4s; + backdrop-filter: blur(8px); +} + +.stat:hover { + background: var(--panel-hi); + transform: translateY(-4px); + border-color: var(--line); +} + +.stat b { + display: block; + font-size: clamp(26px, 4vw, 36px); + font-weight: 800; + background: linear-gradient(180deg, #fff, var(--gold)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + line-height: 1.2; +} + +.stat span { + font-size: 12.5px; + color: var(--muted); + letter-spacing: .12em; +} + +/* ===== 时间轴 ===== */ +.timeline { + position: relative; + margin-top: 64px; + padding: 10px 0; +} + +.timeline::before { + content: ''; + position: absolute; + left: 50%; + top: 0; + bottom: 0; + width: 1px; + background: linear-gradient(180deg, transparent, rgba(230, 192, 104, .55) 12%, rgba(230, 192, 104, .55) 88%, transparent); + transform: translateX(-.5px); +} + +.tl-item { + position: relative; + width: 50%; + padding: 0 46px 56px 0; + text-align: right; +} + +.tl-item:nth-child(even) { + margin-left: 50%; + padding: 0 0 56px 46px; + text-align: left; +} + +.tl-item:last-child { + padding-bottom: 0; +} + +.tl-dot { + position: absolute; + top: 10px; + right: -6.5px; + width: 13px; + height: 13px; + border-radius: 50%; + background: var(--bg); + border: 2px solid var(--gold); + box-shadow: 0 0 0 4px rgba(230, 192, 104, .08); + transition: .4s; +} + +.tl-item:nth-child(even) .tl-dot { + left: -6.5px; + right: auto; +} + +.tl-item:hover .tl-dot { + background: var(--gold); + box-shadow: 0 0 16px rgba(230, 192, 104, .9); +} + +.tl-card { + display: inline-block; + text-align: left; + max-width: 420px; + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 16px; + padding: 22px 24px; + transition: .45s cubic-bezier(.2, .7, .2, 1); +} + +.tl-item:hover .tl-card { + background: var(--panel-hi); + border-color: var(--line); + transform: translateY(-4px); + box-shadow: 0 18px 40px -20px rgba(0, 0, 0, .9); +} + +.tl-date { + font-size: 12px; + letter-spacing: .2em; + color: var(--gold); + font-weight: 600; + margin-bottom: 8px; +} + +.tl-card h3 { + font-size: 18px; + font-weight: 700; + margin-bottom: 8px; + letter-spacing: .03em; +} + +.tl-card p { + font-size: 14.5px; + color: var(--muted); + line-height: 1.85; +} + +/* ===== 人物卡片 ===== */ +.people { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 18px; + margin-top: 56px; +} + +.person { + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 18px; + padding: 28px 22px; + text-align: center; + transition: .45s cubic-bezier(.2, .7, .2, 1); + position: relative; + overflow: hidden; +} + +.person::after { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 50% 0%, rgba(230, 192, 104, .16), transparent 65%); + opacity: 0; + transition: .5s; +} + +.person:hover { + transform: translateY(-6px); + border-color: var(--line); + background: var(--panel-hi); +} + +.person:hover::after { + opacity: 1; +} + +.avatar { + width: 62px; + height: 62px; + margin: 0 auto 16px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 24px; + background: linear-gradient(140deg, rgba(230, 192, 104, .22), rgba(110, 168, 254, .18)); + border: 1px solid var(--line); +} + +.person h3 { + font-size: 16px; + font-weight: 700; + margin-bottom: 4px; + position: relative; +} + +.person .role { + font-size: 12px; + letter-spacing: .18em; + color: var(--gold); + position: relative; +} + +.person .quote { + font-size: 13px; + color: var(--muted); + margin-top: 12px; + position: relative; + line-height: 1.7; +} + +/* ===== 荣誉 ===== */ +.honors { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 16px; + margin-top: 56px; +} + +.honor { + display: flex; + gap: 16px; + align-items: flex-start; + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 16px; + padding: 22px; + transition: .4s; +} + +.honor:hover { + background: var(--panel-hi); + border-color: var(--line); + transform: translateX(4px); +} + +.honor .medal { + flex: 0 0 42px; + height: 42px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 19px; + background: rgba(230, 192, 104, .12); + border: 1px solid var(--line); +} + +.honor h4 { + font-size: 15px; + font-weight: 700; + margin-bottom: 3px; +} + +.honor p { + font-size: 13px; + color: var(--muted); +} + +/* ===== 记忆墙 ===== */ +.gallery { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 14px; + margin-top: 56px; +} + +.photo { + aspect-ratio: 1/1; + border-radius: 16px; + position: relative; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, .07); + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(150deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .015)); + transition: .5s cubic-bezier(.2, .7, .2, 1); + cursor: pointer; +} + +.photo:nth-child(3n) { + background: linear-gradient(150deg, rgba(230, 192, 104, .1), rgba(255, 255, 255, .015)); +} + +.photo:nth-child(4n) { + background: linear-gradient(150deg, rgba(110, 168, 254, .1), rgba(255, 255, 255, .015)); +} + +.photo:hover { + transform: scale(1.035); + border-color: var(--line); +} + +.photo span { + font-size: 13px; + color: var(--muted); + letter-spacing: .1em; + text-align: center; + padding: 0 12px; + transition: .4s; +} + +.photo:hover span { + color: var(--gold-soft); +} + +.photo::before { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 50% 120%, rgba(230, 192, 104, .18), transparent 60%); + opacity: 0; + transition: .5s; +} + +.photo:hover::before { + opacity: 1; +} + +/* ===== 留言墙 ===== */ +.msg-form { + display: grid; + grid-template-columns: 200px 1fr auto; + gap: 12px; + margin-top: 48px; + align-items: stretch; +} + +.msg-form input, +.msg-form textarea { + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .1); + border-radius: 14px; + padding: 14px 18px; + color: var(--text); + font-family: inherit; + font-size: 14.5px; + outline: none; + transition: .3s; + resize: none; +} + +.msg-form input:focus, +.msg-form textarea:focus { + border-color: var(--line); + background: var(--panel-hi); + box-shadow: 0 0 0 4px rgba(230, 192, 104, .07); +} + +.msg-form textarea { + min-height: 52px; + max-height: 140px; + line-height: 1.6; +} + +.msg-form button { + background: linear-gradient(140deg, var(--gold), #b8912f); + border: none; + border-radius: 14px; + padding: 0 30px; + cursor: pointer; + font-family: inherit; + font-size: 14.5px; + font-weight: 700; + color: #1a1405; + letter-spacing: .12em; + transition: .35s; +} + +.msg-form button:hover { + filter: brightness(1.12); + transform: translateY(-2px); + box-shadow: 0 12px 26px -12px rgba(230, 192, 104, .8); +} + +.msg-form button:active { + transform: translateY(0); +} + +.msg-form button:disabled { + opacity: .6; + cursor: not-allowed; + transform: none; + box-shadow: none; + filter: none; +} + +.msg-list { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 14px; + margin-top: 28px; +} + +.msg { + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 16px; + padding: 20px; + position: relative; + animation: pop .5s cubic-bezier(.2, .9, .3, 1.3) both; +} + +@keyframes pop { + from { + opacity: 0; + transform: scale(.94) translateY(10px) + } + + to { + opacity: 1; + transform: none + } +} + +.msg .who { + font-size: 12px; + letter-spacing: .14em; + color: var(--gold); + margin-bottom: 8px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; +} + +.msg .who time { + font-size: 11px; + color: #66708a; + letter-spacing: 0; +} + +.msg .body { + font-size: 14.5px; + color: #c9d0de; + line-height: 1.8; + word-break: break-word; +} + +/* ===== 页脚 ===== */ +footer { + text-align: center; + padding: 80px 24px 60px; + border-top: 1px solid rgba(255, 255, 255, .06); + position: relative; + z-index: 2; +} + +footer .sig { + font-size: clamp(18px, 3vw, 24px); + font-weight: 700; + letter-spacing: .14em; + background: linear-gradient(100deg, var(--gold-soft), var(--gold)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + margin-bottom: 14px; +} + +footer p { + color: var(--muted); + font-size: 13px; + letter-spacing: .14em; +} + +footer .small { + margin-top: 26px; + font-size: 12px; + color: #4c566b; + letter-spacing: .1em; +} + +/* 回到顶部 */ +#top { + position: fixed; + right: 24px; + bottom: 24px; + width: 46px; + height: 46px; + border-radius: 50%; + background: rgba(230, 192, 104, .12); + border: 1px solid var(--line); + color: var(--gold); + font-size: 18px; + cursor: pointer; + z-index: 50; + opacity: 0; + pointer-events: none; + transition: .4s; + backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; +} + +#top.show { + opacity: 1; + pointer-events: auto; +} + +#top:hover { + background: var(--gold); + color: #151006; + transform: translateY(-3px); +} + +/* ============================================================ + 页眉 / 顶部导航 + ============================================================ */ +.topbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 60; + + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + + padding: 14px 28px; + + background: rgba(8, 12, 23, 0); + backdrop-filter: blur(0px); + -webkit-backdrop-filter: blur(0px); + border-bottom: 1px solid rgba(255, 255, 255, 0); + + transition: + background 0.4s ease, + backdrop-filter 0.4s ease, + border-color 0.4s ease, + padding 0.4s ease; +} + +/* 滚动后「实心化」 */ +.topbar.scrolled { + padding: 10px 28px; + background: rgba(8, 12, 23, 0.72); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + border-bottom-color: rgba(255, 255, 255, 0.06); +} + +/* ---- 左侧标识 ---- */ +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + flex: 0 0 auto; /* 品牌区不参与收缩 */ + text-decoration: none; + color: var(--gold-soft, #f4e0a8); + font-size: 13.5px; + letter-spacing: 0.14em; + white-space: nowrap; +} + +.brand-mark { + display: grid; + place-items: center; + width: 30px; + height: 30px; + border-radius: 50%; + border: 1px solid rgba(230, 192, 104, 0.35); + background: rgba(230, 192, 104, 0.1); + color: #e6c068; + font-size: 12px; + font-weight: 700; + letter-spacing: 0; + box-shadow: 0 0 18px rgba(230, 192, 104, 0.18); + transition: 0.35s; +} + +.brand:hover .brand-mark { + background: #e6c068; + color: #151006; + box-shadow: 0 0 26px rgba(230, 192, 104, 0.45); +} + +/* ---- 右侧导航 ---- */ +.topnav { + display: flex; + align-items: center; + justify-content: flex-start; /* 滚动容器用 flex-start,溢出时左侧项仍可达 */ + gap: 4px; + + flex: 1 1 auto; /* 占满剩余空间 */ + min-width: 0; /* ★ 关键:允许在 flex 容器内收缩 */ + + overflow-x: auto; + overflow-y: hidden; + overscroll-behavior-x: contain; + -webkit-overflow-scrolling: touch; + + scrollbar-width: none; + -ms-overflow-style: none; +} + +.topnav::-webkit-scrollbar { + display: none; +} + +/* ★ 空间足够时把整组推到最右;溢出时 auto margin 自动归零,第一项依然从最左侧开始 */ +.topnav > a:first-child { + margin-left: auto; +} + +.topnav a { + flex: 0 0 auto; /* 标签不被压缩 */ + padding: 7px 12px; + border-radius: 100px; + font-size: 13px; + letter-spacing: 0.08em; + color: #96a0b8; + text-decoration: none; + white-space: nowrap; + transition: + color 0.3s, + background 0.3s; +} + +.topnav a:hover { + color: #f4e0a8; + background: rgba(255, 255, 255, 0.05); +} + +.topnav a.nav-cta { + margin-left: 6px; + color: #e6c068; + border: 1px solid rgba(230, 192, 104, 0.28); + background: rgba(230, 192, 104, 0.06); +} + +.topnav a.nav-cta:hover { + background: #e6c068; + color: #151006; +} + +/* ---- 锚点跳转时不被页眉盖住 ---- */ +section[id] { + scroll-margin-top: 88px; +} + +/* ---- 首屏给页眉让出空间 ---- */ +.hero { + padding-top: 92px; +} + +/* ============================================================ + 响应式 + ============================================================ */ +@media (max-width:860px) { + .intro-grid { + grid-template-columns: 1fr; + gap: 36px; + } + + .msg-form { + grid-template-columns: 1fr; + } + + .msg-form button { + padding: 14px; + } +} + +@media (max-width: 720px) { + + /* ---- 页眉 ---- */ + .topbar, + .topbar.scrolled { + padding: 10px 12px; + gap: 10px; + } + + .brand-text { + display: none; + } + + .topnav { + /* 保留 flex-start:滚动容器里若用 flex-end, + 内容溢出时左侧项会被推出可视区且滚不回来 */ + justify-content: flex-start; + + /* 右侧渐隐,提示「还能横向滑动」 */ + -webkit-mask-image: linear-gradient( + 90deg, #000 0, #000 calc(100% - 20px), transparent 100% + ); + mask-image: linear-gradient( + 90deg, #000 0, #000 calc(100% - 20px), transparent 100% + ); + } + + /* ★ 手机端:菜单靠右对齐。 + 空间足够 → auto margin 吃掉剩余空间,整组贴右; + 空间不足 → auto margin 归零,从第一项开始正常横向滚动 */ + .topnav > a:first-child { + margin-left: auto; + } + + .topnav a { + padding: 6px 10px; + font-size: 12.5px; + } + + .topnav a.nav-cta { + margin-left: 4px; + margin-right: 4px; /* 滚到最右时留点呼吸感 */ + } + + section[id] { + scroll-margin-top: 72px; + } + + .hero { + padding-top: 80px; + } + + /* ---- 正文 ---- */ + section { + padding: 80px 0; + } + + .timeline::before { + left: 6px; + } + + .tl-item, + .tl-item:nth-child(even) { + width: 100%; + margin-left: 0; + padding: 0 0 44px 34px; + text-align: left; + } + + .tl-dot, + .tl-item:nth-child(even) .tl-dot { + left: .5px; + right: auto; + } + + .tl-card { + max-width: 100%; + } + + .stats { + grid-template-columns: 1fr 1fr; + gap: 12px; + } + + .stat { + padding: 18px 12px; + } + + .gallery { + grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); + gap: 10px; + } +} + +@media (prefers-reduced-motion: reduce) { + .topbar { + transition: none; + } +} diff --git a/public/css/pages.css b/public/css/pages.css new file mode 100644 index 0000000..2020417 --- /dev/null +++ b/public/css/pages.css @@ -0,0 +1,600 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --bg: #080c17; + --panel: rgba(255, 255, 255, .045); + --panel-hi: rgba(255, 255, 255, .08); + --line: rgba(230, 192, 104, .22); + --gold: #e6c068; + --gold-soft: #f4e0a8; + --blue: #6ea8fe; + --text: #e9ecf5; + --muted: #96a0b8; +} + +html { + scroll-behavior: smooth; +} + +body { + background: var(--bg); + color: var(--text); + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", sans-serif; + line-height: 1.8; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; +} + +::selection { + background: rgba(230, 192, 104, .3); + color: #fff; +} + +/* ===== 背景 ===== */ +#stars { + position: fixed; + inset: 0; + width: 100%; + height: 100%; + z-index: 0; + pointer-events: none; +} + +.glow { + position: fixed; + border-radius: 50%; + filter: blur(90px); + opacity: .35; + z-index: 0; + pointer-events: none; +} + +.glow.g1 { + width: 520px; + height: 520px; + background: #1b3a7a; + top: -180px; + left: -160px; +} + +.glow.g2 { + width: 460px; + height: 460px; + background: #5a3d1a; + bottom: -160px; + right: -140px; +} + +.glow.g3 { + width: 380px; + height: 380px; + background: #123f45; + top: 45%; + left: 60%; + opacity: .25; +} + +.wrap { + position: relative; + z-index: 2; +} + +/* ===== 顶部进度条 ===== */ +#progress { + position: fixed; + top: 0; + left: 0; + height: 2px; + width: 0; + background: linear-gradient(90deg, var(--gold), var(--blue)); + z-index: 99; + transition: width .1s linear; + box-shadow: 0 0 12px rgba(230, 192, 104, .7); +} + +/* ===== 顶部导航 ===== */ +.topbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 60; + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 14px 28px; + background: rgba(8, 12, 23, .62); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + border-bottom: 1px solid rgba(255, 255, 255, .05); +} + +.back { + display: inline-flex; + align-items: center; + gap: 8px; + font-size: 13.5px; + letter-spacing: .1em; + color: var(--gold); + text-decoration: none; + padding: 7px 16px; + border-radius: 100px; + border: 1px solid var(--line); + background: rgba(230, 192, 104, .05); + transition: .35s; +} + +.back:hover { + background: var(--gold); + color: #151006; + transform: translateX(-3px); +} + +.nav-tag { + font-size: 12px; + letter-spacing: .35em; + color: var(--muted); +} + +.topbar-actions { + display: flex; + align-items: center; + gap: 12px; + margin-left: auto; +} + +@media (max-width:600px) { + .topbar { + padding: 12px 16px; + } + + .nav-tag { + display: none; + } +} + +/* ===== 通用 ===== */ +.container { + max-width: 820px; + margin: 0 auto; + padding: 0 24px; +} + +.reveal { + opacity: 0; + transform: translateY(30px); + transition: opacity .9s cubic-bezier(.2, .7, .2, 1), transform .9s cubic-bezier(.2, .7, .2, 1); +} + +.reveal.visible { + opacity: 1; + transform: none; +} + +/* ===== 文章头部 ===== */ +.post-head { + padding: 150px 0 46px; + text-align: center; + position: relative; +} + +.post-date { + display: inline-block; + font-size: 12px; + letter-spacing: .4em; + color: var(--gold); + margin-bottom: 22px; + padding: 8px 22px; + border-radius: 100px; + border: 1px solid var(--line); + background: rgba(230, 192, 104, .05); + animation: fadeDown 1s .05s both; +} + +.post-head h1 { + font-size: clamp(30px, 6.2vw, 52px); + font-weight: 800; + letter-spacing: .05em; + line-height: 1.25; + background: linear-gradient(180deg, #fff 10%, #e8d9a8 60%, #9c7c2e 100%); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + animation: fadeDown 1.1s .18s both; + filter: drop-shadow(0 8px 34px rgba(230, 192, 104, .2)); +} + +.post-sub { + margin-top: 20px; + font-size: clamp(14px, 2vw, 16.5px); + color: var(--muted); + letter-spacing: .1em; + animation: fadeDown 1.1s .34s both; +} + +.post-meta { + margin-top: 28px; + display: flex; + justify-content: center; + align-items: center; + gap: 14px; + flex-wrap: wrap; + font-size: 12.5px; + letter-spacing: .14em; + color: #66708a; + animation: fadeDown 1.1s .5s both; +} + +.post-meta i { + font-style: normal; + color: rgba(230, 192, 104, .5); +} + +.head-line { + width: 1px; + height: 64px; + margin: 46px auto 0; + background: linear-gradient(180deg, transparent, var(--gold)); + animation: fadeDown 1.3s .62s both; +} + +.head-line::after { + content: ''; + display: block; + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--gold); + margin: 0 auto; + transform: translateY(-2px); + animation: pulse 2s infinite; +} + +@keyframes fadeDown { + from { + opacity: 0; + transform: translateY(-16px) + } + + to { + opacity: 1; + transform: none + } +} + +@keyframes pulse { + + 0%, + 100% { + opacity: .4; + transform: translateY(-2px) scale(1) + } + + 50% { + opacity: 1; + transform: translateY(-2px) scale(1.6) + } +} + +/* ===== 封面图 ===== */ +.cover { + margin: 0 auto 56px; + max-width: 980px; + padding: 0 24px; +} + +.cover .ph { + aspect-ratio: 21/9; + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, .07); + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(150deg, rgba(230, 192, 104, .1), rgba(110, 168, 254, .06) 55%, rgba(255, 255, 255, .015)); + color: var(--muted); + font-size: 13px; + letter-spacing: .2em; + position: relative; + overflow: hidden; +} + +.cover .ph::after { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 50% 130%, rgba(230, 192, 104, .16), transparent 60%); +} + +/* ===== 正文 ===== */ +.post-body { + padding-bottom: 20px; +} + +.post-body p { + font-size: 16.5px; + line-height: 2.05; + color: #c3cad9; + margin-bottom: 22px; +} + +.post-body h2 { + font-size: clamp(19px, 3vw, 23px); + font-weight: 700; + letter-spacing: .04em; + margin: 52px 0 18px; + padding-left: 18px; + position: relative; +} + +.post-body h2::before { + content: ''; + position: absolute; + left: 0; + top: .42em; + bottom: .28em; + width: 3px; + border-radius: 3px; + background: linear-gradient(180deg, var(--gold), rgba(230, 192, 104, .12)); +} + +.post-body strong { + color: var(--gold-soft); + font-weight: 700; +} + +.post-body blockquote { + margin: 30px 0; + padding: 20px 26px; + background: var(--panel); + border-left: 2px solid var(--gold); + border-radius: 0 16px 16px 0; + color: var(--gold-soft); + font-size: 15.5px; + line-height: 1.95; + position: relative; +} + +.post-body blockquote::before { + content: '“'; + position: absolute; + right: 18px; + top: -6px; + font-size: 56px; + color: rgba(230, 192, 104, .14); + font-family: Georgia, serif; + line-height: 1; +} + +.post-body ul { + margin: 22px 0 26px; + padding-left: 4px; + list-style: none; +} + +.post-body li { + font-size: 16px; + color: #c3cad9; + line-height: 1.95; + padding-left: 24px; + position: relative; + margin-bottom: 10px; +} + +.post-body li::before { + content: ''; + position: absolute; + left: 4px; + top: .72em; + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--gold); + opacity: .7; +} + +.figure { + margin: 34px 0; +} + +.figure .ph { + aspect-ratio: 16/9; + border-radius: 18px; + border: 1px solid rgba(255, 255, 255, .07); + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(150deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .015)); + color: var(--muted); + font-size: 13px; + letter-spacing: .16em; + transition: .5s; +} + +.figure .ph:hover { + border-color: var(--line); + transform: translateY(-3px); +} + +.figure figcaption { + text-align: center; + font-size: 12.5px; + color: #66708a; + letter-spacing: .12em; + margin-top: 12px; +} + +/* 分隔符 */ +.divider { + display: flex; + align-items: center; + justify-content: center; + gap: 14px; + margin: 56px 0; + color: rgba(230, 192, 104, .5); + font-size: 12px; + letter-spacing: .4em; +} + +.divider::before, +.divider::after { + content: ''; + height: 1px; + flex: 1; + max-width: 120px; + background: linear-gradient(90deg, transparent, var(--line), transparent); +} + +/* ===== 上下篇 ===== */ +.post-nav { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + margin-top: 30px; + padding-top: 44px; + border-top: 1px solid rgba(255, 255, 255, .06); +} + +.post-nav a { + display: block; + text-decoration: none; + background: var(--panel); + border: 1px solid rgba(255, 255, 255, .07); + border-radius: 16px; + padding: 20px 22px; + transition: .45s cubic-bezier(.2, .7, .2, 1); +} + +.post-nav a:hover { + background: var(--panel-hi); + border-color: var(--line); + transform: translateY(-4px); + box-shadow: 0 18px 40px -20px rgba(0, 0, 0, .9); +} + +.post-nav .label { + font-size: 11.5px; + letter-spacing: .24em; + color: var(--gold); + margin-bottom: 7px; +} + +.post-nav .title { + font-size: 15px; + color: var(--text); + font-weight: 600; + letter-spacing: .03em; +} + +.post-nav .next { + text-align: right; +} + +@media (max-width:600px) { + .post-nav { + grid-template-columns: 1fr; + } + + .post-nav .next { + text-align: left; + } +} + +/* ===== 页脚 ===== */ +footer { + text-align: center; + padding: 80px 24px 60px; + margin-top: 80px; + border-top: 1px solid rgba(255, 255, 255, .06); + position: relative; + z-index: 2; +} + +footer .sig { + font-size: clamp(17px, 3vw, 22px); + font-weight: 700; + letter-spacing: .14em; + background: linear-gradient(100deg, var(--gold-soft), var(--gold)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + margin-bottom: 12px; +} + +footer p { + color: var(--muted); + font-size: 13px; + letter-spacing: .12em; +} + +footer .small { + margin-top: 22px; + font-size: 12px; + color: #4c566b; + letter-spacing: .1em; +} + +/* 回到顶部 */ +#top { + position: fixed; + right: 24px; + bottom: 24px; + width: 46px; + height: 46px; + border-radius: 50%; + background: rgba(230, 192, 104, .12); + border: 1px solid var(--line); + color: var(--gold); + font-size: 18px; + cursor: pointer; + z-index: 50; + opacity: 0; + pointer-events: none; + transition: .4s; + backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; +} + +#top.show { + opacity: 1; + pointer-events: auto; +} + +#top:hover { + background: var(--gold); + color: #151006; + transform: translateY(-3px); +} + +.hero-nav { + display: flex; + gap: 16px; + margin-top: 24px; +} + +.hero-nav .nav-link { + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 13.5px; + letter-spacing: .1em; + color: var(--gold); + text-decoration: none; + padding: 7px 16px; + border-radius: 100px; + border: 1px solid var(--line); + background: rgba(230, 192, 104, .05); + transition: .35s; +} + +.hero-nav .nav-link:hover { + background: var(--gold); + color: #151006; + transform: translateX(-3px); +} \ No newline at end of file diff --git a/public/js/index.js b/public/js/index.js new file mode 100644 index 0000000..6e45740 --- /dev/null +++ b/public/js/index.js @@ -0,0 +1,282 @@ +/* ================= 星空背景 ================= */ +(function () { + const canvas = document.getElementById('stars'); + const ctx = canvas.getContext('2d'); + let w, h, stars = [], dpr = Math.min(window.devicePixelRatio || 1, 2); + + function resize() { + w = canvas.width = window.innerWidth * dpr; + h = canvas.height = window.innerHeight * dpr; + canvas.style.width = window.innerWidth + 'px'; + canvas.style.height = window.innerHeight + 'px'; + const count = Math.min(160, Math.floor(window.innerWidth / 9)); + stars = Array.from({ length: count }, () => ({ + x: Math.random() * w, + y: Math.random() * h, + r: (Math.random() * 1.4 + .3) * dpr, + a: Math.random() * .6 + .15, + s: Math.random() * .0009 + .0003, + dy: Math.random() * .05 + .015 + })); + } + + let t = 0; + function draw() { + ctx.clearRect(0, 0, w, h); + t += 1; + for (const s of stars) { + const alpha = s.a + Math.sin(t * s.s * 12) * .25; + ctx.beginPath(); + ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); + ctx.fillStyle = 'rgba(255,244,214,' + Math.max(0.03, Math.min(1, alpha)) + ')'; + ctx.fill(); + s.y += s.dy * dpr; + if (s.y > h + 5) { s.y = -5; s.x = Math.random() * w; } + } + requestAnimationFrame(draw); + } + + resize(); + window.addEventListener('resize', resize); + draw(); +})(); + +/* ================= 打字机 ================= */ +(function () { + const el = document.getElementById('typed'); + const lines = [ + '我们的故事,从那年秋天开始', + '三年同窗,一生朋友', + '愿此去前程似锦,再相逢依然少年' + ]; + let li = 0, ci = 0, deleting = false; + + function tick() { + const cur = lines[li]; + if (!deleting) { + ci++; + el.textContent = cur.slice(0, ci); + if (ci === cur.length) { + deleting = true; + return setTimeout(tick, 1800); + } + return setTimeout(tick, 95); + } else { + ci--; + el.textContent = cur.slice(0, ci); + if (ci === 0) { + deleting = false; + li = (li + 1) % lines.length; + return setTimeout(tick, 350); + } + return setTimeout(tick, 40); + } + } + setTimeout(tick, 900); +})(); + +/* ================= 滚动出现 ================= */ +(function () { + const els = document.querySelectorAll('.reveal'); + if (!('IntersectionObserver' in window)) { + els.forEach(e => e.classList.add('visible')); + return; + } + const io = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const el = entry.target; + // 延时随文档顺序单调不减(不能取模:那样第 7 个延时回到 0, + // 会先于它上面的元素出现),到第 6 级后不再累加。 + const idx = Array.from(el.parentElement.children).indexOf(el); + const delay = Math.min(idx, 6) * 70; + setTimeout(() => el.classList.add('visible'), delay); + io.unobserve(el); + } + }); + }, { threshold: .12, rootMargin: '0px 0px -60px 0px' }); + els.forEach(e => io.observe(e)); +})(); + +/* ================= 数字滚动 ================= */ +(function () { + const nums = document.querySelectorAll('[data-count]'); + const io = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (!entry.isIntersecting) return; + const el = entry.target; + const target = parseInt(el.dataset.count, 10); + const suffix = target === 999 ? '+' : ''; + let start = null; + const dur = 1600; + function step(ts) { + if (!start) start = ts; + const p = Math.min((ts - start) / dur, 1); + const eased = 1 - Math.pow(1 - p, 3); + el.textContent = Math.floor(target * eased) + suffix; + if (p < 1) requestAnimationFrame(step); + else el.textContent = target + suffix; + } + requestAnimationFrame(step); + io.unobserve(el); + }); + }, { threshold: .5 }); + nums.forEach(n => io.observe(n)); +})(); + +/* ================= 进度条 + 回顶部 ================= */ +(function () { + const bar = document.getElementById('progress'); + const top = document.getElementById('top'); + function onScroll() { + const st = window.scrollY || document.documentElement.scrollTop; + const max = document.documentElement.scrollHeight - window.innerHeight; + bar.style.width = (max > 0 ? (st / max) * 100 : 0) + '%'; + top.classList.toggle('show', st > 500); + } + window.addEventListener('scroll', onScroll, { passive: true }); + onScroll(); + top.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })); +})(); + +/* ================= 留言墙 ================= */ +(function () { + const API = '/api/messages'; + + const list = document.getElementById('msgList'); + const nameI = document.getElementById('msgName'); + const textI = document.getElementById('msgText'); + const btn = document.getElementById('msgSend'); + + let sending = false; + + const BTN_TEXT = '留 言'; + // 跟随页面渲染出的占位符(班级名由 src/site.config.ts 注入),避免在此硬编码 + const PLACEHOLDER = textI.placeholder || '想说点什么……'; + + function setTip(tip) { + list.innerHTML = ''; + const p = document.createElement('p'); + p.style.cssText = 'color:#66708a;font-size:14px;'; + p.textContent = tip; + list.appendChild(p); + } + + function render(data) { + list.innerHTML = ''; + if (!data || !data.length) { + setTip('还没有留言,来做第一个吧~'); + return; + } + data.forEach((m, i) => { + const d = document.createElement('div'); + d.className = 'msg'; + d.style.animationDelay = Math.min(i * 0.05, 0.4) + 's'; + + const who = document.createElement('div'); + who.className = 'who'; + const span = document.createElement('span'); + span.textContent = m.name; + const time = document.createElement('time'); + time.textContent = m.time; + who.append(span, time); + + const body = document.createElement('div'); + body.className = 'body'; + body.textContent = m.text; + + d.append(who, body); + list.appendChild(d); + }); + } + + async function load() { + setTip('加载中…'); + try { + const res = await fetch(API, { headers: { Accept: 'application/json' } }); + const data = await res.json().catch(() => ({})); + if (!res.ok || !data.ok) throw new Error(data.error || '加载失败'); + render(data.data); + } catch (err) { + setTip('留言加载失败,请刷新重试~'); + } + } + + async function send() { + if (sending) return; + + const name = nameI.value.trim(); + const text = textI.value.trim(); + + if (!text) { + textI.focus(); + textI.placeholder = '至少写一句话呀~'; + setTimeout(() => { textI.placeholder = PLACEHOLDER; }, 2000); + return; + } + + sending = true; + btn.disabled = true; + btn.textContent = '发送中…'; + + try { + const res = await fetch(API, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, text }) + }); + const data = await res.json().catch(() => ({})); + if (!res.ok || !data.ok) throw new Error(data.error || '发送失败'); + + textI.value = ''; + btn.textContent = BTN_TEXT; + btn.disabled = false; + sending = false; + + // 直接把新留言插到最前面,不用重新拉全量 + if (data.data) { + const first = list.querySelector('.msg'); + const d = document.createElement('div'); + d.className = 'msg'; + d.style.animationDelay = '0s'; + + const who = document.createElement('div'); + who.className = 'who'; + const span = document.createElement('span'); + span.textContent = data.data.name; + const time = document.createElement('time'); + time.textContent = data.data.time; + who.append(span, time); + + const body = document.createElement('div'); + body.className = 'body'; + body.textContent = data.data.text; + + d.append(who, body); + + if (first && first.parentNode === list) list.insertBefore(d, first); + else { + if (list.querySelector('p')) list.innerHTML = ''; + list.appendChild(d); + } + } + return; + } catch (err) { + btn.textContent = err.message && err.message.length <= 10 ? err.message : '发送失败'; + setTimeout(() => { + btn.textContent = BTN_TEXT; + btn.disabled = false; + }, 1600); + sending = false; + return; + } + } + + btn.addEventListener('click', send); + + textI.addEventListener('keydown', e => { + if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') btn.click(); + }); + + load(); +})(); \ No newline at end of file diff --git a/public/js/music-random.js b/public/js/music-random.js new file mode 100644 index 0000000..f08e20c --- /dev/null +++ b/public/js/music-random.js @@ -0,0 +1,192 @@ +/* ================= 随机抽取歌曲 ================= */ +/* 歌单数据由 /music/ 页面以 + + + + diff --git a/src/pages/chronicle.astro b/src/pages/chronicle.astro new file mode 100644 index 0000000..9d1bbfd --- /dev/null +++ b/src/pages/chronicle.astro @@ -0,0 +1,206 @@ +--- +export const prerender = true; +import { getCollection } from "astro:content"; +import { SITE } from "../site.config"; + +// 班史列表:src/content/*.md(与首页「班级编年史」同源) +// 升序排列,序号与文章页「第 N 篇」一致 +const posts = (await getCollection("chronicle")).sort( + (a, b) => a.data.date.valueOf() - b.data.date.valueOf(), +); + +const pad = (n: number) => String(n).padStart(2, "0"); +const total = posts.length; + +const items = posts.map((post, i) => { + const d = post.data.date; + return { + index: i + 1, + dateLabel: `${d.getFullYear()} · ${pad(d.getMonth() + 1)} · ${pad(d.getDate())}`, + title: post.data.title, + summary: post.data.summary, + author: post.data.author, + url: `/pages/${post.id.split("/").pop()}`, + }; +}); +--- + + + + + + 班史列表 · {SITE.className} + + + + + + +
+
+
+
+ + +
+ ← 返回班史 + {SITE.className} · 班史列表 + 📝 投稿 +
+ +
+
+ +

班史列表

+

+ 从初见的那一天起,每一段日子都有了名字 · 共 {total} 篇 +

+
+
+ +
+ { + items.length > 0 ? ( +
    + {items.map((p) => ( +
  1. + + + {String(p.index).padStart(2, "0")} + +
    +
    {p.dateLabel}
    +
    {p.title}
    + {p.summary && ( +
    {p.summary}
    + )} + {p.author && ( +
    {p.author}
    + )} +
    + 查看 → +
    +
  2. + ))} +
+ ) : ( +

班史还是空的,快去投稿吧~

+ ) + } +
+ +
+
{SITE.className} · 永远
+

愿我们都被世界温柔以待,也永远记得这间教室

+

© {SITE.className}班史 · 制作于某个想起你们的夜晚

+
+
+ + + + + diff --git a/src/pages/contribute.astro b/src/pages/contribute.astro new file mode 100644 index 0000000..c2759e3 --- /dev/null +++ b/src/pages/contribute.astro @@ -0,0 +1,948 @@ +--- +export const prerender = true; +import { SITE } from "../site.config"; + +// Cloudflare Turnstile 前端 site key(构建时注入,缺失则自动禁用) +const turnstileSiteKey = import.meta.env.PUBLIC_TURNSTILE_SITE_KEY ?? ""; +const hasTurnstile = turnstileSiteKey.length > 0; +--- + + + + + + 班史投稿 + { + hasTurnstile && ( + + + diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 0000000..c9940fa --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,256 @@ +--- +// 文章列表已移至 /chronicle(班史列表页),首页编年史区块留空 +import { SITE } from "../site.config"; +--- + + + + + + + {SITE.className} · 班史 + + + + + + +
+
+
+
+ +
+ + {SITE.brandMark} + {SITE.className} · 班史 + + + +
+
+ +
+
{SITE.heroBadge}
+

{SITE.className}

+

+ +

+
+ 📖 打开班史列表 +
+ +
+
+
+
+ About Us +

+ 一间教室,三年光阴 +

+

+ 那年秋天,几十个互不相识的名字被写进同一张座位表。风扇转过无数个燥热的午后,黑板擦落下的粉笔灰在阳光里飘成一场小雪。我们从陌生到熟悉,从并肩到并肩。 +

+

+ 这里有早读时此起彼伏的背书声,有课间十分钟的喧闹与追逐,有考试前互相打气的纸条,也有晚自习窗外那片被灯光照亮的夜色。这些琐碎的日常,后来都成了我们回不去的黄金时代。 +

+

谨以此页,记录 {SITE.className} 走过的每一步。

+
+
+
+ 0同 学 +
+
+ 0年 时 光 +
+
+ 0个 日 夜 +
+
+ 0+ 回 忆 +
+
+
+
+
+ +
+
+
+ Chronicle +

班级编年史

+

+ 从初见的那一天起,每一段日子都有了名字。 +

+
+ +
+
+
+ +
+
+
+ The Crew +

班级人物志

+

那些撑起这个班的人。

+
+ +
+
+
👑
+

班长

+
CAPTAIN
+

"都安静一下,我说个事儿。"

+
+
+
📚
+

学习委员

+
STUDY
+

"作业收一下,最后一排。"

+
+
+
🏃
+

体育委员

+
SPORTS
+

"集合!快点儿,别磨蹭!"

+
+
+
🎨
+

文艺委员

+
ART
+

"这次板报,我们拿第一。"

+
+
+
🧹
+

劳动委员

+
DUTY
+

"今天值日的是第三组,别忘了。"

+
+
+
📣
+

宣传委员

+
MEDIA
+

"照片我都存着呢,一张没删。"

+
+
+
+
+ +
+
+
+ Honors +

班级荣誉

+

属于我们共同的勋章。

+
+
+
+
🏆
+
+

校运动会团体总分第一

+

20XX · 秋季运动会

+
+
+
+
🥇
+
+

优秀班集体

+

20XX—20XX 学年

+
+
+
+
🎭
+
+

校园艺术节最佳创意奖

+

20XX · 元旦汇演

+
+
+
+
📖
+
+

经典诵读比赛一等奖

+

20XX · 读书节

+
+
+
+
🏀
+
+

年级篮球赛亚军

+

20XX · 春季

+
+
+
+
⭐
+
+

文明班级 · 三连冠

+

连续三个学期

+
+
+
+
+
+ +
+
+
+ Memories +

班级记忆

+

+ 把这里替换成你们的照片吧 —— 将 <div + class="photo"> 换成 <img> 或背景图即可。 +

+
+ +
+
+ +
+
+
+ Message Board +

留言墙

+

写下一句话,送给未来的我们。

+
+
+ + + +
+
+
+
+ +
+
{SITE.className} · 永远
+

愿我们都被世界温柔以待,也永远记得这间教室

+

© {SITE.className}班史 · 制作于某个想起你们的夜晚

+
+
+ + + + + diff --git a/src/pages/music-contribute.astro b/src/pages/music-contribute.astro new file mode 100644 index 0000000..0109a65 --- /dev/null +++ b/src/pages/music-contribute.astro @@ -0,0 +1,864 @@ +--- +export const prerender = true; +import { SITE } from "../site.config"; + +// Cloudflare Turnstile 前端 site key(构建时注入,缺失则自动禁用) +const turnstileSiteKey = import.meta.env.PUBLIC_TURNSTILE_SITE_KEY ?? ""; +const hasTurnstile = turnstileSiteKey.length > 0; +--- + + + + + + 音乐投稿 · {SITE.className} + { + hasTurnstile && ( + + + diff --git a/src/pages/music.astro b/src/pages/music.astro new file mode 100644 index 0000000..63f28c6 --- /dev/null +++ b/src/pages/music.astro @@ -0,0 +1,541 @@ +--- +export const prerender = true; +import { getCollection } from "astro:content"; +import { SITE } from "../site.config"; + +// 歌单完全来自投稿:src/songs/*.json(投稿 PR 合并后自动显示) +type Song = { + title: string; + artist: string; + note?: string; + link?: string; + author?: string; +}; + +let songs: Song[] = []; +try { + songs = (await getCollection("songs")) + .sort((a, b) => (b.data.date ?? "").localeCompare(a.data.date ?? "")) + .map((e) => ({ + title: e.data.title, + artist: e.data.artist, + note: e.data.note, + link: e.data.link, + author: e.data.author, + })); +} catch { + // 目录还不存在或为空时忽略(目录不存在时 glob loader 也可能抛错) + songs = []; +} + +const total = songs.length; + +// 随机抽取用的数据(静态预渲染,直接内联 JSON 给浏览器) +// 转义 "<" ,避免歌名/备注里出现脚本结束标签时提前闭合 script +const songsJson = JSON.stringify(songs).replace(/ + + + + 班级歌单 · {SITE.className} + + + + + + +
+
+
+
+ + +
+ ← 返回班史 + {SITE.className} · 歌单 + 🎵 投稿音乐 +
+ +
+
+ +

班级歌单

+

+ 那些在教室里循环过的旋律,共 {total} 首 +

+ { + total > 0 && ( +
+ + + 不知道听什么?交给随机 · 也可按 R + +
+ ) + } + { + total > 1 && ( + + ) + } +
+
+ +
+ { + songs.length > 0 ? ( +
    + {songs.map((s, i) => ( +
  1. + + {String(i + 1).padStart(2, "0")} + +
    +
    + {s.title} + {s.artist} +
    + {s.note &&
    {s.note}
    } + {s.author &&
    {s.author}
    } +
    + {s.link && ( + + ♫ 播放 + + )} +
  2. + ))} +
+ ) : ( +

歌单还是空的,快去投稿吧~

+ ) + } +
+ + + +
+
随机抽取
+

—

+
+ + +
+ + + + +
+

按 R 换一首 · Esc 关闭

+

+
+
+ +
+
{SITE.className} · 永远
+

愿我们都被世界温柔以待,也永远记得这间教室

+

© {SITE.className}班史 · 制作于某个想起你们的夜晚

+
+
+ + + + + + + + diff --git a/src/pages/pages/[...slug].astro b/src/pages/pages/[...slug].astro new file mode 100644 index 0000000..371af76 --- /dev/null +++ b/src/pages/pages/[...slug].astro @@ -0,0 +1,53 @@ +--- +// 动态路由:src/content/*.md → /pages/<文件名去扩展名> +// 例如 src/content/20250101.md → /pages/20250101 +import { getCollection, render } from 'astro:content'; +import PostLayout from '../../layouts/PostLayout.astro'; + +export async function getStaticPaths() { + const posts = await getCollection('chronicle'); + const sorted = posts.sort( + (a, b) => a.data.date.valueOf() - b.data.date.valueOf() + ); + + return Promise.all( + sorted.map(async (entry, i) => { + const slug = entry.id.split('/').pop()!; // 去掉年月目录前缀 + const prev = i > 0 ? sorted[i - 1] : null; + const next = i < sorted.length - 1 ? sorted[i + 1] : null; + return { + params: { slug }, + props: { + entry, + index: i, + total: sorted.length, + prev: prev + ? { + url: `/pages/${prev.id.split('/').pop()}`, + title: prev.data.title, + } + : null, + next: next + ? { + url: `/pages/${next.id.split('/').pop()}`, + title: next.data.title, + } + : null, + rendered: await render(entry), + }, + }; + }) + ); +} + +const { entry, index, total, prev, next, rendered } = Astro.props; +--- + + diff --git a/src/plugins/markdown-reveal.mjs b/src/plugins/markdown-reveal.mjs new file mode 100644 index 0000000..50e7c2c --- /dev/null +++ b/src/plugins/markdown-reveal.mjs @@ -0,0 +1,51 @@ +/* ================= markdown → HTML 时自动补 .reveal ================= + Astro 7 默认使用 Sätteri 处理器,这里是一个 Sätteri 的 hast 插件: + 在 markdown 转成 HTML 之后,给正文最外层的块级元素补上 .reveal, + 交给 /js/pages.js 的 IntersectionObserver 做错峰入场。 + + 这样文章的 markdown 源文件保持干净,不用手写任何 class。 */ + +// 需要入场动画的块级元素。 +const BLOCK_TAGS = [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "p", + "ul", + "ol", + "blockquote", + "pre", + "table", + "figure", + "details", + "summary", +]; + +/** 把 "reveal" 追加到已有 class 上(class 可能是数组或字符串)。 */ +function withReveal(current) { + const list = Array.isArray(current) + ? current.slice() + : typeof current === "string" && current.trim() + ? current.trim().split(/\s+/) + : []; + if (!list.includes("reveal")) list.push("reveal"); + return list; +} + +export default { + name: "reveal", + element: { + // 由 Sätteri 在 Rust 侧按标签名过滤,只有这些元素会进到 visit + filter: BLOCK_TAGS, + visit(node, ctx) { + // 只标注正文最外层:嵌套的 li、blockquote 里的 p、内层 ul 等 + // 跟着外层一起出现,再各自加一层会重复播放、时序也会互相错开。 + const parent = ctx.parent(node); + if (parent && parent.type !== "root" && !(node.tagName === "summary" && parent.tagName === "details")) return; + ctx.setProperty(node, "className", withReveal(node.properties?.className)); + }, + }, +}; diff --git a/src/site.config.ts b/src/site.config.ts new file mode 100644 index 0000000..74f51fa --- /dev/null +++ b/src/site.config.ts @@ -0,0 +1,22 @@ +/** 班级信息:改这一个文件即可完成大部分定制,各页面会自动引用。 */ +export const SITE = { + /** 班级全名,如 "30届1班" */ + className: "XX届X班", + /** 班级简称,用于留言框占位符等口语场景,如 "1班" */ + classShort: "X班", + /** 顶栏 logo 方块里显示的字符,如 "1" */ + brandMark: "X", + /** 首屏徽章文字,如 "CLASS 1 · FOREVER" */ + heroBadge: "CLASS XX · FOREVER", + /** 首页「班级简介」区块的统计数字 */ + stats: { + /** 同学 */ + students: 40, + /** 年时光 */ + years: 3, + /** 个日夜 */ + days: 1000, + /** + 回忆(值为 999 时会自动显示加号) */ + memories: 999, + }, +} as const; diff --git a/src/songs/20250101-example.json b/src/songs/20250101-example.json new file mode 100644 index 0000000..1942929 --- /dev/null +++ b/src/songs/20250101-example.json @@ -0,0 +1,8 @@ +{ + "title": "示例歌曲(删掉我)", + "artist": "示例歌手", + "date": "20250101", + "link": "https://example.com/", + "note": "这是一条示例投稿,展示歌单条目的显示效果,正式使用前请删除本文件。", + "author": "站长" +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8bf91d3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +}