From 5bb63bacf59b40cd89f993d6ad1495691596f252 Mon Sep 17 00:00:00 2001 From: Adrian Altner Date: Wed, 22 Apr 2026 10:55:29 +0200 Subject: [PATCH] Initial commit: Astro 6 static blog site - German (default) and English i18n support - Categories and tags - Blog posts with hero images - Dark/light theme switcher - View Transitions removed to fix reload ghost images - Webmentions integration - RSS feeds per locale Co-Authored-By: Claude Sonnet 4.5 --- .claude/launch.json | 11 + .forgejo/workflows/deploy.yml | 63 + .gitignore | 26 + .vscode/extensions.json | 4 + .vscode/launch.json | 11 + CLAUDE.md | 45 + Containerfile | 35 + README.md | 63 + astro.config.mjs | 75 + compose.yml | 13 + package-lock.json | 5928 +++++++++++++++++ package.json | 22 + public/favicon.ico | Bin 0 -> 655 bytes public/favicon.svg | 9 + scripts/VISION.md | 76 + scripts/copy-sw.js | 17 + scripts/deploy.sh | 49 + scripts/fetch-favicons.mjs | 74 + scripts/metadata.ts | 424 ++ scripts/new-note-mdx-prompt.sh | 40 + scripts/new-note-prompt.sh | 38 + scripts/new-note.sh | 68 + scripts/new-post-prompt.sh | 38 + scripts/new-post.sh | 39 + scripts/publish-all.sh | 62 + scripts/publish-blog.sh | 62 + scripts/publish-links.sh | 52 + scripts/publish-notes.sh | 58 + scripts/publish-photos.sh | 57 + scripts/publish-projects.sh | 49 + scripts/squash-history.sh | 23 + scripts/vision.spec.ts | 91 + scripts/vision.ts | 820 +++ src/assets/blog-placeholder-1.jpg | Bin 0 -> 32040 bytes src/assets/blog-placeholder-2.jpg | Bin 0 -> 33136 bytes src/assets/blog-placeholder-3.jpg | Bin 0 -> 28687 bytes src/assets/blog-placeholder-4.jpg | Bin 0 -> 38690 bytes src/assets/blog-placeholder-5.jpg | Bin 0 -> 34890 bytes src/assets/blog-placeholder-about.jpg | Bin 0 -> 21606 bytes src/assets/fonts/atkinson-bold.woff | Bin 0 -> 23780 bytes src/assets/fonts/atkinson-regular.woff | Bin 0 -> 22792 bytes src/components/BaseHead.astro | 70 + src/components/CategoriesPage.astro | 62 + src/components/CategoryDetailPage.astro | 88 + src/components/Footer.astro | 91 + src/components/FormattedDate.astro | 27 + src/components/Header.astro | 433 ++ src/components/HeaderLink.astro | 42 + src/components/HomePage.astro | 118 + src/components/TagDetailPage.astro | 84 + src/components/TagsPage.astro | 57 + src/components/Webmentions.astro | 300 + src/consts.ts | 14 + src/content.config.ts | 42 + src/content/categories/de/allgemein.md | 5 + src/content/categories/de/technik.md | 5 + src/content/categories/en/general.md | 5 + src/content/categories/en/tech.md | 5 + src/content/posts/de/first-post.md | 18 + src/content/posts/de/markdown-style-guide.md | 218 + src/content/posts/de/second-post.md | 17 + .../de/setting-up-forgejo-actions-runner.md | 237 + src/content/posts/de/third-post.md | 17 + src/content/posts/de/using-mdx.mdx | 35 + src/content/posts/en/hello-world.md | 12 + .../en/setting-up-forgejo-actions-runner.md | 237 + src/i18n/posts.ts | 152 + src/i18n/ui.ts | 134 + src/layouts/BaseLayout.astro | 57 + src/layouts/Post.astro | 163 + src/layouts/Prose.astro | 50 + src/pages/[...slug].astro | 21 + src/pages/datenschutz.md | 119 + src/pages/en/[...slug].astro | 21 + src/pages/en/about.astro | 14 + src/pages/en/categories.astro | 5 + src/pages/en/category/[slug].astro | 18 + src/pages/en/contact.astro | 138 + src/pages/en/imprint.md | 38 + src/pages/en/index.astro | 5 + src/pages/en/privacy-policy.md | 119 + src/pages/en/rss.xml.js | 16 + src/pages/en/tag/[slug].astro | 13 + src/pages/en/tags.astro | 5 + src/pages/impressum.md | 38 + src/pages/index.astro | 5 + src/pages/kategorie/[slug].astro | 18 + src/pages/kategorien.astro | 5 + src/pages/kontakt.astro | 138 + src/pages/rss.xml.js | 16 + src/pages/schlagwoerter.astro | 5 + src/pages/schlagwort/[slug].astro | 13 + src/pages/ueber-mich.astro | 14 + src/styles/global.css | 167 + tsconfig.json | 11 + 95 files changed, 12199 insertions(+) create mode 100644 .claude/launch.json create mode 100644 .forgejo/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 CLAUDE.md create mode 100644 Containerfile create mode 100644 README.md create mode 100644 astro.config.mjs create mode 100644 compose.yml create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 public/favicon.svg create mode 100644 scripts/VISION.md create mode 100644 scripts/copy-sw.js create mode 100755 scripts/deploy.sh create mode 100644 scripts/fetch-favicons.mjs create mode 100644 scripts/metadata.ts create mode 100755 scripts/new-note-mdx-prompt.sh create mode 100755 scripts/new-note-prompt.sh create mode 100755 scripts/new-note.sh create mode 100755 scripts/new-post-prompt.sh create mode 100755 scripts/new-post.sh create mode 100755 scripts/publish-all.sh create mode 100755 scripts/publish-blog.sh create mode 100755 scripts/publish-links.sh create mode 100755 scripts/publish-notes.sh create mode 100755 scripts/publish-photos.sh create mode 100755 scripts/publish-projects.sh create mode 100755 scripts/squash-history.sh create mode 100644 scripts/vision.spec.ts create mode 100644 scripts/vision.ts create mode 100644 src/assets/blog-placeholder-1.jpg create mode 100644 src/assets/blog-placeholder-2.jpg create mode 100644 src/assets/blog-placeholder-3.jpg create mode 100644 src/assets/blog-placeholder-4.jpg create mode 100644 src/assets/blog-placeholder-5.jpg create mode 100644 src/assets/blog-placeholder-about.jpg create mode 100644 src/assets/fonts/atkinson-bold.woff create mode 100644 src/assets/fonts/atkinson-regular.woff create mode 100644 src/components/BaseHead.astro create mode 100644 src/components/CategoriesPage.astro create mode 100644 src/components/CategoryDetailPage.astro create mode 100644 src/components/Footer.astro create mode 100644 src/components/FormattedDate.astro create mode 100644 src/components/Header.astro create mode 100644 src/components/HeaderLink.astro create mode 100644 src/components/HomePage.astro create mode 100644 src/components/TagDetailPage.astro create mode 100644 src/components/TagsPage.astro create mode 100644 src/components/Webmentions.astro create mode 100644 src/consts.ts create mode 100644 src/content.config.ts create mode 100644 src/content/categories/de/allgemein.md create mode 100644 src/content/categories/de/technik.md create mode 100644 src/content/categories/en/general.md create mode 100644 src/content/categories/en/tech.md create mode 100644 src/content/posts/de/first-post.md create mode 100644 src/content/posts/de/markdown-style-guide.md create mode 100644 src/content/posts/de/second-post.md create mode 100644 src/content/posts/de/setting-up-forgejo-actions-runner.md create mode 100644 src/content/posts/de/third-post.md create mode 100644 src/content/posts/de/using-mdx.mdx create mode 100644 src/content/posts/en/hello-world.md create mode 100644 src/content/posts/en/setting-up-forgejo-actions-runner.md create mode 100644 src/i18n/posts.ts create mode 100644 src/i18n/ui.ts create mode 100644 src/layouts/BaseLayout.astro create mode 100644 src/layouts/Post.astro create mode 100644 src/layouts/Prose.astro create mode 100644 src/pages/[...slug].astro create mode 100644 src/pages/datenschutz.md create mode 100644 src/pages/en/[...slug].astro create mode 100644 src/pages/en/about.astro create mode 100644 src/pages/en/categories.astro create mode 100644 src/pages/en/category/[slug].astro create mode 100644 src/pages/en/contact.astro create mode 100644 src/pages/en/imprint.md create mode 100644 src/pages/en/index.astro create mode 100644 src/pages/en/privacy-policy.md create mode 100644 src/pages/en/rss.xml.js create mode 100644 src/pages/en/tag/[slug].astro create mode 100644 src/pages/en/tags.astro create mode 100644 src/pages/impressum.md create mode 100644 src/pages/index.astro create mode 100644 src/pages/kategorie/[slug].astro create mode 100644 src/pages/kategorien.astro create mode 100644 src/pages/kontakt.astro create mode 100644 src/pages/rss.xml.js create mode 100644 src/pages/schlagwoerter.astro create mode 100644 src/pages/schlagwort/[slug].astro create mode 100644 src/pages/ueber-mich.astro create mode 100644 src/styles/global.css create mode 100644 tsconfig.json diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..cc9ef50 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "astro-dev", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "port": 4321 + } + ] +} diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml new file mode 100644 index 0000000..b403634 --- /dev/null +++ b/.forgejo/workflows/deploy.yml @@ -0,0 +1,63 @@ +name: Deploy + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: self-hosted + env: + DEPLOY_DIR: /opt/websites/adrian-altner.de + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Sync to deploy directory + run: | + sudo rsync -a --delete \ + --exclude='.env' \ + --exclude='.env.production' \ + --exclude='.git/' \ + --exclude='node_modules/' \ + ./ "${DEPLOY_DIR}/" + + - name: Secret check + env: + WEBMENTION_TOKEN: ${{ secrets.WEBMENTION_TOKEN }} + WEBMENTION_APP_TOKEN: ${{ secrets.WEBMENTION_APP_TOKEN }} + run: | + echo "WEBMENTION_TOKEN length: ${#WEBMENTION_TOKEN}" + echo "WEBMENTION_APP_TOKEN length: ${#WEBMENTION_APP_TOKEN}" + + - name: Build image + run: | + cd "${DEPLOY_DIR}" + sudo podman build \ + --no-cache \ + --build-arg WEBMENTION_TOKEN="${{ secrets.WEBMENTION_TOKEN }}" \ + -t localhost/adrian-altner.de:latest . + + - name: Restart service + run: sudo systemctl restart podman-compose@adrian-altner.de.service + + - name: Prune + run: | + sudo podman container prune -f 2>/dev/null || true + sudo podman image prune --external -f 2>/dev/null || true + sudo podman image prune -f 2>/dev/null || true + sudo podman builder prune -af 2>/dev/null || true + + - name: Send webmentions + env: + WEBMENTION_APP_TOKEN: ${{ secrets.WEBMENTION_APP_TOKEN }} + run: | + if [ -z "$WEBMENTION_APP_TOKEN" ]; then + echo "No WEBMENTION_APP_TOKEN — skipping." + exit 0 + fi + for feed in rss.xml en/rss.xml; do + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/${feed}&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + done diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d89661 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# 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.local +.env.development +.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..56f043d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode", "unifiedjs.vscode-mdx"], + "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/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5b6276a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,45 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +- `npm run dev` — local dev server at `localhost:4321` +- `npm run build` — production build to `./dist/` +- `npm run preview` — preview production build +- `npm run astro -- --help` — Astro CLI (e.g. `astro check` for type-checking) + +Node >= 22.12.0 required. + +## Path aliases + +[tsconfig.json](tsconfig.json) defines a single `~/*` → `src/*` alias. Prefer it over relative imports (`~/components/Foo.astro` instead of `../../components/Foo.astro`) in `.astro`, `.ts`, `.js`, `.mjs`, and MDX files. Frontmatter `heroImage` paths and inline markdown `![](…)` image refs stay relative — Astro's image resolver expects those relative to the content file. + +## Architecture + +Astro 6 static site, based on the `blog` starter template. No tests, no linter configured. Site URL: `https://adrian-altner.de`. + +### Internationalisation (de default, en secondary) + +- Astro i18n is configured in [astro.config.mjs](astro.config.mjs) with `defaultLocale: 'de'`, `locales: ['de', 'en']`, `prefixDefaultLocale: false`. German lives at `/`, English at `/en/`. +- Posts are organised per locale under `src/content/posts//…`. Post `id` is `/`; helpers in [src/i18n/posts.ts](src/i18n/posts.ts) (`entryLocale`, `entrySlug`, `getPostsByLocale`, `getCategoriesByLocale`, `getPostsByCategory`, `categoryHref`, `categorySegment`) split and filter them. The content schema in [src/content.config.ts](src/content.config.ts) globs `{de,en}/**/*.{md,mdx}`. Collection name is `posts` — access via `getCollection('posts')` / `CollectionEntry<'posts'>`. +- A second collection `categories` lives under `src/content/categories//*.md` (schema: `name`, optional `description`, optional `translationKey`). Blog posts reference a category via `category: reference('categories')` in the schema; frontmatter values are fully-qualified entry ids, e.g. `category: de/technik` or `category: en/tech`. Resolve with `getEntry(post.data.category)`. +- **Translation linking**: both collections support an optional `translationKey` string. Entries in different locales that represent the same logical content share one key (e.g. `de/technik` and `en/tech` both set `translationKey: tech`). The language switcher resolves this via `findTranslation(entry, target)` ([src/i18n/posts.ts](src/i18n/posts.ts)) to produce the correct target-locale URL. Pages that render a specific content entry should pass it to `Header` as `entry={…}` (see [src/pages/[...slug].astro](src/pages/[...slug].astro), [CategoryDetailPage](src/components/CategoryDetailPage.astro)); the `BlogPost` layout forwards an `entry` prop. When an entry has no translation, the switcher falls back to the other locale's home rather than producing a 404. +- Category routes are localised in the URL: `/kategorie/` (de) and `/en/category/` (en), driven by [src/pages/kategorie/[slug].astro](src/pages/kategorie/[slug].astro) and [src/pages/en/category/[slug].astro](src/pages/en/category/[slug].astro). Both use shared UI components ([CategoryIndexPage](src/components/CategoryIndexPage.astro), [CategoryDetailPage](src/components/CategoryDetailPage.astro)). `categorySegment(locale)` returns the right URL segment. +- Because posts sit two levels deep, hero images and component imports inside MD/MDX use `../../../assets/…` / `../../../components/…` relative paths. +- UI strings and path helpers live in [src/i18n/ui.ts](src/i18n/ui.ts). `t(locale, key)` for translations; `localizePath(path, locale)` prefixes `/en` when needed; `switchLocalePath(pathname, target)` rewrites the current URL to the other locale (used by the header language switcher and hreflang alternates in [BaseHead.astro](src/components/BaseHead.astro)). +- Site titles/descriptions per locale live in [src/consts.ts](src/consts.ts) (`SITE.de`, `SITE.en`). The `SITE[locale]` map is the single source of truth — update when rebranding. +- Pages: German under `src/pages/` (`index.astro`, `about.astro`, `[...slug].astro`, `rss.xml.js`), English mirrors under `src/pages/en/`. The shared home UI lives in [src/components/HomePage.astro](src/components/HomePage.astro); both `index.astro` files are thin wrappers that pass `locale="de"` / `locale="en"`. +- Layouts: [BaseLayout.astro](src/layouts/BaseLayout.astro) is the common skeleton (`` / `` with `BaseHead` / `` with `Header` + `main` + `Footer`). Accepts `title`, `description`, `locale`, optional `image`, optional `entry` (for the language-switch translation lookup), optional `bodyClass`, and a `head` named slot for per-page ``/`` extras. All page templates compose via this layout — don't re-assemble head/header/footer by hand. [Post.astro](src/layouts/Post.astro) wraps `BaseLayout` to add hero image + title block + category line for single posts. `Header`, `BaseHead`, and `FormattedDate` also accept `locale` directly and fall back to `getLocaleFromUrl(Astro.url)`. +- Separate RSS feeds per locale: `/rss.xml` (de) and `/en/rss.xml`. The sitemap integration is configured with `i18n: { defaultLocale: 'de', locales: { de: 'de-DE', en: 'en-US' } }`. + +### Routing and data flow + +- [src/pages/[...slug].astro](src/pages/[...slug].astro) and [src/pages/en/[...slug].astro](src/pages/en/[...slug].astro) generate post pages via `getStaticPaths` + `getPostsByLocale(locale)`, rendering through [BlogPost.astro](src/layouts/BlogPost.astro). +- `@astrojs/sitemap` generates the sitemap index; `` tags are emitted in `BaseHead.astro` for both locales plus `x-default`. +- **Fonts**: Atkinson is loaded as a local font via Astro's `fonts` API in `astro.config.mjs`, exposed as CSS variable `--font-atkinson`. Files in `src/assets/fonts/`. +- **MDX** is enabled via `@astrojs/mdx`; posts can mix Markdown and components. + +## Hero image workflow + +Per user convention: hero image templates live under `src/assets/heros/*`. Workflow uses Maple Mono font, headless Brave to render, then `sharp` to export JPG at 1020×510. diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..06e85f9 --- /dev/null +++ b/Containerfile @@ -0,0 +1,35 @@ +FROM node:22-bookworm-slim AS build + +ARG WEBMENTION_TOKEN="" +ENV WEBMENTION_TOKEN=$WEBMENTION_TOKEN + +WORKDIR /app + +COPY package.json package-lock.json ./ + +RUN npm ci + +COPY . . + +RUN npm run build + + +FROM node:22-bookworm-slim AS runtime + +WORKDIR /app + +ENV NODE_ENV=production +ENV ASTRO_TELEMETRY_DISABLED=1 +ENV HOST=0.0.0.0 +ENV PORT=4321 + +COPY --from=build --chown=node:node /app/package.json ./package.json +COPY --from=build --chown=node:node /app/package-lock.json ./package-lock.json +COPY --from=build --chown=node:node /app/node_modules ./node_modules +COPY --from=build --chown=node:node /app/dist ./dist + +USER node + +EXPOSE 4321 + +CMD ["node", "dist/server/entry.mjs"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..3883e37 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# Astro Starter Kit: Blog + +```sh +npm create astro@latest -- --template blog +``` + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +Features: + +- ✅ Minimal styling (make it your own!) +- ✅ 100/100 Lighthouse performance +- ✅ SEO-friendly with canonical URLs and Open Graph data +- ✅ Sitemap support +- ✅ RSS Feed support +- ✅ Markdown & MDX support + +## 🚀 Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +├── public/ +├── src/ +│   ├── assets/ +│   ├── components/ +│   ├── content/ +│   ├── layouts/ +│   └── pages/ +├── astro.config.mjs +├── README.md +├── package.json +└── tsconfig.json +``` + +Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. + +There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. + +The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more. + +Any static assets, like images, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). + +## Credit + +This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/). diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..27c9723 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,75 @@ +// @ts-check + +import mdx from '@astrojs/mdx'; +import sitemap from '@astrojs/sitemap'; +import { defineConfig, fontProviders } from 'astro/config'; +import { loadEnv } from 'vite'; + +import node from '@astrojs/node'; + +const envMode = process.env.NODE_ENV === 'production' ? 'production' : 'development'; +const envVars = loadEnv(envMode, process.cwd(), ''); +const WEBMENTION_TOKEN = envVars.WEBMENTION_TOKEN || process.env.WEBMENTION_TOKEN || ''; + +// https://astro.build/config +export default defineConfig({ + site: 'https://adrian-altner.de', + + vite: { + define: { + 'globalThis.__WEBMENTION_TOKEN__': JSON.stringify(WEBMENTION_TOKEN), + }, + }, + + devToolbar: { + enabled: false, + }, + + i18n: { + defaultLocale: 'de', + locales: ['de', 'en'], + routing: { + prefixDefaultLocale: false, + redirectToDefaultLocale: false, + }, + }, + + integrations: [ + mdx(), + sitemap({ + i18n: { + defaultLocale: 'de', + locales: { de: 'de-DE', en: 'en-US' }, + }, + }), + ], + + fonts: [ + { + provider: fontProviders.local(), + name: 'Atkinson', + cssVariable: '--font-atkinson', + fallbacks: ['sans-serif'], + options: { + variants: [ + { + src: ['./src/assets/fonts/atkinson-regular.woff'], + weight: 400, + style: 'normal', + display: 'swap', + }, + { + src: ['./src/assets/fonts/atkinson-bold.woff'], + weight: 700, + style: 'normal', + display: 'swap', + }, + ], + }, + }, + ], + + adapter: node({ + mode: 'standalone', + }), +}); \ No newline at end of file diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..1056761 --- /dev/null +++ b/compose.yml @@ -0,0 +1,13 @@ +name: adrian-altner-de + +services: + website: + image: localhost/adrian-altner.de:latest + container_name: adrian-altner.de + ports: + - "4321:4321" + environment: + NODE_ENV: production + HOST: 0.0.0.0 + PORT: 4321 + restart: unless-stopped diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..dfbcc34 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5928 @@ +{ + "name": "adrian-altner.de", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "adrian-altner.de", + "version": "0.0.1", + "dependencies": { + "@astrojs/mdx": "^5.0.3", + "@astrojs/node": "^10.0.5", + "@astrojs/rss": "^4.0.18", + "@astrojs/sitemap": "^3.7.2", + "astro": "^6.1.8", + "sharp": "^0.34.3" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/compiler": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-3.0.1.tgz", + "integrity": "sha512-z97oYbdebO5aoWzuJ/8q5hLK232+17KcLZ7cJ8BCWk6+qNzVxn/gftC0KzMBUTD8WAaBkPpNSQK6PXLnNrZ0CA==", + "license": "MIT" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.8.0.tgz", + "integrity": "sha512-J56GrhEiV+4dmrGLPNOl2pZjpHXAndWVyiVDYGDuw6MWKpBSEMLdFxHzeM/6sqaknw9M+HFfHZAcvi3OfT3D/w==", + "license": "MIT", + "dependencies": { + "picomatch": "^4.0.3" + } + }, + "node_modules/@astrojs/markdown-remark": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.1.0.tgz", + "integrity": "sha512-P+HnCsu2js3BoTc8kFmu+E9gOcFeMdPris75g+Zl4sY8+bBRbSQV6xzcBDbZ27eE7yBGEGQoqjpChx+KJYIPYQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.8.0", + "@astrojs/prism": "4.0.1", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "js-yaml": "^4.1.1", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.0", + "smol-toml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.1.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/mdx": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-5.0.3.tgz", + "integrity": "sha512-zv/OlM5sZZvyjHqJjR3FjJvoCgbxdqj3t4jO/gSEUNcck3BjdtMgNQw8UgPfAGe4yySdG4vjZ3OC5wUxhu7ckg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "7.1.0", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.16.0", + "es-module-lexer": "^2.0.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "piccolore": "^0.1.3", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.6", + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "astro": "^6.0.0" + } + }, + "node_modules/@astrojs/node": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-10.0.5.tgz", + "integrity": "sha512-rgZiU9nD7zmM3fdmOVuobcNHAyXWx2HXXDLTuxjVCTQ+QmHmL5zkZZhNIL5NjlQtDRAU1i5fVaXp7nAKdET30w==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.8.0", + "send": "^1.2.1", + "server-destroy": "^1.0.1" + }, + "peerDependencies": { + "astro": "^6.0.0" + } + }, + "node_modules/@astrojs/prism": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.1.tgz", + "integrity": "sha512-nksZQVjlferuWzhPsBpQ1JE5XuKAf1id1/9Hj4a9KG4+ofrlzxUUwX4YGQF/SuDiuiGKEnzopGOt38F3AnVWsQ==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@astrojs/rss": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.18.tgz", + "integrity": "sha512-wc5DwKlbTEdgVAWnHy8krFTeQ42t1v/DJqeq5HtulYK3FYHE4krtRGjoyhS3eXXgfdV6Raoz2RU3wrMTFAitRg==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^5.5.7", + "piccolore": "^0.1.3", + "zod": "^4.3.6" + } + }, + "node_modules/@astrojs/sitemap": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.2.tgz", + "integrity": "sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==", + "license": "MIT", + "dependencies": { + "sitemap": "^9.0.0", + "stream-replace-string": "^2.0.0", + "zod": "^4.3.6" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.1.tgz", + "integrity": "sha512-7fcIxXS9J4ls5tr8b3ww9rbAIz2+HrhNJYZdkAhhB4za/I5IZ/60g+Bs8q7zwG0tOIZfNB4JWhVJ1Qkl/OrNCw==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.4.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "is-docker": "^4.0.0", + "is-wsl": "^3.1.1", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", + "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@clack/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.2.0.tgz", + "integrity": "sha512-qfxof/3T3t9DPU/Rj3OmcFyZInceqj/NVtO9rwIuJqCUgh32gwPjpFQQp/ben07qKlhpwq7GzfWpST4qdJ5Drg==", + "license": "MIT", + "dependencies": { + "fast-wrap-ansi": "^0.1.3", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.2.0.tgz", + "integrity": "sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.2.0", + "fast-string-width": "^1.1.0", + "fast-wrap-ansi": "^0.1.3", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "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.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "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.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "cpu": [ + "loong64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "cpu": [ + "ppc64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.0.2.tgz", + "integrity": "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.0.2", + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.0.2.tgz", + "integrity": "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.0.2.tgz", + "integrity": "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.0.2.tgz", + "integrity": "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.0.2.tgz", + "integrity": "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.0.2.tgz", + "integrity": "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", + "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "24.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", + "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/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.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-6.1.8.tgz", + "integrity": "sha512-6fT9M12U3fpi13DiPavNKDIoBflASTSxmKTEe+zXhWtlebQuOqfOnIrMWyRmlXp+mgDsojmw+fVFG9LUTzKSog==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^3.0.1", + "@astrojs/internal-helpers": "0.8.0", + "@astrojs/markdown-remark": "7.1.0", + "@astrojs/telemetry": "3.3.1", + "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.3.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": "^1.1.1", + "devalue": "^5.6.3", + "diff": "^8.0.3", + "dset": "^3.1.4", + "es-module-lexer": "^2.0.0", + "esbuild": "^0.27.3", + "flattie": "^1.1.1", + "fontace": "~0.4.1", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "js-yaml": "^4.1.1", + "magic-string": "^0.30.21", + "magicast": "^0.5.2", + "mrmime": "^2.0.1", + "neotraverse": "^0.6.18", + "obug": "^2.1.1", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.3", + "rehype": "^13.0.2", + "semver": "^7.7.4", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "svgo": "^4.0.1", + "tinyclip": "^0.1.12", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "tsconfck": "^3.1.6", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.4", + "unist-util-visit": "^5.1.0", + "unstorage": "^1.17.4", + "vfile": "^6.0.3", + "vite": "^7.3.1", + "vitefu": "^1.1.2", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^22.0.0", + "zod": "^4.3.6" + }, + "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.34.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz", + "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "license": "MIT" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-string-truncated-width": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-1.2.1.tgz", + "integrity": "sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow==", + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-1.1.0.tgz", + "integrity": "sha512-O3fwIVIH5gKB38QNbdg+3760ZmGz0SZMgvwJbA1b2TGXceKE6A2cOlfogh1iw8lr049zPyd7YADHy+B7U4W9bQ==", + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^1.2.0" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.1.6.tgz", + "integrity": "sha512-HlUwET7a5gqjURj70D5jl7aC3Zmy4weA1SHUfM0JFI0Ptq987NH2TwbBFLoERhfwk+E+eaq4EK3jXoT+R3yp3w==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^1.1.0" + } + }, + "node_modules/fast-xml-builder": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", + "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.1.tgz", + "integrity": "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.5", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.2" + } + }, + "node_modules/fontkitten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", + "license": "MIT", + "dependencies": { + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz", + "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.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/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "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-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "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-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "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" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "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-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "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" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "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" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/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/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-mock-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/p-limit": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.0.tgz", + "integrity": "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.2.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.1.2.tgz", + "integrity": "sha512-ktsDOALzTYTWWF1PbkNVg2rOt+HaOaMWJMUnt7T3qf5tvZ1L8dBW3tObzprBcXNMKkwj+yFSLqHso0x+UFcJXw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", + "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rollup": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shiki": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.2.tgz", + "integrity": "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.0.2", + "@shikijs/engine-javascript": "4.0.2", + "@shikijs/engine-oniguruma": "4.0.2", + "@shikijs/langs": "4.0.2", + "@shikijs/themes": "4.0.2", + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz", + "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==", + "license": "MIT", + "dependencies": { + "@types/node": "^24.9.2", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.4.1" + }, + "bin": { + "sitemap": "dist/esm/cli.js" + }, + "engines": { + "node": ">=20.19.5", + "npm": ">=10.8.2" + } + }, + "node_modules/smol-toml": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-replace-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", + "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", + "license": "MIT" + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strnum": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/svgo": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, + "node_modules/tinyclip": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.12.tgz", + "integrity": "sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, + "node_modules/tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "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/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", + "license": "MIT" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", + "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/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-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/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.npmjs.org/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/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..d3a26f8 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "adrian-altner.de", + "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/mdx": "^5.0.3", + "@astrojs/node": "^10.0.5", + "@astrojs/rss": "^4.0.18", + "@astrojs/sitemap": "^3.7.2", + "astro": "^6.1.8", + "sharp": "^0.34.3" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7f48a94d16071d6c8d06478c7458ab12e675019c GIT binary patch literal 655 zcmV;A0&x9_P)Rl-XF(A`bsas&GH{e7U1}Ri zJr5jR8B2*Jd6$=$AqgTM2o2FV$WZ9|#jJ3mmpEs{jB0ps@*Kxv}=RB|IJih8Z&fqwCG`%bN0000#bW%=J zQ=IH#a_&L{B{_6Lu_3m>0bMN%+@aOmN_3G~H^8EGi>+bXO=;-|Z`uFnf==AdP z{Oj-S=ltmI=<4`LcLE*&009F@L_t(|+I`d4ZUZ3@1<*Uo7H^LoCw6-8z4wsbd;b4l zA}zMFtOw2mLX6O5Mgl}(5P=uOM4%=tnuHiuAp%(G<c=npm$Fz%eL + + + diff --git a/scripts/VISION.md b/scripts/VISION.md new file mode 100644 index 0000000..8bd3191 --- /dev/null +++ b/scripts/VISION.md @@ -0,0 +1,76 @@ +# Vision Script + +Generiert Metadaten-Sidecars (JSON) fuer Foto-Kollektionen mithilfe von EXIF-Daten und einer Vision-AI (Anthropic oder OpenAI). + +## Voraussetzungen + +- `exiftool` installiert (`brew install exiftool`) +- `ANTHROPIC_API_KEY` oder `OPENAI_API_KEY` in `.env.local` gesetzt (je nach Provider) + +## Aufruf + +```bash +pnpm run vision [optionen] [verzeichnis] +``` + +Ohne Verzeichnis wird der Standard `content/fotos` verwendet. + +## Optionen + +| Option | Beschreibung | +|---|---| +| `--provider=anthropic\|openai` | Vision-API Provider (Standard: `anthropic`). Anthropic nutzt `claude-opus-4-6`, OpenAI nutzt `gpt-4o-mini`. | +| `--refresh` | Alle Sidecars neu generieren (EXIF + AI). Ueberschreibt vorhandene Dateien. | +| `--exif-only` | Nur EXIF-Daten in bestehenden Sidecars aktualisieren. AI-Felder (Titel, Alt, Tags) bleiben erhalten. | +| `--concurrency=N` | Anzahl paralleler Vision-API-Anfragen (Standard: 2) | +| `--retries=N` | Maximale Wiederholungsversuche bei Rate-Limits (Standard: 8) | +| `--backoff-ms=N` | Basis-Wartezeit in ms fuer exponentielles Backoff (Standard: 1500) | + +## Umgebungsvariablen + +Alternativ zu den CLI-Optionen koennen diese Werte auch per Umgebungsvariable gesetzt werden: + +| Variable | Entspricht | +|---|---| +| `VISION_PROVIDER` | `--provider` | +| `VISION_CONCURRENCY` | `--concurrency` | +| `VISION_MAX_RETRIES` | `--retries` | +| `VISION_BASE_BACKOFF_MS` | `--backoff-ms` | + +CLI-Optionen haben Vorrang vor Umgebungsvariablen. + +## Beispiele + +```bash +# Neue Bilder ohne Sidecar verarbeiten (Anthropic) +pnpm run vision + +# Mit OpenAI statt Anthropic +pnpm run vision --provider=openai + +# Alle Sidecars in einem bestimmten Ordner neu generieren +pnpm run vision --refresh --provider=openai content/fotos/kollektionen/reisen/asien/thailand + +# Nur EXIF-Daten aktualisieren (z.B. nach erneutem Lightroom-Export) +pnpm run vision --exif-only + +# Mit hoeherer Parallelitaet +pnpm run vision --refresh --concurrency=4 +``` + +## Ausgabe + +Pro Bild wird eine JSON-Sidecar-Datei mit folgendem Inhalt erstellt: + +- `title` - 5 Titelvorschlaege (deutsch, via AI) +- `alt` - Bildbeschreibung / Alt-Text (deutsch, via AI) +- `tags` - 5 thematische Tags (deutsch, via AI) +- `date` - Aufnahmedatum (aus EXIF) +- `location` - GPS-Koordinaten (aus EXIF, falls vorhanden) +- `locationName` - Aufgeloester Ortsname via Nominatim (falls GPS vorhanden) +- `exif` - Kamera, Objektiv, Blende, ISO, Brennweite, Belichtungszeit + + +# Fix +bei OPENAI rate-limit mit einem gerigem Tier-Level +pnpm run vision --refresh --provider=openai --concurrency=1 content/fotos/kollektionen/reisen/asien/malaysia diff --git a/scripts/copy-sw.js b/scripts/copy-sw.js new file mode 100644 index 0000000..a656a86 --- /dev/null +++ b/scripts/copy-sw.js @@ -0,0 +1,17 @@ +// Copies sw.js + workbox-*.js from dist/server/ to dist/client/ after build. +// @astrojs/node standalone only serves static files from dist/client/, but +// @vite-pwa/astro generates the service worker into dist/server/ during the +// SSR Vite build pass. +import { copyFile, readdir } from "node:fs/promises"; +import { join } from "node:path"; + +const serverDir = "dist/server"; +const clientDir = "dist/client"; + +const files = await readdir(serverDir).catch(() => []); +for (const file of files) { + if (file === "sw.js" || file.startsWith("workbox-")) { + await copyFile(join(serverDir, file), join(clientDir, file)); + console.log(`[copy-sw] ${file} → dist/client/`); + } +} diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100755 index 0000000..c220008 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail + +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" +REMOTE_BASE='/opt/websites/adrian-altner.de' +REMOTE_URL='ssh://git@git.altner.cloud:2222/adrian/adrian-altner.de.git' +GIT_HOST='git.altner.cloud' +GIT_PORT='2222' + +# --- 1. Pull latest from repo --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + mkdir -p ~/.ssh && touch ~/.ssh/known_hosts && chmod 600 ~/.ssh/known_hosts + ssh-keygen -F '[$GIT_HOST]:$GIT_PORT' >/dev/null || ssh-keyscan -p '$GIT_PORT' '$GIT_HOST' >> ~/.ssh/known_hosts + git remote set-url origin '$REMOTE_URL' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production +" + +# --- 2. Build + deploy --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + sudo podman build -t localhost/adrian-altner.de:latest . + sudo systemctl restart podman-compose@adrian-altner.de.service + sudo podman container prune -f 2>/dev/null || true + sudo podman image prune --external -f 2>/dev/null || true + sudo podman image prune -f 2>/dev/null || true + sudo podman builder prune -af 2>/dev/null || true +" + +echo "Deploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions via webmention.app..." + for feed in rss.xml en/rss.xml; do + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/${feed}&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + done + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi diff --git a/scripts/fetch-favicons.mjs b/scripts/fetch-favicons.mjs new file mode 100644 index 0000000..9561bf9 --- /dev/null +++ b/scripts/fetch-favicons.mjs @@ -0,0 +1,74 @@ +/** + * Fetches favicons for all linked domains and saves them locally to public/favicons/. + * Run before astro build so favicons are served statically instead of via Google S2. + * Idempotent: skips domains that already have a cached favicon. + */ + +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const root = join(__dirname, ".."); +const linksPath = join(root, "src/content/links/links.json"); +const outDir = join(root, "public/favicons"); + +function getDomain(url) { + try { + return new URL(url).hostname.replace(/^www\./, ""); + } catch { + return null; + } +} + +function faviconPath(domain) { + return join(outDir, `${domain}.png`); +} + +async function fetchFavicon(domain) { + const url = `https://www.google.com/s2/favicons?domain=${domain}&sz=32`; + const res = await fetch(url); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const buf = await res.arrayBuffer(); + return Buffer.from(buf); +} + +async function main() { + const links = JSON.parse(readFileSync(linksPath, "utf-8")); + + const domains = [ + ...new Set(links.map((l) => getDomain(l.url)).filter(Boolean)), + ]; + + if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true }); + + let fetched = 0; + let skipped = 0; + + await Promise.all( + domains.map(async (domain) => { + const dest = faviconPath(domain); + if (existsSync(dest)) { + skipped++; + return; + } + try { + const data = await fetchFavicon(domain); + writeFileSync(dest, data); + fetched++; + console.log(` ✓ ${domain}`); + } catch (err) { + console.warn(` ✗ ${domain}: ${err.message}`); + } + }), + ); + + console.log( + `Favicons: ${fetched} fetched, ${skipped} cached, ${domains.length} total`, + ); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/scripts/metadata.ts b/scripts/metadata.ts new file mode 100644 index 0000000..9a25f3f --- /dev/null +++ b/scripts/metadata.ts @@ -0,0 +1,424 @@ +#!/usr/bin/env -S node --experimental-strip-types + +import { writeFile } from "node:fs/promises"; +import { basename, relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { consola } from "consola"; +import sharp from "sharp"; +import { + getImagesMissingMetadata, + getMetadataPathForImage, + getPhotoAbsolutePath, + getPhotoDirectories, + PHOTOS_DIRECTORY, +} from "../src/lib/photo-albums.ts"; + +const PHOTOS_DIR = PHOTOS_DIRECTORY; + +// ─── IPTC parser ──────────────────────────────────────────────────────────── + +interface IptcFields { + title?: string; + caption?: string; + keywords?: string[]; + dateCreated?: string; + timeCreated?: string; +} + +function parseIptc(buf: Buffer): IptcFields { + const fields: IptcFields = {}; + let i = 0; + + while (i < buf.length - 4) { + if (buf[i] !== 0x1c) { + i++; + continue; + } + + const record = buf[i + 1]; + const dataset = buf[i + 2]; + const len = buf.readUInt16BE(i + 3); + const value = buf.subarray(i + 5, i + 5 + len).toString("utf8"); + i += 5 + len; + + if (record !== 2) continue; + + switch (dataset) { + case 5: + fields.title = value; + break; + case 25: + fields.keywords ??= []; + fields.keywords.push(value); + break; + case 55: + fields.dateCreated = value; + break; + case 60: + fields.timeCreated = value; + break; + case 120: + fields.caption = value; + break; + } + } + + return fields; +} + +// ─── XMP parser ───────────────────────────────────────────────────────────── + +interface XmpFields { + title?: string; + description?: string; + keywords?: string[]; + lens?: string | undefined; + createDate?: string | undefined; +} + +function extractRdfLiValues(xml: string, tagName: string): string[] { + const re = new RegExp(`<${tagName}[^>]*>[\\s\\S]*?<\\/${tagName}>`, "i"); + const match = xml.match(re); + if (!match) return []; + + const liRe = /]*>([^<]*)<\/rdf:li>/gi; + const values: string[] = []; + for (let m = liRe.exec(match[0]); m !== null; m = liRe.exec(match[0])) { + if (m[1]?.trim()) values.push(m[1].trim()); + } + return values; +} + +function extractXmpAttr(xml: string, attr: string): string | undefined { + const re = new RegExp(`${attr}="([^"]*)"`, "i"); + return xml.match(re)?.[1] ?? undefined; +} + +function parseXmp(buf: Buffer): XmpFields { + const xml = buf.toString("utf8"); + const fields: XmpFields = {}; + + const titles = extractRdfLiValues(xml, "dc:title"); + if (titles[0]) fields.title = titles[0]; + + const descriptions = extractRdfLiValues(xml, "dc:description"); + if (descriptions[0]) fields.description = descriptions[0]; + + const subjects = extractRdfLiValues(xml, "dc:subject"); + if (subjects.length > 0) fields.keywords = subjects; + + fields.lens = extractXmpAttr(xml, "aux:Lens"); + fields.createDate = extractXmpAttr(xml, "xmp:CreateDate"); + + return fields; +} + +// ─── EXIF parser (minimal TIFF IFD0 + SubIFD) ────────────────────────────── + +interface ExifFields { + model?: string; + lensModel?: string; + fNumber?: number; + focalLength?: string; + exposureTime?: string; + iso?: number; + dateTimeOriginal?: string; + gpsLatitude?: string; + gpsLongitude?: string; + gpsLatitudeRef?: string; + gpsLongitudeRef?: string; +} + +function parseExifBuffer(buf: Buffer): ExifFields { + // Skip "Exif\0\0" header if present + let offset = 0; + if ( + buf[0] === 0x45 && + buf[1] === 0x78 && + buf[2] === 0x69 && + buf[3] === 0x66 + ) { + offset = 6; + } + + const isLE = buf[offset] === 0x49; // "II" = little endian + const read16 = isLE + ? (o: number) => buf.readUInt16LE(offset + o) + : (o: number) => buf.readUInt16BE(offset + o); + const read32 = isLE + ? (o: number) => buf.readUInt32LE(offset + o) + : (o: number) => buf.readUInt32BE(offset + o); + + const readRational = (o: number): number => { + const num = read32(o); + const den = read32(o + 4); + return den === 0 ? 0 : num / den; + }; + + const readString = (o: number, len: number): string => { + return buf + .subarray(offset + o, offset + o + len) + .toString("ascii") + .replace(/\0+$/, ""); + }; + + const fields: ExifFields = {}; + + const parseIfd = (ifdOffset: number, parseGps = false) => { + if (ifdOffset + 2 > buf.length - offset) return; + const count = read16(ifdOffset); + + for (let i = 0; i < count; i++) { + const entryOffset = ifdOffset + 2 + i * 12; + if (entryOffset + 12 > buf.length - offset) break; + + const tag = read16(entryOffset); + const type = read16(entryOffset + 2); + const numValues = read32(entryOffset + 4); + const valueOffset = read32(entryOffset + 8); + + // For values that fit in 4 bytes, data is inline at entryOffset+8 + const dataOffset = + type === 2 && numValues <= 4 + ? entryOffset + 8 + : type === 5 || numValues > 4 + ? valueOffset + : entryOffset + 8; + + if (parseGps) { + switch (tag) { + case 1: // GPSLatitudeRef + fields.gpsLatitudeRef = readString(entryOffset + 8, 2); + break; + case 2: // GPSLatitude + if (dataOffset + 24 <= buf.length - offset) { + const d = readRational(dataOffset); + const m = readRational(dataOffset + 8); + const s = readRational(dataOffset + 16); + fields.gpsLatitude = `${d} deg ${Math.floor(m)}' ${s.toFixed(2)}"`; + } + break; + case 3: // GPSLongitudeRef + fields.gpsLongitudeRef = readString(entryOffset + 8, 2); + break; + case 4: // GPSLongitude + if (dataOffset + 24 <= buf.length - offset) { + const d = readRational(dataOffset); + const m = readRational(dataOffset + 8); + const s = readRational(dataOffset + 16); + fields.gpsLongitude = `${d} deg ${Math.floor(m)}' ${s.toFixed(2)}"`; + } + break; + } + continue; + } + + switch (tag) { + case 0x0110: // Model + if (dataOffset + numValues <= buf.length - offset) { + fields.model = readString(dataOffset, numValues); + } + break; + case 0x8769: // ExifIFD pointer + parseIfd(valueOffset); + break; + case 0x8825: // GPS IFD pointer + parseIfd(valueOffset, true); + break; + case 0x829a: // ExposureTime + if (dataOffset + 8 <= buf.length - offset) { + const num = read32(dataOffset); + const den = read32(dataOffset + 4); + fields.exposureTime = + den > num ? `1/${Math.round(den / num)}` : `${num / den}`; + } + break; + case 0x829d: // FNumber + if (dataOffset + 8 <= buf.length - offset) { + fields.fNumber = readRational(dataOffset); + } + break; + case 0x8827: // ISO + fields.iso = type === 3 ? read16(entryOffset + 8) : valueOffset; + break; + case 0x9003: // DateTimeOriginal + if (dataOffset + numValues <= buf.length - offset) { + fields.dateTimeOriginal = readString(dataOffset, numValues); + } + break; + case 0x920a: // FocalLength + if (dataOffset + 8 <= buf.length - offset) { + const fl = readRational(dataOffset); + fields.focalLength = fl.toFixed(1).replace(/\.0$/, ""); + } + break; + case 0xa434: // LensModel + if (dataOffset + numValues <= buf.length - offset) { + fields.lensModel = readString(dataOffset, numValues); + } + break; + } + } + }; + + const ifdOffset = read32(4); + parseIfd(ifdOffset); + + return fields; +} + +// ─── Merged metadata ──────────────────────────────────────────────────────── + +interface ImageMetadata { + id: string; + title: string[]; + image: string; + alt: string; + location: string; + date: string; + tags: string[]; + exif: { + camera: string; + lens: string; + aperture: string; + iso: string; + focal_length: string; + shutter_speed: string; + }; +} + +function formatGpsLocation(exif: ExifFields): string { + if (!exif.gpsLatitude || !exif.gpsLongitude) return ""; + + const latRef = exif.gpsLatitudeRef ?? "N"; + const lonRef = exif.gpsLongitudeRef ?? "E"; + return `${exif.gpsLatitude} ${latRef}, ${exif.gpsLongitude} ${lonRef}`; +} + +function formatDate(raw: string | undefined): string { + if (!raw) return ""; + + // Handle "YYYY:MM:DD HH:MM:SS" or "YYYYMMDD" or "YYYY-MM-DDTHH:MM:SS" + if (/^\d{8}$/.test(raw)) { + return `${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`; + } + + const [datePart] = raw.split(/[T ]/); + if (!datePart) return ""; + return datePart.replaceAll(":", "-"); +} + +async function extractMetadata(imagePath: string): Promise { + const meta = await sharp(imagePath).metadata(); + const fileName = basename(imagePath); + + const iptc = meta.iptc ? parseIptc(meta.iptc) : ({} as IptcFields); + const xmp = meta.xmp ? parseXmp(meta.xmp) : ({} as XmpFields); + const exif = meta.exif ? parseExifBuffer(meta.exif) : ({} as ExifFields); + + const title = iptc.title || xmp.title || ""; + const caption = iptc.caption || xmp.description || ""; + const keywords = iptc.keywords ?? xmp.keywords ?? []; + const date = formatDate( + exif.dateTimeOriginal ?? xmp.createDate ?? iptc.dateCreated, + ); + + if (!title && !caption) { + consola.warn(`No title or caption found in ${fileName}`); + } + + return { + id: fileName.replace(/\.jpg$/i, ""), + title: title ? [title] : [], + image: `./${fileName}`, + alt: caption, + location: formatGpsLocation(exif), + date, + tags: keywords, + exif: { + camera: exif.model ?? "", + lens: exif.lensModel || xmp.lens || "", + aperture: exif.fNumber?.toString() ?? "", + iso: exif.iso?.toString() ?? "", + focal_length: exif.focalLength?.replace(/ mm$/, "") ?? "", + shutter_speed: exif.exposureTime ?? "", + }, + }; +} + +// ─── CLI ──────────────────────────────────────────────────────────────────── + +interface CliOptions { + refresh: boolean; + photosDirectory: string; +} + +function parseCliOptions(argv: string[]): CliOptions { + const nonFlagArgs = argv.filter((arg) => !arg.startsWith("--")); + return { + refresh: argv.includes("--refresh"), + photosDirectory: resolve(nonFlagArgs[0] ?? PHOTOS_DIR), + }; +} + +async function getImagesToProcess( + photosDirectory: string, + options: Pick, +): Promise { + const relativeImagePaths = options.refresh + ? (await getPhotoDirectories(photosDirectory)).flatMap((d) => d.imagePaths) + : await getImagesMissingMetadata(photosDirectory); + + consola.info( + options.refresh + ? `Refreshing ${relativeImagePaths.length} image(s)` + : `Found ${relativeImagePaths.length} image(s) without metadata`, + ); + + return relativeImagePaths.map((p) => + getPhotoAbsolutePath(p, photosDirectory), + ); +} + +async function main() { + consola.start("Checking for images to process..."); + const opts = parseCliOptions(process.argv.slice(2)); + + const images = await getImagesToProcess(opts.photosDirectory, opts); + + if (images.length === 0) { + consola.success( + opts.refresh + ? "No images found to refresh." + : "No images require metadata.", + ); + return; + } + + for (let i = 0; i < images.length; i++) { + const imagePath = images[i] as string; + const rel = relative(process.cwd(), imagePath); + consola.info(`Processing ${i + 1}/${images.length}: ${rel}`); + + const metadata = await extractMetadata(imagePath); + const relativeImagePath = relative(opts.photosDirectory, imagePath); + const jsonPath = getMetadataPathForImage( + relativeImagePath, + opts.photosDirectory, + ); + + await writeFile(jsonPath, JSON.stringify(metadata, null, 2)); + consola.info(`Wrote ${relative(process.cwd(), jsonPath)}`); + } + + consola.success(`Processed ${images.length} image(s).`); +} + +if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) { + try { + await main(); + } catch (error) { + consola.error(error); + process.exit(1); + } +} diff --git a/scripts/new-note-mdx-prompt.sh b/scripts/new-note-mdx-prompt.sh new file mode 100755 index 0000000..79d96b3 --- /dev/null +++ b/scripts/new-note-mdx-prompt.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Standalone wrapper für Obsidian Script Runner — neue Note mit Cover-Bild (MDX) +set -euo pipefail + +VAULT='/Users/adrian/Obsidian/Web/adrian-altner-com' + +TITLE=$(osascript \ + -e 'Tell application "System Events" to display dialog "Note title (with cover):" default answer ""' \ + -e 'text returned of result' 2>/dev/null) || exit 0 + +if [[ -z "$TITLE" ]]; then exit 0; fi + +SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ \+/-/g' | sed 's/^-\+//;s/-\+$//') +DATE_FOLDER=$(date +%Y/%m/%d) +PUBLISH_DATE=$(date +%Y-%m-%d) +DIR="$VAULT/content/notes/$DATE_FOLDER" +FILE="$DIR/$SLUG.mdx" + +mkdir -p "$DIR" + +if [[ -f "$FILE" ]]; then + osascript -e "display notification \"File already exists: $SLUG.mdx\" with title \"New Note\"" 2>/dev/null || true + exit 1 +fi + +cat > "$FILE" << EOF +--- +title: "$TITLE" +publishDate: $PUBLISH_DATE +description: "" +cover: "./$SLUG.jpg" +coverAlt: "" +tags: + - +draft: false +syndication: +--- +EOF + +echo "Created: $FILE" diff --git a/scripts/new-note-prompt.sh b/scripts/new-note-prompt.sh new file mode 100755 index 0000000..abb1d5f --- /dev/null +++ b/scripts/new-note-prompt.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Standalone wrapper für Obsidian Script Runner — neue Note anlegen +set -euo pipefail + +VAULT='/Users/adrian/Obsidian/Web/adrian-altner-com' + +TITLE=$(osascript \ + -e 'Tell application "System Events" to display dialog "Note title:" default answer ""' \ + -e 'text returned of result' 2>/dev/null) || exit 0 + +if [[ -z "$TITLE" ]]; then exit 0; fi + +SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ \+/-/g' | sed 's/^-\+//;s/-\+$//') +DATE_FOLDER=$(date +%Y/%m/%d) +PUBLISH_DATE=$(date +%Y-%m-%d) +DIR="$VAULT/content/notes/$DATE_FOLDER" +FILE="$DIR/$SLUG.md" + +mkdir -p "$DIR" + +if [[ -f "$FILE" ]]; then + osascript -e "display notification \"File already exists: $SLUG.md\" with title \"New Note\"" 2>/dev/null || true + exit 1 +fi + +cat > "$FILE" << EOF +--- +title: "$TITLE" +publishDate: $PUBLISH_DATE +description: "" +tags: + - +draft: false +syndication: +--- +EOF + +echo "Created: $FILE" diff --git a/scripts/new-note.sh b/scripts/new-note.sh new file mode 100755 index 0000000..cb9d271 --- /dev/null +++ b/scripts/new-note.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Usage: new-note.sh "Note Title" [--mdx] +# Creates a new note in the Obsidian vault with correct frontmatter and folder structure. +# Use --mdx for notes that need a cover image or custom components (creates .mdx file). +set -euo pipefail + +VAULT='/Users/adrian/Obsidian/Web/adrian-altner-com' + +if [[ -z "${1:-}" ]]; then + echo "Usage: new-note.sh \"Note Title\" [--mdx]" >&2 + exit 1 +fi + +TITLE="$1" +MDX=false +if [[ "${2:-}" == "--mdx" ]]; then + MDX=true +fi + +SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ \+/-/g' | sed 's/^-\+//;s/-\+$//') +DATE_FOLDER=$(date +%Y/%m/%d) +PUBLISH_DATE=$(date +%Y-%m-%d) +DIR="$VAULT/content/notes/$DATE_FOLDER" + +if $MDX; then + EXT="mdx" +else + EXT="md" +fi + +FILE="$DIR/$SLUG.$EXT" + +mkdir -p "$DIR" + +if [[ -f "$FILE" ]]; then + echo "File already exists: $FILE" >&2 + exit 1 +fi + +if $MDX; then + cat > "$FILE" << EOF +--- +title: "$TITLE" +publishDate: $PUBLISH_DATE +description: "" +cover: "./$SLUG.jpg" +coverAlt: "" +tags: + - +draft: false +syndication: +--- +EOF +else + cat > "$FILE" << EOF +--- +title: "$TITLE" +publishDate: $PUBLISH_DATE +description: "" +tags: + - +draft: false +syndication: +--- +EOF +fi + +echo "Created: $FILE" diff --git a/scripts/new-post-prompt.sh b/scripts/new-post-prompt.sh new file mode 100755 index 0000000..69ad081 --- /dev/null +++ b/scripts/new-post-prompt.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Standalone wrapper für Obsidian Script Runner — neuen Blog-Post anlegen +set -euo pipefail + +VAULT='/Users/adrian/Obsidian/Web/adrian-altner-com' + +TITLE=$(osascript \ + -e 'Tell application "System Events" to display dialog "Post title:" default answer ""' \ + -e 'text returned of result' 2>/dev/null) || exit 0 + +if [[ -z "$TITLE" ]]; then exit 0; fi + +SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ \+/-/g' | sed 's/^-\+//;s/-\+$//') +DATE_FOLDER=$(date +%Y/%m/%d) +PUBLISH_DATE=$(date +%Y-%m-%dT%H:%M:%S%z) +DIR="$VAULT/content/blog/posts/$DATE_FOLDER" +FILE="$DIR/$SLUG.md" + +mkdir -p "$DIR" + +if [[ -f "$FILE" ]]; then + osascript -e "display notification \"File already exists: $SLUG.md\" with title \"New Post\"" 2>/dev/null || true + exit 1 +fi + +cat > "$FILE" << EOF +--- +title: "$TITLE" +description: "" +publishDate: $PUBLISH_DATE +tags: + - +draft: true +syndication: +--- +EOF + +echo "Created: $FILE" diff --git a/scripts/new-post.sh b/scripts/new-post.sh new file mode 100755 index 0000000..21e393d --- /dev/null +++ b/scripts/new-post.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# Usage: new-post.sh "Post Title" +# Creates a new blog post in the Obsidian vault with correct frontmatter and folder structure. +set -euo pipefail + +VAULT='/Users/adrian/Obsidian/Web/adrian-altner-com' + +if [[ -z "${1:-}" ]]; then + echo "Usage: new-post.sh \"Post Title\"" >&2 + exit 1 +fi + +TITLE="$1" +SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ \+/-/g' | sed 's/^-\+//;s/-\+$//') +DATE_FOLDER=$(date +%Y/%m/%d) +PUBLISH_DATE=$(date +%Y-%m-%dT%H:%M:%S%z) +DIR="$VAULT/content/blog/posts/$DATE_FOLDER" +FILE="$DIR/$SLUG.md" + +mkdir -p "$DIR" + +if [[ -f "$FILE" ]]; then + echo "File already exists: $FILE" >&2 + exit 1 +fi + +cat > "$FILE" << EOF +--- +title: "$TITLE" +description: "" +publishDate: $PUBLISH_DATE +tags: + - +draft: true +syndication: +--- +EOF + +echo "Created: $FILE" diff --git a/scripts/publish-all.sh b/scripts/publish-all.sh new file mode 100755 index 0000000..ec42d4f --- /dev/null +++ b/scripts/publish-all.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + +VAULT_CONTENT='/Users/adrian/Library/Mobile Documents/iCloud~md~obsidian/Documents/03 Bereiche/Webseite/adrian-altner-de/content' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/adrian-altner.de' +REMOTE_CONTENT="${REMOTE_BASE}/src/content" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_CONTENT' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --include='*.jpg' \ + --include='*.jpeg' \ + --include='*.png' \ + --include='*.PNG' \ + --include='*.JPG' \ + --include='*.JPEG' \ + --include='*.json' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_CONTENT/" "$VPS:$REMOTE_CONTENT/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + sudo podman build -t localhost/adrian-altner.de:latest . + sudo systemctl restart podman-compose@adrian-altner.de.service + sudo podman container prune -f 2>/dev/null || true + sudo podman image prune --external -f 2>/dev/null || true + sudo podman image prune -f 2>/dev/null || true + sudo podman builder prune -af 2>/dev/null || true +" + +echo "Redeploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions via webmention.app..." + for feed in rss/blog.xml rss/fotos.xml; do + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/${feed}&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + done + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi \ No newline at end of file diff --git a/scripts/publish-blog.sh b/scripts/publish-blog.sh new file mode 100755 index 0000000..f79811e --- /dev/null +++ b/scripts/publish-blog.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Usage: publish-blog.sh [vps-host] [branch] +# Can be called from any directory — no dependency on the repo being the working dir. +set -euo pipefail + +VAULT_BLOG='/Users/adrian/Obsidian/Web/adrian-altner-com/content/blog' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/www.adrian-altner.de' +REMOTE_BLOG="${REMOTE_BASE}/src/content/blog" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_BLOG' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --include='*.jpg' \ + --include='*.jpeg' \ + --include='*.JPG' \ + --include='*.JPEG' \ + --include='*.png' \ + --include='*.PNG' \ + --include='*.webp' \ + --include='*.gif' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_BLOG/" "$VPS:$REMOTE_BLOG/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + + podman-compose -f compose.yml up --build -d --force-recreate + + podman image prune -af + podman builder prune -af || true +" + +echo "Blog deploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions..." + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/rss/blog.xml&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi diff --git a/scripts/publish-links.sh b/scripts/publish-links.sh new file mode 100755 index 0000000..c216f8e --- /dev/null +++ b/scripts/publish-links.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Usage: publish-links.sh [vps-host] [branch] +# Can be called from any directory — no dependency on the repo being the working dir. +set -euo pipefail + +VAULT_LINKS='/Users/adrian/Obsidian/Web/adrian-altner-com/content/links' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/www.adrian-altner.de' +REMOTE_LINKS="${REMOTE_BASE}/src/content/links" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_LINKS' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_LINKS/" "$VPS:$REMOTE_LINKS/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + podman-compose -f compose.yml up --build -d --force-recreate + podman image prune -af + podman builder prune -af +" + +echo "Links deploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions..." + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/rss/links.xml&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi diff --git a/scripts/publish-notes.sh b/scripts/publish-notes.sh new file mode 100755 index 0000000..dd21b4a --- /dev/null +++ b/scripts/publish-notes.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Usage: publish-notes.sh [vps-host] [branch] +# Can be called from any directory — no dependency on the repo being the working dir. +set -euo pipefail + +VAULT_NOTES='/Users/adrian/Obsidian/Web/adrian-altner-com/content/notes' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/www.adrian-altner.de' +REMOTE_NOTES="${REMOTE_BASE}/src/content/notes" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_NOTES' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --include='*.jpg' \ + --include='*.jpeg' \ + --include='*.JPG' \ + --include='*.JPEG' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_NOTES/" "$VPS:$REMOTE_NOTES/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + + podman-compose -f compose.yml up --build -d --force-recreate + + podman image prune -af + podman builder prune -af +" + +echo "Notes deploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions..." + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/rss/notes.xml&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi diff --git a/scripts/publish-photos.sh b/scripts/publish-photos.sh new file mode 100755 index 0000000..c01bb8e --- /dev/null +++ b/scripts/publish-photos.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Usage: publish-photos.sh [vps-host] [branch] +# Can be called from any directory — no dependency on the repo being the working dir. +set -euo pipefail + +VAULT_PHOTOS='/Users/adrian/Obsidian/Web/adrian-altner-com/content/photos' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/www.adrian-altner.de' +REMOTE_PHOTOS="${REMOTE_BASE}/src/content/photos" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_PHOTOS' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --include='*.jpg' \ + --include='*.jpeg' \ + --include='*.JPG' \ + --include='*.JPEG' \ + --include='*.json' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_PHOTOS/" "$VPS:$REMOTE_PHOTOS/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + podman-compose -f compose.yml up --build -d --force-recreate + podman image prune -af + podman builder prune -af +" + +echo "Photos deploy done via $VPS (branch: $REMOTE_BRANCH)." + +# --- 3. Webmentions --- +WEBMENTION_APP_TOKEN="$(ssh "$VPS" "grep '^WEBMENTION_APP_TOKEN=' '$REMOTE_BASE/.env.production' | cut -d= -f2-" 2>/dev/null || true)" +if [[ -n "$WEBMENTION_APP_TOKEN" ]]; then + echo "Sending webmentions..." + curl -s -X POST "https://webmention.app/check?url=https://adrian-altner.de/rss/photos.xml&token=${WEBMENTION_APP_TOKEN}" \ + | grep -o '"status":"[^"]*"' || true + echo "Webmentions triggered." +else + echo "No WEBMENTION_APP_TOKEN in .env.production — skipping webmentions." +fi diff --git a/scripts/publish-projects.sh b/scripts/publish-projects.sh new file mode 100755 index 0000000..4694b76 --- /dev/null +++ b/scripts/publish-projects.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Usage: publish-projects.sh [vps-host] [branch] +# Can be called from any directory — no dependency on the repo being the working dir. +set -euo pipefail + +VAULT_PROJECTS='/Users/adrian/Obsidian/Web/adrian-altner-com/content/projects' +VPS="${1:-hetzner}" +REMOTE_BRANCH="${2:-main}" + +REMOTE_BASE='/opt/websites/www.adrian-altner.de' +REMOTE_PROJECTS="${REMOTE_BASE}/src/content/projects" + +# --- 1. Sync vault to VPS --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + git fetch --prune origin '$REMOTE_BRANCH' + git checkout '$REMOTE_BRANCH' + git reset --hard 'origin/$REMOTE_BRANCH' + git clean -fd -e .env -e .env.production + mkdir -p '$REMOTE_PROJECTS' +" + +rsync -az --delete \ + --include='*/' \ + --include='*.md' \ + --include='*.mdx' \ + --include='*.jpg' \ + --include='*.jpeg' \ + --include='*.JPG' \ + --include='*.JPEG' \ + --include='*.png' \ + --include='*.PNG' \ + --include='*.webp' \ + --include='*.gif' \ + --exclude='.DS_Store' \ + --exclude='*' \ + "$VAULT_PROJECTS/" "$VPS:$REMOTE_PROJECTS/" + +# --- 2. Build + cleanup --- +ssh "$VPS" " + set -euo pipefail + cd '$REMOTE_BASE' + podman-compose -f compose.yml up --build -d --force-recreate + podman image prune -af + podman builder prune -af +" + +echo "Projects deploy done via $VPS (branch: $REMOTE_BRANCH)." diff --git a/scripts/squash-history.sh b/scripts/squash-history.sh new file mode 100755 index 0000000..d5c5264 --- /dev/null +++ b/scripts/squash-history.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# squash-history.sh — Replaces entire git history with a single "init" commit. +# WARNING: Destructive and irreversible. Force-pushes to remote. + +set -euo pipefail + +COMMIT_MSG="${1:-init}" +REMOTE="${2:-origin}" +BRANCH="main" +TEMP="temp-squash-$$" + +echo "⚠️ This will destroy all git history and force-push to $REMOTE/$BRANCH." +read -r -p "Continue? [y/N] " confirm +[[ "$confirm" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; } + +git checkout --orphan "$TEMP" +git add -A +git commit -m "$COMMIT_MSG" +git branch -D "$BRANCH" +git branch -m "$TEMP" "$BRANCH" +git push --force "$REMOTE" "$BRANCH" + +echo "Done. $(git log --oneline)" diff --git a/scripts/vision.spec.ts b/scripts/vision.spec.ts new file mode 100644 index 0000000..6513b1e --- /dev/null +++ b/scripts/vision.spec.ts @@ -0,0 +1,91 @@ +import assert from "node:assert/strict"; +import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import type { + ExifMetadata, + ImageMetadataSuggestion, + VisionAIResult, +} from "./vision.ts"; +import { getImagesToProcess, mergeMetaAndVisionData } from "./vision.ts"; + +const FINAL: ImageMetadataSuggestion = { + id: "2R9A2805", + title: [ + "Blossom and Buzz", + "Spring's Gentle Awakening", + "Cherry Blossom Haven", + "Nature's Delicate Balance", + "A Bee's Spring Feast", + ], + image: "./2R9A2805.jpg", + alt: "Close-up of vibrant pink cherry blossoms on a branch with a honeybee collecting nectar. The bee's wings are slightly blurred, capturing its motion as it works. The background is a soft, dreamy pink hue, complementing the sharp details of the blossoms and the bee.", + location: "48 deg 8' 37.56\" N, 11 deg 34' 13.32\" E", + date: "2024-03-17", + tags: ["nature", "cherryblossom", "bee", "spring", "floral"], + exif: { + camera: "Canon EOS R6m2", + lens: "RF70-200mm F2.8 L IS USM", + aperture: "2.8", + iso: "125", + focal_length: "200.0", + shutter_speed: "1/1000", + }, +}; + +const VISION_DATA: VisionAIResult = { + title_ideas: [ + "Blossom and Buzz", + "Spring's Gentle Awakening", + "Cherry Blossom Haven", + "Nature's Delicate Balance", + "A Bee's Spring Feast", + ], + description: + "Close-up of vibrant pink cherry blossoms on a branch with a honeybee collecting nectar. The bee's wings are slightly blurred, capturing its motion as it works. The background is a soft, dreamy pink hue, complementing the sharp details of the blossoms and the bee.", + tags: ["nature", "cherryblossom", "bee", "spring", "floral"], +}; + +const EXIF_DATA: ExifMetadata = { + SourceFile: "/Users/flori/Sites/flori-dev/src/content/grid/2R9A2805.jpg", + FileName: "2R9A2805.jpg", + Model: "Canon EOS R6m2", + ExposureTime: "1/1000", + FNumber: 2.8, + ISO: 125, + DateTimeOriginal: "2024:03:17 15:06:16", + FocalLength: "200.0 mm", + LensModel: "RF70-200mm F2.8 L IS USM", + GPSPosition: "48 deg 8' 37.56\" N, 11 deg 34' 13.32\" E", +}; + +async function main() { + const tempRoot = await mkdtemp(join(tmpdir(), "vision-photos-")); + + try { + assert.deepEqual(mergeMetaAndVisionData(EXIF_DATA, VISION_DATA), FINAL); + + const albumDirectory = join(tempRoot, "chiang-mai"); + const missingImage = join(albumDirectory, "2025-10-06-121017.jpg"); + const completeImage = join(albumDirectory, "2025-10-06-121212.jpg"); + + await mkdir(albumDirectory, { recursive: true }); + await writeFile(missingImage, ""); + await writeFile(completeImage, ""); + await writeFile(join(albumDirectory, "2025-10-06-121212.json"), "{}"); + + assert.deepEqual(await getImagesToProcess(tempRoot), [missingImage]); + assert.deepEqual( + await getImagesToProcess(tempRoot, { refresh: true, exifOnly: false }), + [missingImage, completeImage], + ); + assert.deepEqual( + await getImagesToProcess(tempRoot, { refresh: false, exifOnly: true }), + [completeImage], + ); + } finally { + await rm(tempRoot, { recursive: true, force: true }); + } +} + +await main(); diff --git a/scripts/vision.ts b/scripts/vision.ts new file mode 100644 index 0000000..5db01b7 --- /dev/null +++ b/scripts/vision.ts @@ -0,0 +1,820 @@ +#!/usr/bin/env -S node --experimental-strip-types + +import { execFile } from "node:child_process"; +import { readFile, writeFile } from "node:fs/promises"; +import { relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import Anthropic from "@anthropic-ai/sdk"; +import { consola } from "consola"; +import OpenAI from "openai"; +import sharp from "sharp"; +import { + getImagesMissingMetadata, + getImagesWithExistingMetadata, + getMetadataPathForImage, + getPhotoAbsolutePath, + getPhotoDirectories, + PHOTOS_DIRECTORY, +} from "../src/lib/photo-albums.ts"; + +const execFileAsync = promisify(execFile); + +/** + * Define the directory where the images are located. + */ +const PHOTOS_DIR = PHOTOS_DIRECTORY; + +/** + * Instantiate the Anthropic client. + */ +type VisionProvider = "anthropic" | "openai"; + +let anthropic: Anthropic | undefined; +let openai: OpenAI | undefined; + +function getAnthropicClient(): Anthropic { + anthropic ??= new Anthropic({ maxRetries: 0 }); + return anthropic; +} + +function getOpenAIClient(): OpenAI { + openai ??= new OpenAI({ maxRetries: 0 }); + return openai; +} + +function assertRequiredEnvironment(provider: VisionProvider): void { + if (provider === "anthropic" && !process.env.ANTHROPIC_API_KEY) { + throw new Error( + "Missing ANTHROPIC_API_KEY. `pnpm run vision` loads `.env.local` automatically. If you run the script directly, use `node --env-file=.env.local --experimental-strip-types scripts/vision.ts`.", + ); + } + if (provider === "openai" && !process.env.OPENAI_API_KEY) { + throw new Error("Missing OPENAI_API_KEY. Set it in `.env.local`."); + } +} + +/** + * Represents the metadata of an image in the Exif format. + */ +export interface ExifMetadata { + SourceFile: string; + FileName: string; + Model: string; + FNumber: number; + FocalLength: string; + ExposureTime: string; + ISO: number; + DateTimeOriginal: string; + LensModel: string; + GPSPosition?: string; + GPSLatitude?: string; + GPSLongitude?: string; + Keywords?: string | string[]; + Subject?: string | string[]; + Title?: string; + "Caption-Abstract"?: string; +} + +/** + * Represents the result of the AI analysis. + */ +export interface VisionAIResult { + title_ideas: string[]; + description: string; + tags: string[]; +} + +/** + * Represents the final metadata suggestion for an image. + */ +export interface ImageMetadataSuggestion { + id: string; + title: string[]; + image: string; + alt: string; + location: string; + locationName?: string; + date: string; + tags: string[]; + exif: { + camera: string; + lens: string; + aperture: string; + iso: string; + focal_length: string; + shutter_speed: string; + }; +} + +interface VisionCliOptions { + refresh: boolean; + exifOnly: boolean; + photosDirectory?: string; + visionConcurrency: number; + visionMaxRetries: number; + visionBaseBackoffMs: number; + provider: VisionProvider; +} + +function parseCliOptions(argv: string[]): VisionCliOptions { + const getNumericOption = (name: string, fallback: number): number => { + const prefix = `--${name}=`; + const rawValue = argv + .find((arg) => arg.startsWith(prefix)) + ?.slice(prefix.length); + const parsed = Number.parseInt(rawValue ?? "", 10); + return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; + }; + + const envConcurrency = Number.parseInt( + process.env.VISION_CONCURRENCY ?? "", + 10, + ); + const envMaxRetries = Number.parseInt( + process.env.VISION_MAX_RETRIES ?? "", + 10, + ); + const envBaseBackoffMs = Number.parseInt( + process.env.VISION_BASE_BACKOFF_MS ?? "", + 10, + ); + const nonFlagArgs = argv.filter((arg) => !arg.startsWith("--")); + + const providerArg = argv + .find((arg) => arg.startsWith("--provider=")) + ?.slice("--provider=".length); + const envProvider = process.env.VISION_PROVIDER; + const rawProvider = providerArg ?? envProvider ?? "anthropic"; + const provider: VisionProvider = + rawProvider === "openai" ? "openai" : "anthropic"; + + return { + refresh: argv.includes("--refresh"), + exifOnly: argv.includes("--exif-only"), + provider, + photosDirectory: resolve(nonFlagArgs[0] ?? PHOTOS_DIR), + visionConcurrency: getNumericOption( + "concurrency", + Number.isFinite(envConcurrency) && envConcurrency > 0 + ? envConcurrency + : 2, + ), + visionMaxRetries: getNumericOption( + "retries", + Number.isFinite(envMaxRetries) && envMaxRetries > 0 ? envMaxRetries : 8, + ), + visionBaseBackoffMs: getNumericOption( + "backoff-ms", + Number.isFinite(envBaseBackoffMs) && envBaseBackoffMs > 0 + ? envBaseBackoffMs + : 1500, + ), + }; +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function isRateLimitError(error: unknown): boolean { + return error instanceof Anthropic.RateLimitError; +} + +function extractRetryAfterMs(error: unknown): number | null { + if (!(error instanceof Anthropic.RateLimitError)) { + return null; + } + + const retryAfter = error.headers?.get("retry-after"); + if (retryAfter) { + const seconds = Number.parseFloat(retryAfter); + if (Number.isFinite(seconds) && seconds > 0) { + return Math.ceil(seconds * 1000); + } + } + + return null; +} + +async function mapWithConcurrency( + values: T[], + concurrency: number, + mapper: (value: T, index: number) => Promise, +): Promise { + if (values.length === 0) { + return []; + } + + const results: R[] = new Array(values.length); + const workerCount = Math.max(1, Math.min(concurrency, values.length)); + let cursor = 0; + + const workers = Array.from({ length: workerCount }, async () => { + while (true) { + const currentIndex = cursor; + cursor += 1; + + if (currentIndex >= values.length) { + return; + } + + const value = values[currentIndex]; + if (typeof value === "undefined") { + continue; + } + + results[currentIndex] = await mapper(value, currentIndex); + } + }); + + await Promise.all(workers); + return results; +} + +/** + * Get all images that don't have a JSON file and therefore need to be processed. + */ +export async function getImagesToProcess( + photosDirectory = PHOTOS_DIR, + options: Pick = { + refresh: false, + exifOnly: false, + }, +): Promise { + let relativeImagePaths: string[]; + let label: string; + + if (options.exifOnly) { + relativeImagePaths = await getImagesWithExistingMetadata(photosDirectory); + label = `Found ${relativeImagePaths.length} ${relativeImagePaths.length === 1 ? "image" : "images"} with existing metadata (EXIF-only update)`; + } else if (options.refresh) { + relativeImagePaths = (await getPhotoDirectories(photosDirectory)).flatMap( + (directory) => directory.imagePaths, + ); + label = `Refreshing ${relativeImagePaths.length} ${relativeImagePaths.length === 1 ? "image" : "images"} with metadata sidecars`; + } else { + relativeImagePaths = await getImagesMissingMetadata(photosDirectory); + label = `Found ${relativeImagePaths.length} ${relativeImagePaths.length === 1 ? "image" : "images"} without metadata`; + } + + consola.info(label); + + return relativeImagePaths.map((imagePath) => + getPhotoAbsolutePath(imagePath, photosDirectory), + ); +} + +/** + * Reads an existing JSON sidecar for an image, preserving all fields. + */ +async function readExistingJsonSidecar( + imagePath: string, + photosDirectory: string, +): Promise> { + const relativeImagePath = relative(photosDirectory, imagePath); + const jsonPath = getMetadataPathForImage(relativeImagePath, photosDirectory); + const content = await readFile(jsonPath, "utf-8"); + return JSON.parse(content) as Record; +} + +/** + * Updates only the EXIF-derived fields in an existing metadata object, + * preserving all other fields (title, alt, tags, flickrId, etc.). + */ +export function mergeExifIntoExisting( + exifData: ExifMetadata, + existing: Record, + locationName?: string | null, +): Record { + const [date] = exifData.DateTimeOriginal.split(" "); + + if (!date) { + throw new Error(`Missing original date for ${exifData.SourceFile}.`); + } + + const result: Record = { + ...existing, + location: getLocationFromExif(exifData), + date: date.replaceAll(":", "-"), + exif: { + camera: exifData.Model, + lens: exifData.LensModel, + aperture: exifData.FNumber.toString(), + iso: exifData.ISO.toString(), + focal_length: exifData.FocalLength.replace(" mm", ""), + shutter_speed: exifData.ExposureTime, + }, + }; + + if (locationName) { + result.locationName = locationName; + } + + return result; +} + +/** + * Extracts the EXIF metadata from an image file. + * @param imagePath - The path to the image file. + * + * @returns A promise that resolves to the extracted EXIF metadata. + */ +export async function extractExifMetadata( + imagePath: string, +): Promise { + /// Check if `exiftool` is installed. + try { + await execFileAsync("exiftool", ["--version"]); + } catch (_error) { + consola.error( + "exiftool is not installed. Please run `brew install exiftool`.", + ); + process.exit(1); + } + + /// Extract the metadata + const { stdout } = await execFileAsync("exiftool", ["-j", imagePath]); + const output = JSON.parse(stdout) as ExifMetadata[]; + + if (!output[0]) { + throw new Error(`No EXIF metadata found for ${imagePath}.`); + } + + return output[0]; +} + +/** + * Encodes an image file to base64. + * @param imagePath - The path to the image file. + * @returns A Promise that resolves to the base64 encoded image. + */ +/** + * The Vision API internally downscales to max 1568px on the longest side. + * Anything larger wastes tokens without improving results. + */ +const VISION_MAX_DIMENSION = 1568; + +async function base64EncodeImage(imagePath: string): Promise { + const resized = await sharp(imagePath) + .resize({ + width: VISION_MAX_DIMENSION, + height: VISION_MAX_DIMENSION, + fit: "inside", + withoutEnlargement: true, + }) + .jpeg({ quality: 80 }) + .toBuffer(); + + return resized.toString("base64"); +} + +const VISION_TOOL = { + name: "vision_response", + description: "Return the vision analysis of the image.", + input_schema: { + type: "object" as const, + additionalProperties: false, + properties: { + title_ideas: { type: "array", items: { type: "string" } }, + description: { type: "string" }, + tags: { type: "array", items: { type: "string" } }, + }, + required: ["title_ideas", "description", "tags"], + }, +}; + +/** + * Generates image description, title suggestions and tags using AI. + * + * @param metadata - The metadata of the image. + * @returns A Promise that resolves to a VisionAIResult object containing the generated image description, title suggestions, and tags. + */ +function buildVisionPrompt( + metadata: ExifMetadata, + locationName: string | null, +): string { + const locationContext = locationName + ? ` Das Foto wurde aufgenommen in: ${locationName}. Verwende diesen Ort konkret in der Beschreibung.` + : ""; + + const rawKeywords = metadata.Keywords ?? metadata.Subject ?? []; + const keywords = Array.isArray(rawKeywords) ? rawKeywords : [rawKeywords]; + const keywordContext = + keywords.length > 0 + ? ` Folgende Tags sind vom Fotografen vergeben worden: ${keywords.join(", ")}. Beruecksichtige diese Informationen in der Beschreibung.` + : ""; + + return `Erstelle eine präzise und detaillierte Beschreibung dieses Bildes, die auch als Alt-Text funktioniert. Der Alt-Text soll keine Wörter wie Bild, Foto, Fotografie, Illustration oder Ähnliches enthalten. Beschreibe die Szene so, wie sie ist.${locationContext}${keywordContext} Erstelle außerdem 5 Titelvorschläge für dieses Bild. Schlage zuletzt 5 Tags vor, die zur Bildbeschreibung passen. Diese Tags sollen einzelne Wörter sein. Identifiziere das Hauptmotiv oder Thema und stelle den entsprechenden Tag an die erste Stelle. Gib die Beschreibung, die Titelvorschläge und die Tags zurück.`; +} + +async function callAnthropicVision( + encodedImage: string, + prompt: string, + sourceFile: string, +): Promise { + const response = await getAnthropicClient().messages.create({ + model: "claude-opus-4-6", + max_tokens: 2048, + tools: [VISION_TOOL], + tool_choice: { type: "tool", name: "vision_response" }, + messages: [ + { + role: "user", + content: [ + { + type: "image", + source: { + type: "base64", + media_type: "image/jpeg", + data: encodedImage, + }, + }, + { type: "text", text: prompt }, + ], + }, + ], + }); + + const toolUseBlock = response.content.find((b) => b.type === "tool_use"); + if (!toolUseBlock || toolUseBlock.type !== "tool_use") { + throw new Error(`No tool use response from AI for ${sourceFile}.`); + } + + return toolUseBlock.input as VisionAIResult; +} + +async function callOpenAIVision( + encodedImage: string, + prompt: string, + sourceFile: string, +): Promise { + const jsonPrompt = `${prompt}\n\nWICHTIG: Antworte komplett auf Deutsch. Alle Titel, Beschreibungen und Tags muessen auf Deutsch sein.\n\nAntworte ausschliesslich mit einem JSON-Objekt im folgenden Format:\n{"title_ideas": ["...", "...", "...", "...", "..."], "description": "...", "tags": ["...", "...", "...", "...", "..."]}`; + + const response = await getOpenAIClient().chat.completions.create({ + model: "gpt-4o-mini", + max_tokens: 2048, + response_format: { type: "json_object" }, + messages: [ + { + role: "user", + content: [ + { + type: "image_url", + image_url: { url: `data:image/jpeg;base64,${encodedImage}` }, + }, + { type: "text", text: jsonPrompt }, + ], + }, + ], + }); + + const content = response.choices[0]?.message?.content; + if (!content) { + throw new Error(`No response from OpenAI for ${sourceFile}.`); + } + + return JSON.parse(content) as VisionAIResult; +} + +function isRetryableError(error: unknown, provider: VisionProvider): boolean { + if (provider === "anthropic") { + return isRateLimitError(error); + } + if (error instanceof OpenAI.RateLimitError) { + return true; + } + return false; +} + +async function generateImageDescriptionTitleSuggestionsAndTags( + metadata: ExifMetadata, + locationName: string | null, + options: Pick< + VisionCliOptions, + "visionMaxRetries" | "visionBaseBackoffMs" | "provider" + >, +): Promise { + const encodedImage = await base64EncodeImage(metadata.SourceFile); + const prompt = buildVisionPrompt(metadata, locationName); + + let lastError: unknown; + + for (let attempt = 0; attempt <= options.visionMaxRetries; attempt += 1) { + try { + const result = + options.provider === "openai" + ? await callOpenAIVision(encodedImage, prompt, metadata.SourceFile) + : await callAnthropicVision( + encodedImage, + prompt, + metadata.SourceFile, + ); + + if ( + result.title_ideas.length === 0 || + result.description.length === 0 || + result.tags.length === 0 + ) { + throw new Error( + `Incomplete vision response for ${metadata.SourceFile}.`, + ); + } + + return result; + } catch (error) { + lastError = error; + if ( + !isRetryableError(error, options.provider) || + attempt >= options.visionMaxRetries + ) { + break; + } + + const retryAfterMs = extractRetryAfterMs(error); + const exponentialBackoffMs = options.visionBaseBackoffMs * 2 ** attempt; + const jitterMs = Math.floor(Math.random() * 350); + const waitMs = + Math.max(retryAfterMs ?? 0, exponentialBackoffMs) + jitterMs; + const relativeSourcePath = relative(process.cwd(), metadata.SourceFile); + const nextAttempt = attempt + 1; + consola.warn( + `Rate limit for ${relativeSourcePath}. Retry ${nextAttempt}/${options.visionMaxRetries} in ${Math.ceil(waitMs / 1000)}s...`, + ); + await sleep(waitMs); + } + } + + throw lastError; +} + +function ensureVisionCanRun( + imagesToProcess: string[], + provider: VisionProvider, +): void { + if (imagesToProcess.length === 0) { + return; + } + + assertRequiredEnvironment(provider); +} + +/** + * Parses an EXIF DMS string like `7 deg 49' 12.00" N` into a decimal number. + */ +function parseDms(dms: string): number { + const match = dms.match(/(\d+)\s*deg\s*(\d+)'\s*([\d.]+)"\s*([NSEW])/i); + if (!match) { + return Number.NaN; + } + const [, deg, min, sec, dir] = match; + let decimal = Number(deg) + Number(min) / 60 + Number(sec) / 3600; + if (dir === "S" || dir === "W") { + decimal *= -1; + } + return decimal; +} + +/** + * Resolves GPS coordinates to a human-readable location via Nominatim. + */ +async function reverseGeocode( + lat: number, + lon: number, +): Promise { + const url = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json&accept-language=de&zoom=14`; + try { + const response = await fetch(url, { + headers: { "User-Agent": "adrian-altner.de/vision-script" }, + }); + if (!response.ok) return null; + const data = (await response.json()) as { display_name?: string }; + return data.display_name ?? null; + } catch { + return null; + } +} + +/** + * Resolves EXIF GPS data to a readable location name. Returns null if no GPS data. + */ +async function resolveLocationName( + exifData: ExifMetadata, +): Promise { + const latStr = exifData.GPSLatitude; + const lonStr = exifData.GPSLongitude; + if (!latStr || !lonStr) return null; + + const lat = parseDms(latStr); + const lon = parseDms(lonStr); + if (Number.isNaN(lat) || Number.isNaN(lon)) return null; + + return await reverseGeocode(lat, lon); +} + +function getLocationFromExif(exifData: ExifMetadata): string { + if (exifData.GPSPosition) { + return exifData.GPSPosition; + } + + if (exifData.GPSLatitude && exifData.GPSLongitude) { + return `${exifData.GPSLatitude}, ${exifData.GPSLongitude}`; + } + + return ""; +} + +/** + * Merges the metadata from EXIF data and vision data to create an ImageMetadataSuggestion object. + * @param exifData - The EXIF metadata of the image. + * @param visionData - The vision AI result data of the image. + * @returns The merged ImageMetadataSuggestion object. + */ +export function mergeMetaAndVisionData( + exifData: ExifMetadata, + visionData: VisionAIResult, + locationName?: string | null, +): ImageMetadataSuggestion { + const [date] = exifData.DateTimeOriginal.split(" "); + + if (!date) { + throw new Error(`Missing original date for ${exifData.SourceFile}.`); + } + + const result: ImageMetadataSuggestion = { + id: exifData.FileName.replace(".jpg", ""), + title: visionData.title_ideas, + image: `./${exifData.FileName}`, + alt: visionData.description, + location: getLocationFromExif(exifData), + date: date.replaceAll(":", "-"), + tags: visionData.tags, + exif: { + camera: exifData.Model, + lens: exifData.LensModel, + aperture: exifData.FNumber.toString(), + iso: exifData.ISO.toString(), + focal_length: exifData.FocalLength.replace(" mm", ""), + shutter_speed: exifData.ExposureTime, + }, + }; + + if (locationName) { + result.locationName = locationName; + } + + return result; +} + +/** + * Writes the given image metadata to a JSON file. + * @param imageMetadata - The image metadata to be written. + * @returns A Promise that resolves when the JSON file is written successfully. + */ +async function writeToJsonFile( + imageMetadata: ImageMetadataSuggestion, + imagePath: string, + photosDirectory: string, +): Promise { + const relativeImagePath = relative(photosDirectory, imagePath); + const jsonPath = getMetadataPathForImage(relativeImagePath, photosDirectory); + const json = JSON.stringify(imageMetadata, null, 2); + await writeFile(jsonPath, json); +} + +/** + * Main. + */ +async function main() { + consola.start("Checking for images to process..."); + const cliOptions = parseCliOptions(process.argv.slice(2)); + const photosDirectory = cliOptions.photosDirectory ?? PHOTOS_DIR; + + /// Load all images that don't have a JSON file. + const images = await getImagesToProcess(photosDirectory, cliOptions); + + if (images.length === 0) { + consola.success( + cliOptions.exifOnly + ? "No images with existing metadata found." + : cliOptions.refresh + ? "No images found to refresh." + : "No images require metadata.", + ); + return; + } + + /// Extract EXIF metadata from these images. + const exifData = await mapWithConcurrency( + images, + 8, + async (imagePath, index) => { + consola.info(`Extracting EXIF ${index + 1}/${images.length}...`); + return await extractExifMetadata(imagePath); + }, + ); + + /// Resolve location names via Nominatim (sequential, 1 req/s limit). + consola.info("Resolving location names via Nominatim..."); + const locationNames: (string | null)[] = []; + for (const exifEntry of exifData) { + const name = await resolveLocationName(exifEntry); + locationNames.push(name); + if (name) { + await sleep(1000); + } + } + const resolvedCount = locationNames.filter(Boolean).length; + consola.info(`Resolved ${resolvedCount}/${exifData.length} location names.`); + + if (cliOptions.exifOnly) { + /// EXIF-only mode: read existing JSON, merge EXIF fields, write back. + const existingData = await mapWithConcurrency( + images, + 8, + async (imagePath) => readExistingJsonSidecar(imagePath, photosDirectory), + ); + + await mapWithConcurrency(exifData, 8, async (exifEntry, index) => { + const existing = existingData[index]; + + if (!existing) { + throw new Error( + `Missing existing metadata for ${exifEntry.SourceFile}.`, + ); + } + + const updated = mergeExifIntoExisting( + exifEntry, + existing, + locationNames[index], + ); + const relativeImagePath = relative(photosDirectory, exifEntry.SourceFile); + const jsonPath = getMetadataPathForImage( + relativeImagePath, + photosDirectory, + ); + await writeFile(jsonPath, JSON.stringify(updated, null, 2)); + consola.info( + `Updated EXIF ${index + 1}/${exifData.length}: ${relativeImagePath}`, + ); + }); + + consola.success("All EXIF data updated successfully."); + return; + } + + consola.info( + `Vision settings: provider=${cliOptions.provider}, concurrency=${cliOptions.visionConcurrency}, retries=${cliOptions.visionMaxRetries}, backoff=${cliOptions.visionBaseBackoffMs}ms`, + ); + + ensureVisionCanRun(images, cliOptions.provider); + + /// Determine the image description, title suggestions and tags for each image with AI. + const visionData = await mapWithConcurrency( + exifData, + cliOptions.visionConcurrency, + async (exifEntry, index) => { + consola.info(`Generating AI metadata ${index + 1}/${exifData.length}...`); + return await generateImageDescriptionTitleSuggestionsAndTags( + exifEntry, + locationNames[index] ?? null, + cliOptions, + ); + }, + ); + + /// Merge the EXIF and Vision data to create the final metadata suggestion. + const imageData = exifData.map((e, i) => { + const currentVisionData = visionData[i]; + + if (!currentVisionData) { + throw new Error(`Missing vision data for ${e.SourceFile}.`); + } + + return mergeMetaAndVisionData(e, currentVisionData, locationNames[i]); + }); + + /// Write the metadata to JSON files. + await mapWithConcurrency(imageData, 8, async (imageMetadata, index) => { + const sourceFile = exifData[index]?.SourceFile; + + if (!sourceFile) { + throw new Error(`Missing source file for ${imageMetadata.id}.`); + } + + await writeToJsonFile(imageMetadata, sourceFile, photosDirectory); + consola.info(`Wrote metadata ${index + 1}/${imageData.length}.`); + }); + + consola.success("All images processed successfully."); +} + +if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) { + try { + await main(); + } catch (error) { + consola.error(error); + process.exit(1); + } +} diff --git a/src/assets/blog-placeholder-1.jpg b/src/assets/blog-placeholder-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..74d4009b527342f03264c9caefd390aa5247b376 GIT binary patch literal 32040 zcmZ6ybzB?4_C6efyK8Y0G`LG~iaQi{hf=(_7I$}dhoXgIh2j*KQe1--hvNLw`@Qe| z?~h>uS~j7I=Vc*MkS$SKL+5Q9Jr3?L9MH#ax0@c$AVCOSGM7A6iB z77hUxHWmQ^4lXVZ0R;g8Aprpen2Z>f$iUQel$4Zo)QpT^Fe4)u7Y7&D|Jn<`_5*NH z;5Om=;NfTiKwLO@T)5XC0CLzc|C<2+O>jVXWF$lcl-J(?lz(#o0IsGXgs{0-1p&U8 zLeK$C{YCGK#UZ)?B4#20I4DMAoK z#u>q>2J)av-KHp0W&p4cfEcX^(bCY>YSh(J&<*Bwj7rw6(in?QM~wN`M`cr)A^}2` z1Y@cU(F&ftvXSA$NM&VdBSZr@n1+^y&dmBVT@4J!#7xMT-u@xkvd+GlUVBhqMpdl)*c_GVpwF2J)X;!5jitlJtOf?)1%ZhG03!#VX3`%SI-hI= zz=)B>dglFuxZ5WuVeTyyZJBZYz&+a_H=HDKBh4FbF}1z0-(K-X}Z2)O3H zK1Y6)wth^01uF!Hfl(z);Y$R`LBIEVhT^G4paAxNHT1AWiB6K1E zVmbgVQ1!Yu=iXkorq2DaD&B8*L)qRHnp&l%g^mbQ9{_B)LWCGp$k6q2eBMPK_Wr?r zVN!61-`|sS91l?@9ipWRXiSAOZLB0hQ-tW+OWi)7c(HHe4K8+iEDVc!IaMge`<570b$UjAetCbRy7>xtyG!hQI6LWgzM+y09Zxp}6QNp##r#`ZIE_R! z1={2!jfMqZtyh4U*fjrOfEw$DN=^rKifqFOnjtEu5Dh?8Bhu1S(_mIhMbVQkL_eXD zy`ogOX()NZrbMs1S+DnY%Rc@VZ`cf{rU0peG?j()H3g;W0sxRNW=_X1vS$HwkFNmX z>s~hI^*m1}QN29gIf1>%7+_xwvvg(CI2ss?7ul=^>}!hDSUK%o4&)!$mpt?L=(>WY z-%g2GYc(R0m0F{U1Hb?xJ@dg}tJHM8j}3pHP1f#_cjb{<=j!JQMB1&nv)rVMSnD*b zGJymDpc-s7inSIN8xCIqfs@wOiWMq(JW~*bj!AO^Af&bKLkd2J0-%wI2~zsSDvbz& z&X~Q}S|XSkwxp8hA$SEP%%TQrtU2g6*^nmdf)RhBet?wfHjN>u!F}vBaErAjgVp=! zeK`@X#tiqdwOebFJ2y!Uky@8A8k}0Gkp83C{>-0PgbFsX^c-Mr|TowCI4Or`{1+>% zDV++H?34_VeYj__iaRUb?lb+YN$x0Ggeoguu%7)`@(Ar@?*Vp1LGxXYV;!4u3^X9+ za)YP&w_n6Pw(Z69ryHu6Clx>Mt>5m)hWA&KQWgBC{?L?T{`c4Gqq%MqiPS(_E&Zy> zV@%g|>7VjTNq> z9RAaFPBEvGu9#InDU;sY0E?3srb8;un^yqx-IUFx>h9ZtAK$KTu;ZQrj7PUA&(0rS z5{BO^&IxK?e06BEtG z&@KLkPA~Q@FU!Zk)hjWZ3lq6}lhqfo=)=<&swbQFyVc_(DvEoN?uZ|63x+wb12-;D z15K_ssP10ko{WwD81oPReFZ39_FRp%9-1UwJ}h#^?vRR0FyhQ9Yt4tw{*IN~_!c15 zKH%rM{_MH;3ZU=0TI%|I*5h!|?U1k^kdYq9?4Pi4e)S4yxHlQwI(iX&Tn~QQSlRFG zgKqrpVvlIQ&zO8hE(&D0z4r`McsiTOH)C^&wICITqyrS+uaQL>9&77mjaeGPEIZGz zh*EThk#L}_{BQ*Mdd_MlG%_p|hWNvdtf_qN%xF||IJDLp$I7(#NAgiwI0ij=yt$V{ z5^SBfXDcFJE<>FkSFeU#72dZmRVYtfO|iLJ#z=yHrlWo+udi`kjrkar#hHa_aJW=L zes9Ci<4_UsTtP|h=2@o%O_xx1-*CLigihtVfV9&rWtAPy z)$a@JppYG|JP3;wB#q~%^sazCu6?W~tv=11-6=6~B+AKb=&^j95j?UjDP zJ`2ElE^>4$X=`gOeJnxsRb1v8>l+W}YCFD!q1 z+Q8|EhMWl{jO1Ai)^lkDv!3zsk zxz;w+GNE{5dTzGpAM0D|3~HEiC!d~U1_d{o9>lipUc_c@yvC zwPF1gU@{(1(ErT8^WyPX5OMfdtl>_KXOc5>vA)k1^0vWEvSfy!KzPc_YP1~q`RT2*+kF;8C!MpG zjEoKMwz_YcNpxdZy4UPH>f~Wdl`9W{Wbi?V;E2`BT-_QPidJ0qR{zn(@(MgV0s|=<(r^kBeAyz_T|>r z+E(eH4%0}y{t-5-Dy`Oju0K>M-=UDs(7lLo`gb8*}>Xcb`9A?GdIbYJof56d)v)f?gjhe zHLG{VvK33iqx1Lff*Q9wdfVE(s-rmUeI)7Mzg&{~{BZXABEY5D@XXR|3&s zGRX&}Z70qA_ClBp0LqjOv7L!rufb$p06ZU58k%SCwxkaL=!wHYN}Je9ZF1Kp*88Z7 zgJ5^ztu5zRn`|}3=YAgzYast=%mQ=87SEiwnh}6TjnN6pz4FlpDp{{h7ZM;+h$rZ0T#-7S(;ws9=Y3R(qG&n7Z1=%5y@|? z_mwTYlz$9)RA)<18Z1{+tt?V#W{#eR?>#VScWL;e3yXDkr zB*sYK+DXobDq6dE6mjRS*)M?52tnx!c;h*|IqA(=)lCzMbp~>YOpzx2s;u`A15PqfOpQDO%5=3Z(eH^M ztx0{5fju=2lT2A~ogOzB+)QeV1_#6hRKve7w`ef<=&}#32BJ|*$pF<@TS3=%wgpn( zYve&hp(qOgKsA1Vu!ir`LmRy%D-huqqc|EWwAiP-Dhs5Bf(^p}$^T&hrrQ6de;D`= z1mOQcAn0E?oZ7!L08ZXK@&5#AW`M?jNxf=Hg09p`CWY!wju2bp**8a<& zbqp?igi<4x!ZJ982Kk=)ogE{<6%Y^rkZU1=rmeT?1(B7TqErHOvpR{i20IstyNEL&Kw5ROIKs~st*xHyHcP}=IY7+E8o@+_AtwcPQT;!4+yL7| zK*+HHcWfW`q?3Es-Eq$`2f7AzVQAZNdA&<)Ukb6lj)<^*DXJYP%@)Mu(S4ZjJ%LaD z&C%NX%r_Emej=tCo?3hHFU-&98l9r>wD!7L-vUlRS?ctu$NFFw^oCrgM0MI$@6Xzj z;01qtTdYL+86@LiuvqRE74P@p@fF(BDaReF*zF(=51^IlT>NY8lIxl$WJ7jbnrxGA zu>J=H9)O#L>EOFCF)Yfu*y)&+Ywh6AYX=hNKn%6ETx{>0^y^9dW+Ry4yAE63APxX3 zh__Db@}bauBF@QEJ}V0c9)N}*({klw+Re4tsv(~#4i5u>BF=vvdIS`7L?k3QM8JP+ z0003O5s!uw2VcU4fR>9#-7NS!HMgXOrm1UE(U&bkIu7v}HS>_q$>$(m3um|fVz6{# z;l+Om4LC92E8yryc%BIjqCuF&XQc=5D?mOTllvg!nVx7aa<8z$tD?S1>BuTEuL6Ii z+#}DuDW%0cZ)ZuK&tncnWn$s07kBJYIZ<9#-0+exO*UASqD#Hl)#7v0dqF*V(7u2a zjZIo|i~b*NCa(|M1%^TO@Z1>u)mE(cB{KDY3>A%StNz5${1zzh+EQOGx^1mv>J^Yc zAoJO=Zm!Kj*p25ro#WVVz3G^BUTXrcE{H@3VF|Y#wq!3%q+YX3$Nw)~H)L z7WfWca(7+P&KZ4Ft^N&9xzS!>Ekks!LJO_gE~u0x(wRxn2TI>q^?pjc=%k;Gss+8g`CW0hW$aw*{(pk_mHD}Rh0=WJiK`> zpVQuIUmgyo%tUBc;*QYQWFuM{qeSOo?}{^Ll3GHOSBO@z!0xkFUrO;NC|BD?cVK*P zamCtJL4=dLfIZsPFPU40TJh)lGF0@ms!UK}ZJFu=w#>zY>ON zs=kIT%2FHKTq^R^x#+L$yB@wf^{(QQc9JjmY`30+B~#=l_t;1i`%&uw&VS=fTKrIv zR=DDl6IFzTCLHIi?$UgX`WXbrbFQh7B1$d}e0WB#%Kr{FY~%j%4A>z3@t4Q#Q<8qP zO%p>Ln7rX#1Wr6ciMv6iI?s z1O`0UaLcl?B>yoyZjEn+zniN1jD;hP5g++%qI;MQX(QHYweuADS-f=M7qGn+9%YsD zufKWTJlZL-%waOMwh?Sl?==Zn0&dzeE^kC^jAAO3g#aeG-(*B<@1YAwe+>F z)HCwL8I~TgGl(Vy;~d-D_5W@rvm{8oQwXB*vLGs9LY16lYMhfvpEju02$PhZWXN>X zsAiO_+yU|^@YiNZetKWgOwy`=liHRVq#ac%FP{Z_1nnmNO0Fd*Z--uVBKen#E;%_^ zC)K3ne@KPSC5PX6mvL=5>P03)mCs@%(nQl&R2DqN`TPoqQ@>B=j z5h?@Y6>&ou7%7(dnzgJXhb`7Jl<8 zU1YFFZ+?Ve@GBtUn^Jziwar`~&`-w?mNld~Ave8J^QTuXi(B4{?Fu=%{d zLZJ3;3AFqlJj^!8dTsBB0=b>q_x;e>2U&i{NbIrxF-eXCB-(RuG}oqr?vtv@-P-h&0^fOZ6}>($8cGq#v_K%dQ!sg=wl4<<<|BPv>HpWE7YMQu1Rs zt+?gi5UT~aI8>ay(UGh8_6qp*f12B#=p|0AXB7I75vMgeo|=ExiYp(~AmT6P7`yG9 zIxe7LYnK_1%Xz4M#@TQEmbQDJq{aG;T2IZvZw%FOzGLt;mH=Uc-1J{gohSd_mfmx| z+lv>r8%1KUNPX;d#$xx(#!p}5Vsa`mhHjAkchsc&Su0FOpS>fx?4L_E^`3tAY-COI z{KMb8vRefIA^E_)$<6dbwo->?$d#9tEK1We>R*40P`&)n$DYQhZ*S4M!bj9rRBKh0 z+Bq~`zq;QMIb`geQc=$}QP`H7DPs$L?qsDUOOt~CND&o7GbYgXv}NM1@3@-HV175l z{z5j@+m`W7MV~^`F1>5BD;h0wi_fG;^sLr7hJCuga}k%{hDIlG2JMaAP1Jq)J{p@& zjQ%3112(Uv3%T2t<=o@O!MbrLm*+Na+_yi;*UA_*=JAp=Tyg%qNmUb7U^*`k;+=J; z)E6!c!NjtV$sE<}+yGMvw07z9AES@0z^3Q$$tXfl=HOGHUjXLk7;YJ0FGJ9%xIIvIA;Qy4m zCj5hmSu$EXm^2PgDWU*Xt(sd)wP~D1!GNH@qOWPS^IkSzRBgB0k!YzYBmVjoV9v_V zKC$*ISmiF&O@|}wL;c&YGQ~sf+Dd0ee+R2K73C})?=dlOx#>L1_^~d~CH`~ogCx_p z9C$@q)|D-~R$*N#Bgvs963d^B6{G@G#9E$$iis99|#O zWbO+m4aWxZ<1ikPJbkHD%VK@zMM5x*aAh^|_EbLs$Xa0N=$oy@=jDT;s6S#=QBBMK zGWDujdXs$N+Wr#sw{!R)rkg~2mS&ZXd}Po64hAp9K3zuvn^9sDKQo!#H;u|#0qU={ zE+)4)sz4t}+YOJ8-Bppx#?t7832EDYFOs6mt+9NJe}>aaSX;YaVubOtv0UwaOPD5( z+$6*L;zZ?VtqQne4M&afLy0{U^~794knvw;(ec#DhpMiCq`IUO85|iOB+!q6Bmdd$ zZ^&BmspVEpCE{4t^c8Bqdl1sY#>FHCzZOQcdXehxtWgPMD#;(j*yi+8Ugh-=Q%>?;P@S! z0<@?~Cx5pBD}~Cc8%j^nyssX|j=eS;BWh-guFRI}Hk+Ep2(nhDIV4_|xtYzDW|p)< zWu{iMiBE$0V?1~LVVGDyG37;%*bB{&QS2g>CHSP1ICY-r5|IAX+dVf~S1g4KB zc#ABBSKou`WGOH^eOh_>fIvHuZEVUAI7?`y6dSGjcL|HHZNbC*FcefL0nbZ@(!57$ zHpuinm>@<{`R_W~2UC32T>mWo>9^+dg8f4m5v|Q$$Yl_X~YeQdTMZ>;kO0L*Wbk>2@bYl+^996_G2v zJ)NeIXe_>i@h}vnVx3^4NGaHB>$g3(-(Av|s_Uc8d(hdC$^>R+5|uCIh_k4Ym5(!B zJi48|Rw>@?@5B;)#-hZeQ!e89!!ho&r19%AR^-_ALo`-tIia00d8EqL!vJ4Su$E_R ze%=?+ek04Tg7SpOH8Lq9ZhoR|R^*yv#CdMXLQP@%Dbicgw*iemt2ebN0Trb-_$OtD zuAeGmQ&7|;`-kj!ap{Ck2BH-X#aTjCRYeAhP=KlRoVP7g*$D~9`1tV?Ah4-fJXNrX z`kwK8Puj_-LGi4O9=o4)tS{d|lU|9{+@2{vO1`fFhux?ufpic`s{FbVlZ-vHV2WnB zy#A=x`mLE=apXZiSTOr-9^`JEe8=#fY8M;1Uo z2Kw@Rnb173Z4z;P&TRD_xs?s9e((0XBbrj-{Oxp=X;n+_w5Txcyw6opQ8M>N@kAEt z`!YS2lpY34tuhDwl`$pzJQ4!tZ$(kWhP=98<60*fj1?hAb7N|S6l&&E&di1k_8gqN zpkoJqd~al0YM!G;6wqmuys`xLgsH2f&xF3;Qi~VelTwC$$_15fflwRH$V=ahP5mP= zcCy_v!Dh1k;qbaM86*wUe6A${<|m&zcvKN5zvEdZ;A98wgx3(i`CYPxP^R&tB3U!y zn@rM(n^%lfUdQq!nchCk!B6-mlesB9h@H-~LKIrOMl*Cl2c-L~- zPW{5JLNAO-kw4X5B|Oh1%~&GzcX6(}#R6JuMDj*g|Nff6sLRAhve1*L9NAFbnuWFF zI^Ql*z3qNBqwYAjsH~8OGmXbyZ7W|FtV6vuC!zpq9KZrXqQ2f2CKi(T3flH z4I{*+Y+(=Jh%IM76b3H)__X=!Rs^dWRc&fs$u0`nR_wM~^BTESAIIq!+IQ|~FOl_p z?f7?ExEZRc|Gz7GHyTND6~W2`Pu8&%{Bfx(;mA)JQ@7F={f;)v?&r_|9BgYzeEKZ84;EF<1?tmqdF zr@^=fQY$A2%@++bJ}$dqH_FQF=G6@14#(@49`d^Eox`3I7i6{+EZsZ*mCToGf!`~7 zl7j@?Gpr-R&q}pAef7~V`u}bMamUnH{jJQyL}SPFUKSo%z%GMQdvQ=DaLvqCgFvm8 zfIED}pa$iGwk*up|27&%B;b=`>N&!3)d-4hBx6lQYwIpAJV?8+39R;r9yISw$+@ry zh~aaDFcx{y`1)WVmTuF2^1x^l7xQwZcmSKsi;yq3ct~Bws`y_i76}eO#z#P%+h;5` z(^8Wed72SpLALhXxU2#z2X(f+OdN&^GV+CoF_N}Q!h^eXa1a0KsgAwA@=x@jsX$Q@ zEem0EpE@a-gu37kA*`rQVPcVmFkDCa_Qkp&7e-D%Z~#C!AOZpsJdCD-Q4=t70vCWo zL(M5+#-Z*~Bp#gf<@>qX%!TQe^Z(cfnpXf%*V``hCuXs5QL(_wbXZ)>`U;3NId6D2 zAL5{zIK11EA;b`fxZAU-h{G`zk=jvz1&}mS;+h=&kqVP|@j`9g-@Pudy@P!s&%6b@ zy-Gp~akX+qUjaeAu`_q+NIC_cAF4wzjCOhqDHlkTF{KGP?v%yQ8#c*{qRuET`|D7q z{3x?rWH319Q4q8_F1XL{&m(qtNe^YFd~m4osFCRdcd69?a!5*nW8e%i(5mMqj9m;T zZIuS1rC_55;5!W_29e_6&~_l#TRzMXIPU8SqxAD#vET8)or;UZM=X-yNbAO3L{f*? zg-%N#qK0R`0)m$Yil>&uj=D1WlRl1)PU*H=PDX9kbr!5prUA>z0TNOeV*B}-U61hl z2I%n)4>ml9(>4~aNNGzY5^2Gv6yVso(UJo#y`;tmSq$sTA z0q#;$&Yo_B95>`ak`GX+avFXR-^i0Q0*+8FJX}PC)1@kFr_E)4)!1|5G4BNWwrI2F z6hn&$93moD(RF1_=nL6RU|cVp6aZ=GFMX+mv* zAB2-6W*2DD9f1+L#3*K>INQgFs$1Am?I_x6P;7wK0N?po3|s{K1;d3TS{eq&7LGVm z83xCl3<3Q4v!Cmx9TFlr#}*KUx+@rl_?OuAcT;Rmc;A__&`Y%YevnK zb4Y|OpZ*;9f%pH=QDAzPVO)zHfIee;c{dq?6I{+BPzh=E8@TT$1G?I!m7Alo75@rD z9SWJK`StYUdwmhk9u{uoK>wZ?GTcH?O!w3thRkXJ26#VqQ^r+X`D6Aw7vp(pqQrvwykN=@D&yrVIhD)-YA%v4jyv@ZiX?=;C%g zRFB)4f_Pt!@>=UljKm@>5~=Bp%&n}PzNVCT3wPlkCq*-^->8*~<5-_Ds73m|g|;M& zudCfe*M-Vd5i!iW@zUAZxU)@PW$&b8SvopeV4ua^*9c@0Ar{VB2Gqvi!4)yp$?tL9 zbkc1TX`mJr)Wr$`{UVCP250qBMj z?Xei)*iI5teFkZc%TGusd(=o$!f{m}Hwp~{5|^s_;3Nm;`!8iDZIT&C-A!_z`yMH+ zsY=EB7HQ(>8XStqa8-ZCg&qLtl{yw9dzWZt`T5@q3v`EjYcALzSlCiWGd6aTJYnT* z&gRja-&2@{wGdT3Gn`_o>OBS%C#qof!3PRBBLSMOSZ~W(U2iCdJbUda!V|m|O_OGi ztWRih_P$Jf_CE@=(EFQv{wWn$U|@y;II+DE!-+(&G{kKos_$0Ckfh^U|JxB!VV1OS z3$%or4oH;JQu9lAu9A=ec;X#JU2c9yx>jWoZ4^D{a5}NJ?duFFnIuKda{KcJ@fn`q z6M^U3%I7^>B?C(j`rxWYaHXHjQPx7lNt2MDLSF&6G|Ps7#c6dM4b0EHBbha| zp;4XNHl_GS7Rf9l0rRE@*d|BRTmWCnZJS%CXCm#@Q4u_!4!%@&zPZkZK`0-#6oymECuNZbz_&Ghk?Clm#5-xIP z$rA(JM2OU)r1WC+1qUatL70%*HxjKBYf_gM0fHf->J%dXKd?;1$ZuD ztV9XX#eRV!Yje^xnxN&9#I&a~1bllS8xD#{;@9=JYH70`QUVyWB=ciS1`#%_s>g6= zL_>-bAOB{HSrkLNgn8&cE$x<-8YPM(9ZT5siUR{VDB40ISAiI{buOI=C^TL9;xo&G0^s`EwY1 zxy$9oT3>lrze%-pg}K`Nr1DOg%X&^S##3a(96dmQ&mgWIY$c^uHxkxxdAEnhLI;I# z(U6QyNKOtQ88kw6iulq;5B1gt)Xi8wSNWol7+?(TwJ33Mf8?`*hkles zZ0j2v_YY2To%*jMn~@m!rGiozA~Xm%;xyspwB;nWUO_T|9A&0dj$tX~^Nm5fFy}Na z5gH`I0YdIjDInQDOC4Q^gXN4;RqD>r&xTh2)ji)`%V1DDNNGEou{fIXOElIO8I*96 zue3phW4=-ng@t`)Ta1M`D9l^@p)f#_21R#yjFlso7k{{wWHt=F%yF#BaPg;AC1lAlk2pmP; z$Dg|f7YY~R=FZ@SLGTO_?yHG$cqzmKvegfgNFaR9oDCTXiLWh7^xz9Mmj@0)CD@|b ze#5okh+luCl#|p2Nrc0rDHY1YGh)axepPWRJW?*wSXs;``Z|X(&o{sHydh&nut=(sU~L)^-uIKw&=+lu(2ve(g)C zPK#pbgLhKs3U`GC2zF$PY+G8IKcWe9_c!j<8Rb4k&0Ohfn6(y>ylhzj!_OJd9qrCv z=KS@Hup1fkeIAe4>&uto@~1v_wD-~$weD>7`b~P?>Qf3tWUj9SIeI0~N zuO1XO!as(F(~O6CPlCT{>*#hwuUobH-B~>vM0R82r zf`Ef&OorOUF?*vfLmWmpo8{~gkKw(gtISgzF6`kQLt4l83Q!fIUAnKRx{WJ4?_L z%#TbrpH!Qm0CDO<{NJGisPQ5S*jNJaK8HW>^V|#F1Zox;i^CZ?44bcJexuqzcdkh@ zLa>^q_Cxv1A2MZZBk#p4U29Ls*PS1xiWbR8=xtV1zbuAiy!FA1Sa*|=t$0TDT!u)% zf8C50Ork8_Hx}|_3!t@r2{z5P7wU@09ntpdAR^6FESnZJ#p-sNQ3k$y(<=HoDX;JL z{YC{d^2~&4ITQ%T6{P;tj3Z|tN=7R74leSX;=I#)$Ra+2{w*W(fmx{5kDk zx6l*_(o8(`qb`AOmysLPE(6_hKML|2Q}mjx-Vy@2L9#h7{VPGFv4Zg$+d6v`g-#BR zAA{cQeHv9Q+_jF$$5pBZVizXZzFpd1G)>SYhjHv4$oX=j-b;*13~0sC%$;4beTSM7 z5i3DQ2j@mpUIgmPW|R^rx}ROVNaUa2bki8HOXs+E@jyy*ve8MX5q6b(a{6+b$NwVL z_u9q)hep(4HGonx_lzsyA>B|Vz%^*_(XL7+o0(DJYi&o6C zqVxVvQ>{7FP4e?Yaf^5%D@;uOJQ`e6(qXuk$xtZ_0R$W}5@pIvEHL3$^i&lZ0&O0A z)Oe~s)B<8dw$46BxCA6OeP%}6O6ok@Pr?7H+wg@)^qmm`T7XPr`tk7sPexT%p*jkA z&Xtw#-Y9D7ZgLLGlJgg(_ZNo1lk;$F;*c;pqDCNoWkD-Mvy-%lm8IH@cNQTt)3}f! z(A0(5;^N|xnwC%HGc#(_^RjU9%n0nH;pFc^itSXc)!(0Ikh}ekPe>?0xoD}1Mkx-D zCQ+A>jAnd?tiziCSN|1}J1f$xpRT{^18wv#EmE~S3!Eg>c!A@BSZi)_*NgEX)55a7 zt-_3uqQQ5eB*jHkj56Dt+iJxVPKap`uAzIMQm-1Uzi?#rVFG zEVc7fr=-sVVud!>u`k!KqvhqIV4eHnU7+~XDT#|mcHf`4Kit*X7Cc__x+(#5NQD!)`M29G+5!|t!q{Ib%!}c( zvPS3H{kB_9KFGe~z-$o>+Jg^NAQH7;N(>3ESo@_mEu(3$OmJgk(}gl_0=F#_^__Z&Vk zI2P|{Y%i@{e_3Yla>0*CMUKQ${2&GZR*@Zx3i~E%so&>RUtOt1WZjY@s(exAV9^v& zBpYl9B555cQ}NLCDCDsg;-uIKuI47k-8_`~ZYWx7k1iz$Yy_SRPUsU_DrR+yn|`t2 z{v(*7{_A0^m|36sH{E9e$6$3CLX<(7&^s|0Yrz0xEr38cc!dA47BJd^hEqb_%q18H z_5#KCne(j+>i-cII0uP;JPa88yIIhYASIT8`5D0tK>ALX`Fe91R?$#GP@d;^Os;3V z<>$@36e-?*a>5t1;;S}e&!!=_ONL$IT_M#V`H^ zUX0pBO6y{kFCh(|FYTXM&2~qxRYNR#OI;4H&2V1a`Q}fpsY-FftqUlCym$TE{mrbL$ zq*T8cmyo9?R0AZigtnxAu~xO5S-brkr1GQJ2?$-(2^qCTP2BUVmlKqaEtt#}P|XZ|0+~2)&%S8J%7; zy(^F|D;vr8@e#p*p?M0Dzqeq87Yw<$pJy&<+p zT9Gr4ZG!ajyzFR#60RQoNpW{*Wh`f^jw|F>gfLgECZYK=pTCbpQ;Yj3)ylOFJqFd^ z8P#INCp>kG1Mykd>Xpn~b1}`pJ3Vn|K4%|EpL7w-r3Lo~$FeVy_rd(fMT1PF zSd+9TjmWM%TOCQ?rb|-W+TC^FMc%}VasYNpLdYkBF9|808d?ji1d_fKlqe<6@4F`l zGMkfcMFP;T3zo4*e&Sy0`RFmcq%eNmV?1Cce+fgr&Sn|OQRYnxA?Htvx-Ls#aOsgN zP&lP?wtPt@82uXD26bGqIIu>PDVWxZ!>Jm5mbKKJcgM?C6cFOn#!DUD86}TLwQ5*@25^@wmO1j?=5m*wQtv`j53pR_+k-4H~sR{wBdTJgthG?hVzlGHZnzsxFyM|x4G&W ziIh2dW_rWiR^CA>&V+thB+1o-cO*J$>=n>2JKZx*S2*vZIQ$)1{mQ~;J)+?6>}Jt) zhl|Z6j|h8-H5dDXECR*N;RXU1TlCE82?$JUh^lOjolwko(8A+YR4~h_o7m9Xm`Q-^ zVWfB}e@BV2X@uIraG&*@ks{2|Oz-C-`aFKUw0R!+Vw_qV-CbauzemhPx7nP`UNs*z zTH-%^{^gL)WDTp?X4hvkxZ#2ET+7ILNUT|@0qLixsIp1p3y<|zo&)u_h zdsr&x%49`s$}gb>Ky_>=gQVW7@};7M0|^BoCy3`qVu;RacqI3DVHXZkD;m zQIah7ls9jfxL8CBtW8!kHr@SlM0`w2KKhFeech;#DBtqw2h%=r8yBo5ozf&`@MKYq zxbPUXC#{QM$hRd=!Rwq4R|;_<8sTJ+GUF$8J5^57kJ&^v^peRK5fU-WCKS&!D{Sj0@NSG@4Ia4h23YD{!sz71!{g^O*S&FU0 z6T>r~D3%Y2A0eL;@-?bJfjQ2jL=*bCm^op5uN8D-X|qQ<;mf}Io0~8!<+bn6$Vm+< zcf>-wM%;(1ce`I2l;>FJ54?YHp)u`=DL*KG&$?cVR7_$plCf%$QJ7vGpwb#rF_Xrw zJg$&>kb92Sg}sXi>e{qp*etSF`U`4%cdoc-Qu1QX#;}_jHT@Tns0#n^o_q6@lMSh| zi1TE|53hHY!1T!EJF)b@=8>ZHAn`fZ#i)k3@>sP1Ir1c}K-rpGyaqYzhRqOg=e796R=ikuO&ZUBj=^o^jf?PeH6$qVK(4h zj8O;K%rj+5bGTq%1IR1X`#OT?JwoqXMae;cKgfhJ9=or|L)NTedQaq&FdCBjbsUv> zox~k&v_nMmfeTf#7arMlJSyz}gknkGd%p|KsPgbjYRp@mIISgXVKtXfOo+Z^D0>C$ zuoloyZWkzCKN2vwQD9QMAQg9ZmixFkdo1$fw45}&)r_pdt?x;ry=559e0-DP?*1;c z4b+8FfiHqiGP1x%90FFfh^(Mj?+frxL^~(&AqPxm2YCHLi&*?=kV;DzTMH3O}gQ z;VD;DfS6*VXdscNkifE@aVfhjl}3KezSSi2_aKwToN)rJ+MW4zXc-M~!Nr`n!Z>~$e)D#zPMp~2Ngn|EZZH!LjFvR;4ec5^l@il2$tZ&zx57;5&>&Xi7(#a`TA^>cP8n93IdhUD;t0cbmoStbnXg2`-{lJ z%0UVfaj@OGy$=245<)B;_+8?fdA~Dm*T(OX=a$qX3SXe42| z`RmFIsO;!Z!jA0B#vEmV6qOXugdUWhNV-h+%eA>br-oG2>?op}FUFVkiP@lNt(Y57Z*JU6t%3=6;nx4N1aX%M7H`Rw%8!a#`}}Gu#=rbd;;W>LH6YD zc!UX#f%RqDQ>BkSQcgU)3B~jVbZ0$ge+~t$*>n`+aht5=l-Q~=J`|LlC=eSpv}7c! zUrHF@|5Qm#mrDinoU^7}Gx3);TChPaA0@yE`&_I3SVnk`agVgDgUL%~=#xJ@pF_xu z_@wD4OWof@OVg=z=(l`qQ}inaZgTULET# zyUfi@u#rkt6C-T6Hi={syhPMY%4#vPQ9BCGp9jiE31Ml@V&Jh>mH^vt^*j*1`n&ok zy$g%bo-^Xk?z$>b^>JdE*O=_0zRC!eQj z9NV@)CL$jU0#koJSb8()maXh^xFoNPw^lc)&vQ+ zK!zh&%hShm%yBlvPOm$$s}RhK+aEW0vDDvH{?fcM0A%X*2WkO%d5JK zkJB$G-@*La)5j&od9|+Uo`)i+^f@0XOJQEBYz1_dr14$%hko7@gQlxP#7D9RP&#|F zqv?njN|Ah1Uz{ZVEhbqlsklYwnR5|QMN1Z=HYp&Q z_L=&)7%gjN{^O53VcYU3xvEmNo$qAK0ps6uvAiiwQ!T#>(h`?_uO??#eoj`-=EU=O z({vR=gkUlAgGhJf_WK)4;@v69inrOXzo#jOX)_+faZ ziFs_H#c`S2=K^v9u@hdr^HD|oU+BJ>(59&xW01?OiBe5Ca&~wLSA5nynY>Sd&!_uh z)y8wFg()#BxB2-VBMd!>{WH?HoQQL}hlor2ZiZFIzR;(gYcIN;i2T0yzXvIO|Km!xq!Gutcp?DdS&_& zQV#T*8^DPplAfy`19e4e$_68Yfk{^e*gW`XtsC$PoOa8O!|-87GV+Xp;`+#fpof!PDdj-q(Qp7TNpAB5D~dhDY?E}@6Ye|-}Zd%pWV*Rp6B^Ik8^+UsC6Xs zzBj?R&av5%|H1G@X<*dVxtb|N+`1+xMJzGJzTBShw!;@gDyJVpliPS=C3C%W7O0-r zlIylTb@0WzR0G?%6;O_q>Jd-?2t5yaW8J?!dYY{9au zJ>ouj`3rcg-m5-YjLny3pAtsuo&7ynJcwT^XLPKj!g^&{Fs|U_feR~z)&AG@sT+;SZi}MvdQ1uPz0`|{xD{GimpB)js>ri|_ov%5>T}zHs zy&3r~!#Q-$844A1Pyz2(J+rRgHV7%H|>mJ%-a0dhh^m{mO8x!L@evbM4VNB%Q z-p&S%kZwXA6{{z1Ij(YnSF-J7uq|2dV?Iwj@Fo3t{9~;<0{|@@6OyMOP`)``;g6)k z>%@2lvWp-V{L*r!2VL|Rj=lxTJTK=vy0*cn{5M0V$=tIHzcjSC;bdiWp-G;J@zD8G z?svE_SYc$zA6jk$$(U}}Y~^3}Klg@QXQS7#16Rq<-xxWZv+I@hEvcGJXBLqmbN!X$ zWdnl1RD;YNfSSSkoZ(-H-)*u^Rl};)NJFTPoPtaL?AH`#8KxkHYg?&D;z$|HhtXSc z1>p%G+35vsl{+~MT$gb_mXY*T*<~={szo7cS9Z9re#M}nwiHxy*b=|4Ih0>q1p>o! z&KNm*p*)59X*{F4`R|f7=83qKOX+b(5HZt8a(Zp}pW%z=g;$*RNL#g}6S=87xRw(> z++LA%r@C_da%ca)w_uuv)R>w#I{x1x9$WZ6o#KMCM+yzmzh4=pse!mvAs z#!g=*sd9(!>X49oJM5Z0^HCsa$zs3$pR&rR+LfxI3#pHJVmwY0I60XD&7$`|Q|wYm z@Bt1TU;i5C5mtP5@7=Ny&XUecxj|cm2C}ILv^p=Ms zjt9v5ll+0C^w1=Z{#5_vwUQp^b(fv3Q$CTD<;_DBBi3=~UeJu7=(68s+J4ZCPS|5} zR!`;RFTr5Z#LW6itvOUu($jcG`@d2RglSd1UCfmwZJ9Z#gKuOt_cNG?XwGS#waPtc z5J4pKG?qKuZ>V;9eAieF|xt@_F-v{Tay67ufsvpyDO2SK| zs;Iazu^f?B!xtEOwB1W(QsRtDy(M3z#fO4kR};ENx!sSJ{j$XD!R}j&dQz!d0Hh2=lPRy4o_eAufHWl@fd?fu7>UevpE`US45xl zXM~^1J$+aENX;f+bNEDXGL{~BCUajW`$^kz0E9+mDI#0)sYkTgPPRDz%0Kf+BZ_z< z>$q}s)q7V}y+D#nCA*}o{t(5{{j~+SG$iz;h`PkaV9n=jl5acv7qyV>6t(STw~wYg zmz34Cjwys+R$fbr+Gn+ObKjcRb#NHcPGTsdGES# zLI-z}9!;qTCQ3vEJ!N5u=JI1;*Dyc}Yp#BdEip2=xl3`wVq-hi0jPTl;j2G`{P?W< z52)G4u?@P~=^pWr^;c}5z$1gN2dl(9?reIahj-fKv#ux%)6yDTY&5yoW^k@2GOuBJ zHtNGhu;on!kS6K_`?-+e5m<{)YlJBz<;CQQ`tM%)#F$gX4N8^*b*kZhdtA}Is;9O> zwLZvvnY)UYV$GcWic6Tr>x8v%37+zSfA(qbX^^6A#^kyALRc7~uvBdth+Q@?>q0!T z<1LP$-nd8wCB~!?YHi?K)a#y51Fi0B)T`wZ#nnDy)OCh3rn|BQFSoU7_j(@#wGt_1 zs^lJF`W_Ae^(Y3>ChwL$APz5~YJbmMxMj3hY_8lAQO+Tpb9)~~#L!rO=G_#0&HaeuNKza3x{fsW z{0T$`Y*6_Eq5RmB-_8AX56NSD*>BaqoM}X_byjHMrOfHG3seZTavERUYdigtI4^J0 z`Rz`sY?$XoOpZ;QkK~e(RKOn|1NIJ$2QekWDfar$&IE&nG3pTZewmSN$hIJknRtym zmeZV!ISM)DUXQBcoE9xm|0Ogy6hB-xeB3$A{Yrsxx%x20TdV%`heWh<%UoPolBu^p zU4SP+0O-fFKe4A-sz?~K(GB!;WXJz=EUpL;AinF{XAc{wui9iQ{G0~tJN_s`G<`H> zWQ!4+UaI@t`s9Ks0D}u;Jkz)Xix)t9P}JgHg-dqh!i9-yy#vD)tm;3s)?vm)g(pL& zGA7?K#JrG{Qb}ir;(u?!-IK+JvH6{OfI|&3>$i1K=zz5SqYUoiai;MgOROr!3nel9uX}aaSyQn-U>BZYDqQL zth86|ZCr0@|MCi3>N78G%OTMCC#I zhg2Z#PuhWnK1m$skl7OzA&;_U&pkhxK0&+Kt4E0sQWG!JH)m31vp6^3qdX>h(xaNg z%m2Nld(QbWc`dBBFJHO;C-cnQ-AMS{d8dzw{!i})?m?(H?#m@E9k9d)Spb>z z1K>+DY!r-9TA|VAr%&OpiX9|BxFn8IEsb>)uI8(KwFY1%Kq=a?px+5kSQINxsdME{>n@g3}!h zqsUww5++|NSHI2gPyIqLJQED-HS+roYE+wF@vs|=C4lL&9mR6fIPE6%(;UW# z(d%sNEz=|VBYJi73HdHcFFO1Rc!K##RMS(r&#i)4=ji%D721pIs7D&U7?Cd-Xwz1; zIko}KKL4`u;496gV*OdoS$y_y0BYjyQ2d1?b`5hTw`$>TW!3Rm-cQ;^qxN7wv$_-mV1asKfRn{a z@j6%W2W&vd#21HgAGOHEszc~yQCQ~c5Aoct9{me|&cMAnxA-oEbA%_+V$Oz<>*JpM zyX3ihwIg?5!UHepGk=0Z&uE@&Ozt3E1?Ykq4D{TtoP{#A(t-6zVK0T$U4bWsr}v0C zZ13v_yob)%hwl&3JmW)Nk)6$Ir58tu(9Nl3EZaq6XF=|Iij+o<{90MkU#I?F<#$p) zN+GznNOAFtTrH7z89f=(gGb^`vFSG3uD1wU<#6-6(pa7qF4iuM zDv%tIa)69^sL&z#7 zX9Z^e{yT4II`z=U!;yM4ZV{R)w>;2M#-5o0G7NM;Xk*ZBKh$?C2jHfJChR+q=<{35>C^aIKcbxz0DdC*l|gL04jgh_g#)@ zv~*@8?1#6s5Dq)xp(BakA)dqQOCu+miyPz_ttpy8z=Y+28p@N=Z1&|i1Uq7nSDrTk zSh)D(kT3X0MA@lo#t=lwlvvSV)VrdysusI|#q%AFuOln~)&JhoEd0vEC=&f1gQ9vD z-}r4>{V6xQFWJre^}z585tMtM+;LryY5c*Q%gYK|T^g}pdb+e<`%@?#YuLXfb< zek)7M0@COzXYc-to=d3t%GI?y(Q#7s5^yuz9!TJm`749s?Ma_j+u7SyS-WT772n3B zwQhiZ&{kt7nqGwtquLF{-bY4B=c|)T=mwjHdmH4uV(JJMe#3VAhWe#_PTlf0UEO_* z!ed^uB|Z02UmRAE3*gd)_NPv!zf13EW7gjCk^b$TR8d2&Dnas2qWsF+b3X(ig6P8I zr3s0Y!6Aw1#s%YvoFi<(yv)bW>;p?U1>v*hh0b3>Lwcw4r#-~@LV>R_C;a^93e<{O zLv<~1MAUS+A09&a-p%EL;b#BPyT_d1U?fg7nXhipT89(A{(63y+GW>4OV+fUM7L^_ z1?wPeJq$Ex?%+covZ4nhw4<}3U+r996nRsUqIikV*tvEAUc1UW{v5sNn6rj+CulRoH=`F>iMvocsifz@k@H5V1nZ;qlbsYV%xnezUtB=;P z(72wiUK~Sk!2>HwSB|vJxf-fmfOB|gy`*5Y0IKVzqwQXpo$NJ$G(H0hSCEhrsZzgq zx)xQ#E89&x-eT4qfZ1L549*!qk&<;kPk81=BCUL<(e2%<Js8Ip>AN*oeCQ4V8`MLvxwDFJ!E0ZzuS5 zWPB021X!#u#$&O8YEdgi4l9y}`k${3&BYh=te}2!fh(%aW|BCxJSkJtSe~h#zX+4* zsGyg+AZ{$6Ru(iMo5LYx{<`hoTei7X$-Xb=3U=@NL|UzpRF=baTt`ZCb)@7VO02c& zU#M21&zT*zs^+gPy zcH*W=xa`Zmw3rUw5mXpRHA&uZlt)EKs#Zwmc#eTCS+OB9M<79Kr3Do09n7Y_YTu8- zmOf0)J*R&pGKYq$uh5qaQWvP_)t^I)K2i5Z)NN&FS)_`B5vNW16{W}AAtX%>_PQP0 z?|_pRj0JXb@j>v%tQxCo(yPQbjIt-Qv?r47X|bW5#l-h`OE!SnFAM)QX>%|!(YVig z?&K{z+#+E`hZEDTD>$873CFT+z4^5!=cajsb&FFLhtLCm4X(os_+v0RpD2~&fwJ|) zK+;&xg4t!3wXX8$6ZDBo6PM_5?6FqtZ{@N6R2_r?Zva6?lpw5JoFyVy@yekkE09%Z zC|o*~&>BYj`ZQ=FZgyupd1u^3J%e>da3}r1%OA@&=RdDgJ6&=Dop1!q`zVSvuaxlk z##R6m^e>a-)hxF*i|j%59AmM>kIK7dxVTaE%M6}NY^;sCdlEx)L;#6f`zFDwItyji zFx>aHmEZQ~Gd~(-8S3#EQ0Tc*moK%aOf#+5h)qiM`I`LT%Mgw(*OxDdZEBqY%_UF` zFf#0lU>jf2TF$oVmE0Ol)*_8I+zhaVW$+yC>P^NU$$FOY$mPC;h~gjS#y6E)qka5B zC{?BYbg!DshSo`+98KH|o+^{C6Fq8|9s9*z0p}0_^@0H zzuo=JjYrPTo@6&|vTO&HV0r{Iw_Tve64@uf7<=ajg5_7dl-mHD~yYRsRrn*5VIiO}ZgsL<#!9<4=-gWQhwU-6DC%@?61T?nb|X`%kcW z@;XJ#Gh7n2*at5t?r~m{b!TKo7a8v?)du`y%>6aYk~&`17q44EiCy>W$F=_0&%wCb zb;tdc&CClJ@^Qdf8y%8NMtJ9F#AE~*B1dDUk0sIyH~nnS=}qNC8@wcIVr?fr{S@KK zAb25j=yXfno?)A2=;bB(R z+y-qaL$ZpDuq++YGcqLrDtvoy@}Ze8IoLb%G^A!&myUT*+H>#UTMP#8j0Qn}(2-#U1dG^ecj#o{;+HDX>=0@Vy>vKOpR1u{G9&XGMnwalgRsZE%y9 z4m)cs6ZrPu;k)!gZ_yKcU3U<&Ukft>**+}7GpY}x2XX5!C*lZ@T)q>j9(LzeGd*6l zQ2By;C8c~W4)1$jXzw>pzd7QPo2B)%LsL;OwyqIOKg87!YsYa_)&JB395yD-(B zb}|;K+{%5(>6w@*xE#w$?u$vy#Q6R--NBYuV2njRJo~ZB3@IWqqle+>8t@w<)Cx50 zPW3wy?ElS*@Ht~&n;ddgLnh*^T#*0XiVP&Ra;g46I3f=EMN~0Pst5gOOo>BTUFl=( z<$j|R{Q^F9>D@p+9sRj<;xfZ7(U(+tZ!>YKI-5MI z1@`r^HwmtL#-g?*R+{!Ii?G(lCVvjjj^$S_q1m8{Y!@9d)G#Jq|CT!!SLY{vulF-= zA55~-uUp@%*a4nrf{LZ{L*q8cR|8E%y>f19)TakrC7JxiSaG#yg*v_Fy+VUF0~D6o z3BbzVKxaoM0tso5=w_Bd5NZKQ5bdLAR5JsYKd)N$IDjKF>XvM_Z4O=aWoT6`Xjsra zl#XIb$-LWY2Iy}(sCf`u0b|n6XSkale6OTN%kwEZpQgbA-za&;$y4iumkoXJ3u^Vx z2(`Q2I=^k`a_sL|3k!PIbg3zDDMGTOzYS?)7By(q18II>%HNjVK~=-nf`49t%x04U z?Il)XL^v1AWj9JJRp-2M2bHYJn=ReK@WkE8!_lts{o#dy}Z&zm$6g zI5$w9K*mAx&C_SVmSprYX!xIjAZCl8?Q?O*gokr|dXz6|KL=`;7$_fRJ{!yf6|&6n z7qgYk0P6j<7pvBl6qtc8)Zub;uUY6zu_h;SzI`i{PWa|@36q0UcLNJh*QxV0mC?{p z>z#s?bgap-`WkR|_!+qTlI4s5U3qxTZbBXtk(W^lW^t5qm^wVrrFvGN{hQY{?5+Pj zuRsWFhQCDL^zK;A7doEk7Bi_>Mfxw-z-kS<>_bg_Ek?n29g%%tB$H9^wHe8Kq%cTX zfO49vpc_=AR87h!755rUk;f~>2Ufp;&jKw8H0%D{?wZ?;)Xs-0ESlcwRiPb8JcD{v zAB4Mx{B+*=*-Bp((CA{jM=&>kPy8u7T3c`9V+-0$F;Du_(D4puBWI7C@R7~6*{a+O}t4Q2w)uSH{aZyzT0v_7o&s_a3LtUC+y%jY4e`?tG7@S;sWK`2)2&mOJJ=>P^*`{JwkaF%`&>!=$zIczZnK z?}R$E^+v3wFSRYG3;m;Gts(RI#(z z9VC8MACj83lRSIGJ1PC54p%of(<5GXb4o1923gN2#7?g_b8K=O6kAL&iBc6UFD&Qs zoD<(PTmeQ6E~yMd6ak9Oui%DeEAy(l8JG%6uDN_zObYj!6x(XxRJbVY+<2_lX6Bf2 zjQPI2^N8bNf?2nmj>0)L86>(|xNBNX`slCOVc&RZt&bUU+22z35~s=(-u>;bwD!ow ztdwf*%?%VUOOPek09Smy8rJjmg{HCWpB<91Irr9uSm_uj{?A`6f;zw9mVAs4+m$}w z-|Vl18OyA|B0N7U-B#%g_jiuuCTTr@@%NJw-foIq$I{DfalNJ>K2|WfFD56#7g^(K zuVdp$J~i~LAh-_kLy@`}bg9$nz^ zew4faYuEu7{Tq)CY~=PRFxL43K4%mggk01@_be*J<|RMC8q^<0DXfh1u9vS$t*4b^ zPOQmCKE|(kH5neO&(_x@bpAXZy<^qhFnyyZ zkuavU9+k^O?NbBm5?Js`t@**1<^i~=>l67G`~2U32U=NJczpv_X%XGEKEduAMAgfQ zFse}#hkWMuu2oTh_Y7FyLQ9hG-e+f_2=}d0*NtJ3z?iNB`g>!`g%xq4$6RtZ7qtd; z334xGXh5=&2;NtOY(IZ}WVmmpNC|-FE4#W4hg)M?C|S!83b>SlULWkc||D&-;QGxt}S;)HPjTVoP!s zS@B*r_uUuy-XkJET*hR{d!3XcGg*#7X2`Sl+hb(1K(MKB>1venv-&~Y7^n|HkT4;o z=S^HPlLP5`bIf^um?v*1#FKP`h4E`q4FdVnY7{WELIbQs@x=@D*ac|WLBA22bCs_# zA`&F!&3K~uD*5gH;AYPWFYV-*bct8G$d#S^Z@Po4x=rDQZ&VlY@avdtK=`{RcRe9T zpS`HjOq3?haJZ&u6(RF5)|>bWsU+W=q=lMfs=M;a?84W5{hU35Z!g&)Ue^lk1N)_R z&2Ku_@~S$>FO9zItlIqS*z>a5&! zR_Xl%CV`F;%YUaNdMuvPcYrx*znF)Rf4S586Brr}=H<PlWfYr^qDedK5%v*t=2T@#!F<%NcNS%W5I!}i zYz!MdTsF!33nS-}H;kD(){qsQjD<@glO6mV&set|=BZ5lobPoOL3bJ7Pyl`r{bJFr zql`1jq$=9()|Fo{Wh!-f;ExCTHv{%U3he@?Nq;Cso}m^aQzei>#i?$Qao!I-G3A~` zV8iQWT>ZNq;gYa>X>#<8;=EbycClF?sZ-=D4B{sgw#82}ApGGr;Zl-uuh%;+o|FTL zP{CKtP;o3ef0AThZKWut=<2_SV_;$hr>cBQ2P`B?bga~+twP%$!A`|jgmWD!@8%b( z7&?}Cr=IDdE~qG6H#pTslMkX6g!sR6yWcx^Ps#~VkM(N1X|A(s6^R03Znxv3qsrk4rDNy6AP-b z3GmtR)sIGj^!02s#pu4w<x@(XC{62B7?r)#n8z_)iS;4=67 z6yY&~!azpD%jZbRO!L*IXHu<~-04;8BlH-)bw3u=-LktVD$Q**hi@CP1_sIFJ=<@* zkYoNlv+IB|UuyOAr91i+W21DP3~Tf{EvYj4pQ@-4@^-O^ldpH6Po@{-pQD|%f_Zuk zzz8JPb5_tX@( z;?%sU$Y$o=jrlr^4u88QzX+6g3V#@r{Dqt+i-9FsU2EztqH(Z4-vVUpNFe?_@F}TVW_71bIrLkRvm$fnZoc~r2eAz_Q$x?cKB#cf0E2h{Vzf?`7(O| zdkd-Y84q1P*+lbUj0(Yg0i4#C2ozwXTqPQ_aY-CYiH38@+4G(Y<}&EUd7BN#wORok zd=O7FN^!6F8o}^YoM^K4b4`N|0EgK$PS>9a6grm7Fe5zc%krey#JLp_ zc^~nhp3dI(Wvs`(o8=|zSB|7jy`JBA=(<5*y6`WsHKv|lPxKfPw?c1B*r~RDyRZvu zUXFZQ@pjjj31)AvO4#{wot;O)T}<&LHj3JQFo;Wr&L&2jIBy$o-<`v2r)f#l>DSCP z9T5X-DqUhl=nO$$dnBlx$D9=HyE8Dfkt5Bgku$<5y6gLb#5XbQqr{>vd#^pGW^Mq-qDz;>l<;3}vfBCqLAto9DamJM2ptDrHxt~D<)U#gf(H&tI6=>2Qy{c)AZ-wyHq&gYI-_II^CbDn3eEST-$0L8 z9R+~8q$y1cH~phzoCBAUBTc%xJ-ZgW1()|c67-6t?H4CMMQjM!e7$LaH@8O_9vET| zHmO4E5p|F`CPF!8t@Hw|M2888D>&GH8HW3cpIsV0*+YxfxCMoiuC@7}tIOcvi_4f_ z@p5{O)2>>7!huKqokhl*k9=c_d8hqO%!g-$`)#q=29*Xcm@2`JpULL3z~2z(!ZRI| zEs54QjS4PxE(p}C3R#4CuEQolRqxEhlXxo8AqWfzRx|mo7jh-3}?*A$Op5UBIBemjL{y3Wh~oDa-w$ao<3SjN2{DpKCLUew(w zNB0Bs{KKS%DbE#FrW#DLTu@91NQI=Mbs;kxUuZLjm#iHD{G{ZJLgj#Uw7Ss%C9Lh5 z96v~w`-{b-K-}w82>${h>?l{L^Q<*Kd%OG$WM)PvU76xpuO7~4Gk)%ER5i&xe1JPL zXgcmMJZI&1SjYNGuLus^@sRJ%`}N$IHyxU~iE1k85a;M~AG=X{P}YV5=q>jkRfqM) zNy%+h6uYPlpS;C;FjpMe+m)J?>G|_1Rc4Zz4MXOf&J;NAGi)hb(Tgu`W7ykf_3_#( z*z<04txs7I^69CwZ2v6ap|*xScVu!Y)kr9ISkMxWj4+qhHx|%ldkc27b-K6;9R=2r z%Os}et!o+=MtH^N?H*K|vvfX>LPcB0iE~>IBWNX# zvJ6S?6VH<)Ql)&HTh>a=$tA54&Y319#kmJZ3h6`&srmQDD))rrOt~*X?-N_j1i0@+ z4*}2JGV-=hpt&EmXuBdn=KWi=K0jfq)-N<9Bu}(XM4okHLyN7@@^-xR^59uya#S9T z^g$roeC2_<&Dj%wHysL-m$pl4Mhc;T4CY++frk2lhO2~6^Nm26WIsRW5Xx_O9<6_G z%!0Ph<4UZ+bdxQ>ox{-KHWsbp$N9?Y!p<#|bU)IetA=?vf#G8@53-;jmM;#^?v&4h zj3uQ;H0G?yXEW}uAI2mBUIE0T)0gTlViU!=EQjZ^dJyddwv!WhGufg+WT7AnFi4L@ zfJ;7{w~^zCs-xqcX&Gj=J(!lQ<&rhWhgA2RMFgI4qQ>XA_AT4Kq#`WJ zvuoznZ{o*V1p%4nOvCoyJ3!wP~mGbLxwnOz#=Wyop2i!B>FfycfO_C(6tuH}~bW-7}Ea z7ge`Zrzn6@(%0OiY*BoAFsOfZ#AhvlY<Bhe#aB5#0sz zzuZl0=lztXL=gu&Q}FW2dcQb8+rKwRIo$au=NzLEK$fsK>h}lGFDYo?B(UZYbHoB^ zyit`GMwdCDzAYCMzThGA2r(ihrvaXswuZsn;JI8G;>4-%ElYsepF}9W(a&H59CmIfFmKs zHS1RcSwDdne-@%-!AY*T-`2^F%O1Al4BsyRXky8;QD%)VkOw%$SqM$RZF~U#;8NE zhg#L}$&`S8TPng8efd{i?GQ?ERA;ZXp&4c+kbq}cBs4Jghgh@@m_>OEh`#$ zkPyD0bxO-3UBlVo#?D$C1vS$#H=v?}7}qZuyB9fEJO`hPe0E1O)9OovDcbi)amxlm z>AuYhoO3mXeD_op)cLCPpahgh^fu2PC7XBVF2+CFLZ=!PQBm&*DE>};*VH2r z8r;g4|1ParNqfD-2EKo#xywiz*Td%Al=*e2)_wrgoZ_(-|0-MCq5`&tvtoP(+jd?SdLlYDW{r-DAY!R3gXbOJEu7%k)kEET9yN#V(%HbkSIkx&c(DHTxIxNv ze*TBMK1<9uwdkt<2D7l_)Wf_-6Qd!KGxt!gCr}Tk&4xn<>^D*dO)?gVZmNqhimtwI zhR|{I1ZmMp0eUAn4Y}Q49!S*18yS+k4m|G;Of-)WVz9JJ+?rK`_bc)fz2EEE580G> z-w9@E-W?MhZk9ZU9E?Q&W78)a$NWY|L5+-uhezZ3c{m=QGE%~hzf->b2K~eF45VP) zpQ_(7WWevC$yS|It_$*AdbhcUXzC=tX>7)TmOaXK<|c_T;y@G^_cnbxkyLvz~fuaIVKPUON=?%T){_?>Z5pREju&r*L0pEo8;-8y%%^-rnIzymEm+*NIWMw!x{!A{1IOErVr z<4k|tCx}j$zt4-SWT*JauL>{R@q*4p#p-9axd;wtA)U(T$55>@Bv^=R!4Wl_ZSqji&1Sx%+5&BG%)p3NeROYe0Y{&F_p&K0(z-`JQK_ zP78rYm*j(t6Pho)Y3I;HF^hZ9j7h#N9P>x>KVvKir#n$o!zI?`L!Ns6`I4U3?F)|H zxda|c8PzUdGW8sKS)20jUx;=v_=xX1GTA&a*ENYeNE3E5PyZhA{#fA(yMRtAf|9bQ z>EBgIr!N`QH)>}YxE&nUN`QKSj#i6R`*&vr^fyC&diNE zD6!>2nd~42Q<7$XHY1Ftl4!*78C>{F=|&NAesJ`Bu{55#I-sC9tc#UnDZh9BX^vn``2C|W zEryeEF5m-N$uqMLA{LDmtN}{VSh7!vNg8#t>1)aTXc&)VE->>z8tbR32UK-OMle1? z0eT`YDEs;3`*Goq)oE`le5}pyLPjW17BahyXQ$2JcCVhHbMdLXzYXUi4Fv^h;w7W14i^G~5LN#hXXv?A&-AzGgXzK`ZOl(k`zUV)q*0ZA z+H{^0755v#k2GmpRG&5H_yKUAQ@)rf)R(w=I$ixOIU64DHH>-_hX~Ply=)t{J{vFJ zf0)xn&Z$=@K01Q3A>X*7Kx0PcAZ? zg2Q1eXEZ3Zt>h9s`nx^aTSHyg2T9+Q+4Q3DpuR00aVI`c zwTY@=I#tIS7&9q7C3-MmDN3Fa$)mEDJ_iwV2^UO?P7y8@$Qi46Sm~Jlb`jsMtw)Di zb~E_Pu}lIBy#`>K7EomjGx5Km=*k11;U!HtTH$S63rh%jZQVYfd6TlWkXSL>6!*S& zJ!?Q8Yu1RXOn*`!t1o2$cz=dBk??;JUo%E`#7K@TorGjReAn~F<(DB z)_x4r8Gz@{nW5q}v-`pZKrKEaTKPKgVz^qh4ImQBD*RE(ur0m2S(>@D=?zaV$|p(eUL>!V-AL<8cfFK; znvye`OsJ4WuRja_+>s*rixlgw^a9a%#z3^jYkr10rZdo9ypgCB=Kf{>a?QiC>5pz_ zocmFX>7>Qlr;FG}FB%pkg%CC%wNHs+3((iMC0iZdy6Z~I`%Pmr%%{I08_;+NKP;XQ z1yA#|FOmuG)v7?5H1o)2)Y=;C)0E~jrRfrO;uoH~0Au*~Qhi#3xtGz;AV#}7j9TJ{ zDpqlX;n~F?o(gj+BgHF9gG5RXAvEAvl4sRj^v*=`H-kh@I<;&wpxN?X8be3&^-%a# z0-0?0{6^jDzVqC}8-NK9?d=HZJ5dgu1- zJGXAA#MZ|jM#YESZFd-GW-F+nLomrYMI2Kvi!s+W6Ci~V2CfiOv=zmK)K*a_3@5VKnx_Y!ZO zbIls3-d?i{^~xmm4AOeCJ5-5_J67GHtX+BYE5813g%H@FEpucq&7%B`aohN=w>1lw zm{I1S#ptagv9RTcoyhLuOZ%#n4`Ny434ToDr93_nm3((QB~Sd^6S*c#ZjpZ_bQX=T z6|$LC-nvr~kOkgJ*Y|c3V#87nQhuQn=%#pIGm6De_u4*L1U(p+zKhDzcJk$e%ip4S z|IMY+U%>hH;E%ylvN1Ldw%Azh{!h1zUA{L~FPNBR`epv(Z%ouNhWMGC3UtsXjUsRE z02Tt8L#jNDYxQRSy+!@cRMNHUkEx;H&Tz^FuP#7{(wEwc>#o|b7uTI*ixlsFWCZ^{ zNKOrtzGZB(K~EIf+4#8VCf)l=R6pjv?)%E>o0y5y{)fuFO9mkOpNY@^v2yQl-K7x& ztLWR30Z|5q-q^yK$A5WYc%J+GjX(Y$f9590Pj4dl#6wMZ&@=bxS6ABeDDVF11fW?O zxPu%0R=M}PvU>6Wbhn6i<#Z%)! zDgqQ~F+FqhT0a({+{+~k|K56;$K85VM%uUGY%9Q(oP`~P>1J$QR-DV5#{9P&_TMri zU=Tu;^(XAC+Dst#5$`-QtD@S{i8rivO-$iua8}%A<@~trADdFUfP)Zw?4+FGhRWIze+YKzoyF-;Xq~Zw-!)wtGkCep&#rN~6g|zch}u)Dl&Y z=}>!Ta=MVEccn?|81n_~D`6r0gQ5QRg}SW0IJ<#HmPYNZL|50vp+{?tga<=C)j4jr zru1M0yBXT|4q5<{ih&|QYLL^!yIam>?QJ(UiLtR5A!Ly-vsobhhZpyd(ZOr&^JWCQ zIa**Zu*%6uA??4_wDIvNJ&B~*frRvfMX=e&l;uDF-dd`H?HHR!QP2y{W#u>7+35fW z65Q-wE6E4@%2wGCGL7)6d2%VNot-ydlJq$F$5n`8ZkXDjUn-xe?1J_08yoQEbHPt% zA1KmBZp``?+IMckB20Vh_T3xq^j*OJpws_xr*HVDcThBs#q{s0c;jz$_TU@S1%vR2 zx0wGgL^pZ#XI!QyP2Ak~-fw_G11jGrtwy35IrG<)0CH&-&+~2y^}PHaKz%R0LaA`L z>DpH6BXE9#b_(LehF0?`qj53d$++wap2p{p3DGo(So;6wu9*DkQJPOf{zbv`*Ll~!EB_BU@)!01 literal 0 HcmV?d00001 diff --git a/src/assets/blog-placeholder-2.jpg b/src/assets/blog-placeholder-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c4214b0e639a782769ea329846e51ec066b7976e GIT binary patch literal 33136 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͘pX%<6>2&FO; z0VS1=X6Woj*gJ39U9o7JM{tU|IAh-oKeA}%im!rP7o-XFtCHX@SvV6#`weg2F|eS) z-*gFxgd92sS2>d&Ub`kSYef3``gjaf@;jhhbcXZ%fE0}aOEqCS!t|Z5aF*& zUTCJg&5q{k)2|9x=|Er3Da48+wCQQ$_z^pJru5T?X|x z;-K+H*Vp{8Dz3p=_GyMgdC@YwosmL0*Q?sL_tq!katwsjj@er>{>1|qTwD}pBHDR0 zD{@tZ^I!}3Dkh&0gUA?l>}i%-@dqW1>07Tl-%J;{2w@vC?+QoRIt(^dR^Ot%C__Zz zYgk3($*;r5OBrmQn9Ul$g6l_{Sx{$RB~OS+)4ijva?jKk2hhCPJ@P4=jg0dNr}5gaF&4Xjj^c|g;Ks304Iey2M2MKGi0kLQ+%39 z<<(%z7aN+jSnFowMl}U!VVa9vs@4wg)&q|0Q|^7eDYD?!{KF9+O*J9f#ZoX1Ww$5u z{)rk>8901}E%)>f7XY#KbuyhX#m|1`?IpWT78lw_f3hT~G+mPAH05Q-bu3ur0I1(< zIZ!loy(}0NKb(F^UE%D3E$w+6;5qjxDWd3C;vEJFW!y56lcjTU91V*<5x{g3&`nG{ zQ`xs9yM;kf>)mF@3R;5^L)GG;v=bcn$IM$ZT0n1{AT^sPPx#Q*=o*z>Z+zQ?Q(RoI z$Su%9G{JL(RqSz&Li`n`hIjJyl{QoNr6T>auV$CRmh@Ia@v1{f15rQ5?)-shT%sxk zCL(R1hNIT=Gu4T(HndU?ex^euDku34Hc1U#nQdI;8Je05v}BF#LzOOkJ$DUK^nBM{ zU?A;AXB%CkU!t|~vAmf3<;NW(odNFTai}QIB*A|f17B5XP|mtl6Vac{$;z;lQ^}!M zK*dBtz=PaxCW=qj?Bc5jRf;Ew@mG+gkdA7BUz48MuGkaVt+C4X@pYzMJ4aq)Kzw&G zU8fP%v5Q?RZGSZBw*B>!N&R1snjf)g92`b)b7~;6I@d=>S?Lbn^Z=iX4%sEOwpsL~ zKya$z!ztj!c2~17CXo-a;w_Fdu?wyy_0r4VN9BuCq$20v0s~NQOwwit^Rl!`Y7(4j+;`^Q#+zGHB;lwG9hzw6PXhxKf zYc%QjJRPE#SQ975kYUemJxW&k*UtdVq6Rjfn*`G{i|g=f>PFBPglTRR^ar zd^z?6{E`*WJNr|CUhxr9la-8#x@Hq4N3h=i zZZ=g6-~3AyrrCW(zyIb-o@QS{U7RD*Z5Liyv+a03+jGmy2Y<&FsTLj`@mLc{_WsB& zco<|aqwi3is5?fhnED&Ee{5=3l+CWTmTemqU(gA*G%vZLjWL=uJvnFjVdOZtn^^=9 z9jX%g@bgYawxQ#AN+YdV>*!oqQcA?7$VQM#GlIvz@l3V~%it>VmniBZ50%3~sqBbk zy&S^TlxjAn58IoSNcwO-h)XMSW{&Q)EjLy7HMPBTDJ_s+(rQvYQRrfip|aikWw4&E zBP`CDoh}-jlAlyGuR~_y-1|71H)2z#Hp5`$T2OB8)%n-FA8|7p$~6&oUkR4<@|6CR zDQu*T1((Iw3b6B6v%ju|TAI*U-~&xB#O~lRDxz2^ ze>E=Y%KiS?1G!Vi@8TA%yJ`_%CS|~d*(yyZn7*^3^`7y-t!{_%q3XRu!JYAdbdu;R z3gFS9AwhFrxMgOfXg^vdFJ%@T2Jgq`1lvCJFb-Di*133VFE-t;G9CLYpelIlval9* z%^kbQDONN`Kg8NUT)fEN3s;M~Rvsa3rx7dJF|gk?`$k5-@{q$Xb zvuDWj(Eq-i+CAK$?U86T zko`74_n{`z+T_cscYPLPy4bOe_1!@z!DbK*fZu)ESRNAx8i zJMCfC)T7!Cf=sy<#}m7ClPG{y>G*VFNMBd7Z$mlTm75>aW>4w7%vRO(OBqwQWmz$< zvt_cj_*F7&w)R?;23^di0X>ugA^07%g$pOVks30E>Ccuv?DAbd(GFYf4&ry*m_g%Dwzb%XTEEx>>8ZH@2)zD`05&SQs)>kCQtzzF`VTSZH813!GD`g#Eia-@{Bh9_ZdOv6|>2 z{UK~*V}aJFXOmd<>VUKBD~&gbHg1Y+v88)Fu|)vy8?#7CHXY|IixoYcqgnC=YIG(u zaD!iaHq(l7nY961ejd{vMGk;h?lv1AT+r z34%9N!EuHTFT80D+VvNp`yyjHR}^=2<3|OCWBo=I`q8V{Zs8rSMJKfD-Os;7Mt6_1 zhZ8VAi)iYMMD=%b-*a;w%Q=}87)f)a9xFz9bBLVrtGUblB}(~GY07fQqo@Rw=FaD1 zYG{L#6Q>@-J~#!-3L7j-rx=zD2$J<`NXjvxo>VmAM+r4jM_YR0z{G@4Q!!4e{ZTH} ziTiQQ7u=4MH6pGD2&=V%VYueYaJ59*1q9v7jyw>%FWDruUu|*mP8A!W^q1&&vYj03 z$Kq!5InrH$O-bJHELug((o6GV7evRIN_?=UQ_iY)m1R>Hs#r1Xp*hW8A|!II!00-~ z!X~}IFwK)x`Kxud&a_7NbQI>(M8Tr)t>LCK&fkl{1}bd7gzxDV{R8RJP?oFAOOK04 z9pSaF9$*|(D_1}&OiT|J`_Zm1uTQx9jQi`DDU@t26s8-ts&CI3Sc5aj zityJ=6B)r?_Z6c6hqjMdoJ^yeuV2ZVxtfbBLh#xz4_8Mau57c$enn=9Bzw0#1u5~p z8c%OYrq%`2(8he*F%jl@E~^2y18B!KU$bJ%T;szoii1u7pBF_HzFyJaS{A5|`-UxK}plIpqEuvYF;#%jV zEI7y24B*0R}K9w@96{Mz4@tMRlT9D?Fswd&!hLh*aPU}xfdThV3V&`N6Sfwe%lpgV^ zJ5Tc8GdKu36}gMP_BT3xGB#4Q7N>9TA|bE8PHbgLC002>NMT?dQ69k5C%%1T%fW%A5jc9E{d|gEI*)z_NLHvr&KT;xfu-ZeGfm z+U4a{_ls1fnCt+Kxzv$MBx!~jlitt*Ic*Y0c(DmAW*vS}^B#H@wXNE}eWsl?c*f$^ zU?2xOZ2_5^ltfNB1sF_3vqq;|T8}vtrz*Za)bj_HA!J@f+?!J0Z#2In&eUUJqIKB{ zm~(hDO|B&Jaj#Qt^i>1*hwVQ+cvDfEu(4+a`3f<($sBH{2r*=hgT_#pIv7_pul|i> zdDFb_VT7t;VQqpPaY9Qk-%WzXpEEJ24wP>zp~kLLu`SHW`&IhE9kGQaQ%ApPOJ+B)i|4N9IPoj&&;&s$cl zQIVC`+HPO7xS~yM9ErdrQegXNMb+XWC(3~@;=gjw{Uw@AQN-t*@r&K(NFHxydD^Gp z38STr6)LdLf}Tf#shQBiWVHp z$7snpUM?0$QI~@$$$}z(jo%hdzf*MeDt6M!<=NK<^A{L#e3=Rh9-1sgQblX4&(_^5 zP4WHMq*%DW1PqI@OXb@RL!PpHtRf5YoX32Y7{^>CX91p1003iMZ{_-x4X;Qh1)O?g zq|iG|*KNY>fOaQsTQu}{z`bfa1E<#o71z}I2w9lC{u0~69^s;)Eqy}#^J3|@Y980d zG^^X9kn_Jp#4&1YV~eJVPZXbFKBJ8re^Yf=@sqZu^1;xN%MThjAe8%-CwyJ_MCW3? z41isH&UXK*Szc4szki9^Z__$C&g4V|biXBTZiZ2kFSJncN%%e4iV%_S8uwl6`gdn7 z5D6!#=_L*}Qo0*&&b_AfcwwN3@9*ZBdtx*hGk*RmvRZk7@q><-ZRuP#GR8J3`NxyK zglx2i%WCF(*KZ2wm{Is&BHnDR(ST^`CfLhIzqc(r0jyXh%aUU-$dVLY;W$?LaW}?| zC3|9Sh4SHO(e3MF#jnn*uZ|oi$Cpem%m8m%)$_tI9gWKV7dI&pmZD&Xk_NxDYlj7v zWq0vh+i0l6^Bg2n(@JQ8FqLT2&#n3CCL2_T&zkxOm}uUey|^*!O1~kOm2Z8V72n=z zcU9dcD^ViQ?e{den6YxZWODh6oj2r^UDmve&EXKI+z_KMMl+fwZmMcfVFRt1ef!(l z)^vQgn_t^l%dR8++S6FmutJYTM1n%iX+(0kO!5c^K;3dAu+vpw|M zSTXA8L6Rk_zrbnA!ePV<%>syLms1ipnbFw{T+*yiLKn=hhiR+@D~yqL%3yY7A;oTc z(N^-BWUgZPT%W;2+W{e_L{9IM1 ze16V)aUUp6)R~fUU2j|VHIC639-NiLQ0*)3w^%$`7!Sx3L#wR|bYC)y$5xf<-}ylT z3|g&}x$SIY)|vo857VF&aAoreX$0J8px#CZZ7vX7mTm9?2QE9|qHN+_S%nsnT(B#Z z47D1LkK?4o9A840G~+Ji?c_Q6jV5T^|IB?rUn}*o?Gf7<@<-l|kr|L+q5|w!m&q8f zkEkET9A`U^BTZjzT`^;WXeA|a%<@U2GzH2Kn0U-96_ax*zp!V&CY@kWg`d7{nY@TE z2$bzBRq6Z?{He%L?wKKfeX>K@&sGlA%uzPuIcoi7}n2ekXTM>S$KxpSLtV18vsn_x!1mXyH5E z%$Od!^xr&CwwwO(Dei26iFOUWgkqIaL{+BCQ#aSU-)L1W?@Z9L?(ScrZDi(qRzBjG zn`CE=urIsE)`M1pMuQs1YJyRxbAe0hW&6ZxmhULI0uyX+;LGHt^69}J65bf6$I^W zf2Y5kXW$Dg6TeIak@Z4rwL=P0^zB~!`-Jd;3 ze_%M}kUPcqEa4{EB)LMWurh68_1SR1gwwJwaO{=84J%V3x4cb0e;w&#?+yG7$7S$FzB{sNkr%?P_9OFa}&J?vYtCpXU)n0!=S>v1sMYJq*%Ri-ocXg%k!^7}Q* z-J$^Lz4&l^7;!kPS0gN5d%x~jPxwP{f5EZ-ZMP}#?t>L#T9P+EwTl{ho??hIEa)`8 zd+x{IiCKV5tXE@lk9bd>W#n93aLI%f%wMM~AGxc($(Yys*85~?qg;aA!Zt(ku6>(F z--qx<{I^(ErN%~c&2-BopoJ#uRFHQ;UbJE{cy1l}^UL;3VSNpaqJU`4PzA^6fhhU@>Me#y7N;YaIz*vvj&j1t92HQG#6;Hj7#{5oC`iU zO^Y;C-<1;FBR7RS#I%FcdeJV7Uk(rD*IEqaXr?Ua^_GzpiuZapND^P=sLka}1{7J6 zPq>!*Y;k$W0OVk(DvB4iSuqlOnVRed-+-v9rfGqcV3v>7hgeB$#|8DN#$O@>7>hM* z2f)p=)fL4d8El-HM15#WY>w{uolg*Ix(x@#*!RrkYMgFDm=>Vq)w{!6ra&FSG1v$8K++EqtM z*D-ah%U1fP?x>m2#ikMaJxHnb$+jnrD;p3&)?32o&a3SNM%k@#yQ$R1K2BqszS(1zCa~xD=IU7d3yP_h%U;Am$ zGhJKjgzKJs;J~op!0e*-!7cr{$mXfkzD{tckp19aB90o1>_`(SALWALb%(8{(1MX+d?$4H-{g{|H$6E zI0tX>oA!1Knxav%iuv4dCSjfC^>4xAQCR7Uryg(N-GTj_K%iF4yFguQs_uN+JojJ^ zT4t1L73bS-9suYTb6w0RiL4c@Cb;r&hP$P!5(-KKgF=&gN;`^r z5_}fiz{Zt?8lxE??EMU4Yuo_&^96@e5i3gQ8&h$eX;_qjLb|-v)DvUhLhZXQuh&5_ z$1k1bc8~b4=1FPn90!9JYB?GXkpVlYu3Z(!d~xqrdsM4o5vg_WFxzwb8vA-C!`?sx zbdi6CSruLDlQ?}s=E6@TInKdf4nfQJwMYP{)+8@Q=9 zP3%_XjyFBUaZ^c;R|kJWOpFH+sIKwdi=iYFM^SH7*fn*{c0G%)lvta~n9G!*CAZIUipZ;(wV-&|VnWOWlQ|t^jP!3V&3&6oe_iG+%Gqc-Pz? zJSqH5+WSerlm9OfpoN{l?uE_GICPnbH`8O5jB7fhw?b0WiC>mXD@H zJ{sB%*Q_YYPq8S71?zVCXzTEjdeG_)+b5JP3N#IZb>Nu8EiZva7uCU0Q?=YA=i zzK*6xN#l|rsFyxvD9}QZFRm7n6aecfP&<)6=|I=_aiN+0&L>CExw}1mbc;703k#h= tN$+g|KW%fdox#|d3BoTnQwaB~9`L&})F*-!cp)V$WZf^}c<^`b{{V+h6G{L8 literal 0 HcmV?d00001 diff --git a/src/assets/blog-placeholder-3.jpg b/src/assets/blog-placeholder-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbe2ac0cb0c744ddfa28d406c0e90956a3398aaa GIT binary patch literal 28687 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%0DiGW1X5wzY-YA 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 TVJ6o-Ra1Fns$2dL{aO4U($WiW literal 0 HcmV?d00001 diff --git a/src/assets/blog-placeholder-4.jpg b/src/assets/blog-placeholder-4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f4fc88e293c2d70d1b193101df252bf45ca57760 GIT binary patch literal 38690 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 T|DXOxj{SQDa(JEk*X+Lm3zv-d literal 0 HcmV?d00001 diff --git a/src/assets/blog-placeholder-5.jpg b/src/assets/blog-placeholder-5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c5646746c08c6521843002a7491abebe6ccdf6d9 GIT binary patch literal 34890 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 IdcP0<*;<)SP5=M^ literal 0 HcmV?d00001 diff --git a/src/assets/blog-placeholder-about.jpg b/src/assets/blog-placeholder-about.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf5f68532f3ec832627250e7cc25c71cb034b263 GIT binary patch literal 21606 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 literal 0 HcmV?d00001 diff --git a/src/assets/fonts/atkinson-bold.woff b/src/assets/fonts/atkinson-bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..e7f8977eca89348892bc93330dc44763d2bcb5ed GIT binary patch literal 23780 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 TgZPdR1Wjq(Awr&0Te9!ymo0-qdNv>p)%*kYM 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 iK{P#$jT~-jX-b_^Z component. +import '~/styles/global.css'; +import type { ImageMetadata } from 'astro'; +import FallbackImage from '~/assets/blog-placeholder-1.jpg'; +import { DEFAULT_LOCALE, type Locale, SITE } from '~/consts'; +import { getLocaleFromUrl, switchLocalePath } from '~/i18n/ui'; +import { Font } from 'astro:assets'; + +interface Props { + title: string; + description: string; + image?: ImageMetadata; + locale?: Locale; +} + +const canonicalURL = new URL(Astro.url.pathname, Astro.site); +const { + title, + description, + image = FallbackImage, + locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE, +} = Astro.props; + +const otherLocale: Locale = locale === 'de' ? 'en' : 'de'; +const alternateHref = new URL(switchLocalePath(Astro.url.pathname, otherLocale), Astro.site); +const rssHref = new URL(locale === 'de' ? 'rss.xml' : 'en/rss.xml', Astro.site); +--- + + + + + + + + + + + + + + + + + + + + + + + +{title} + + + + + + + + + + + + + + + + + diff --git a/src/components/CategoriesPage.astro b/src/components/CategoriesPage.astro new file mode 100644 index 0000000..31eeb35 --- /dev/null +++ b/src/components/CategoriesPage.astro @@ -0,0 +1,62 @@ +--- +import BaseLayout from '~/layouts/BaseLayout.astro'; +import { type Locale, SITE } from '~/consts'; +import { categoryHref, getCategoriesByLocale, getPostsByCategory } from '~/i18n/posts'; +import { t } from '~/i18n/ui'; + +interface Props { + locale: Locale; +} + +const { locale } = Astro.props; +const categories = await getCategoriesByLocale(locale); +const withCounts = await Promise.all( + categories.map(async (c) => ({ category: c, count: (await getPostsByCategory(c)).length })), +); + +const pageTitle = `${t(locale, 'categories.title')} — ${SITE[locale].title}`; +const pageDescription = t(locale, 'categories.description'); +--- + + +

+ + + diff --git a/src/components/CategoryDetailPage.astro b/src/components/CategoryDetailPage.astro new file mode 100644 index 0000000..bd8ccf9 --- /dev/null +++ b/src/components/CategoryDetailPage.astro @@ -0,0 +1,88 @@ +--- +import { Image } from 'astro:assets'; +import type { CollectionEntry } from 'astro:content'; +import FormattedDate from '~/components/FormattedDate.astro'; +import BaseLayout from '~/layouts/BaseLayout.astro'; +import { type Locale, SITE } from '~/consts'; +import { getPostsByCategory, postSlug } from '~/i18n/posts'; +import { localizePath, t } from '~/i18n/ui'; + +interface Props { + locale: Locale; + category: CollectionEntry<'categories'>; +} + +const { locale, category } = Astro.props; +const posts = await getPostsByCategory(category); +const pageTitle = `${category.data.name} — ${SITE[locale].title}`; +const pageDescription = + category.data.description ?? `${t(locale, 'category.postsIn')} ${category.data.name}`; +--- + + +
+

{category.data.name}

+ {category.data.description &&

{category.data.description}

} +

{t(locale, 'category.postsIn')} {category.data.name}

+ { + posts.length === 0 ? ( +

{t(locale, 'category.noPosts')}

+ ) : ( + + ) + } +
+
+ + diff --git a/src/components/Footer.astro b/src/components/Footer.astro new file mode 100644 index 0000000..ec7a5f0 --- /dev/null +++ b/src/components/Footer.astro @@ -0,0 +1,91 @@ +--- +import { DEFAULT_LOCALE, type Locale } from '~/consts'; +import { getLocaleFromUrl, localizePath, t } from '~/i18n/ui'; + +interface Props { + locale?: Locale; +} + +const locale: Locale = Astro.props.locale ?? getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE; +const contactSegment = locale === 'de' ? 'kontakt' : 'contact'; +const imprintSegment = locale === 'de' ? 'impressum' : 'imprint'; +const privacySegment = locale === 'de' ? 'datenschutz' : 'privacy-policy'; + +const today = new Date(); +--- + + + diff --git a/src/components/FormattedDate.astro b/src/components/FormattedDate.astro new file mode 100644 index 0000000..db993cf --- /dev/null +++ b/src/components/FormattedDate.astro @@ -0,0 +1,27 @@ +--- +import { DEFAULT_LOCALE, type Locale } from '~/consts'; +import { getLocaleFromUrl } from '~/i18n/ui'; + +interface Props { + date: Date; + locale?: Locale; + class?: string; +} + +const { + date, + locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE, + class: className, +} = Astro.props; +const tag = locale === 'de' ? 'de-DE' : 'en-US'; +--- + + diff --git a/src/components/Header.astro b/src/components/Header.astro new file mode 100644 index 0000000..8e28250 --- /dev/null +++ b/src/components/Header.astro @@ -0,0 +1,433 @@ +--- +import type { CollectionEntry } from 'astro:content'; +import { type Locale, SITE } from '~/consts'; +import { + aboutSegment, + categoryIndexSegment, + entryHref, + findTagBySlug, + findTranslation, + tagHref, + tagIndexSegment, + tagSegment, +} from '~/i18n/posts'; +import { getLocaleFromUrl, localizePath, switchLocalePath, t } from '~/i18n/ui'; +import HeaderLink from '~/components/HeaderLink.astro'; + +interface Props { + locale?: Locale; + /** The current page's content entry, if any — used to resolve a translated language-switch link. */ + entry?: CollectionEntry<'posts' | 'categories'>; +} + +const { entry } = Astro.props; +const locale: Locale = Astro.props.locale ?? getLocaleFromUrl(Astro.url); +const otherLocale: Locale = locale === 'de' ? 'en' : 'de'; +const homeHref = localizePath('/', locale); +const aboutHref = localizePath(`/${aboutSegment(locale)}`, locale); +const categoriesHref = localizePath(`/${categoryIndexSegment(locale)}`, locale); +const tagsHref = localizePath(`/${tagIndexSegment(locale)}`, locale); + +const translated = entry ? await findTranslation(entry, otherLocale) : undefined; + +// If we're on a tag detail page, verify the tag exists in the target locale — +// otherwise the switched URL would 404. Fall back to the target tags index. +async function resolveSwitchHref(): Promise { + if (translated) return entryHref(translated); + if (entry) return localizePath('/', otherLocale); + const parts = Astro.url.pathname.split('/').filter(Boolean); + const localePrefix = parts[0] === locale ? 1 : 0; + const first = parts[localePrefix]; + const slug = parts[localePrefix + 1]; + if (first === tagSegment(locale) && slug) { + const target = await findTagBySlug(otherLocale, slug); + return target + ? tagHref(otherLocale, target) + : localizePath(`/${tagIndexSegment(otherLocale)}`, otherLocale); + } + return switchLocalePath(Astro.url.pathname, otherLocale); +} +const switchHref = await resolveSwitchHref(); +--- + +
+ +
+ + + diff --git a/src/components/HeaderLink.astro b/src/components/HeaderLink.astro new file mode 100644 index 0000000..77cf777 --- /dev/null +++ b/src/components/HeaderLink.astro @@ -0,0 +1,42 @@ +--- +import type { HTMLAttributes } from 'astro/types'; +import { LOCALES } from '~/consts'; + +type Props = HTMLAttributes<'a'>; + +const { href, class: className, ...props } = Astro.props; + +function stripTrailing(p: string) { + return p.length > 1 && p.endsWith('/') ? p.slice(0, -1) : p; +} + +function stripBase(p: string) { + const base = import.meta.env.BASE_URL; + if (base && base !== '/' && p.startsWith(base)) return p.slice(base.length - 1) || '/'; + return p; +} + +const pathname = stripTrailing(stripBase(Astro.url.pathname)); +const target = stripTrailing(String(href ?? '')); + +// Locale home URLs (`/`, `/en`) should only activate on exact match; deeper +// routes activate when the pathname equals or is nested under the href. +const localeHomes = new Set(['/', ...LOCALES.map((l) => `/${l}`)]); +const isActive = localeHomes.has(target) + ? pathname === target + : pathname === target || pathname.startsWith(target + '/'); +--- + + + + + diff --git a/src/components/HomePage.astro b/src/components/HomePage.astro new file mode 100644 index 0000000..6cb3e9e --- /dev/null +++ b/src/components/HomePage.astro @@ -0,0 +1,118 @@ +--- +import { Image } from 'astro:assets'; +import FormattedDate from '~/components/FormattedDate.astro'; +import BaseLayout from '~/layouts/BaseLayout.astro'; +import { type Locale, SITE } from '~/consts'; +import { getPostsByLocale, postSlug } from '~/i18n/posts'; +import { localizePath } from '~/i18n/ui'; + +interface Props { + locale: Locale; +} + +const { locale } = Astro.props; +const posts = await getPostsByLocale(locale); +--- + + +
+ +
+
+ + diff --git a/src/components/TagDetailPage.astro b/src/components/TagDetailPage.astro new file mode 100644 index 0000000..810bb0f --- /dev/null +++ b/src/components/TagDetailPage.astro @@ -0,0 +1,84 @@ +--- +import { Image } from 'astro:assets'; +import FormattedDate from '~/components/FormattedDate.astro'; +import BaseLayout from '~/layouts/BaseLayout.astro'; +import { type Locale, SITE } from '~/consts'; +import { type TagEntry, getPostsByTag, postSlug } from '~/i18n/posts'; +import { localizePath, t } from '~/i18n/ui'; + +interface Props { + locale: Locale; + tag: TagEntry; +} + +const { locale, tag } = Astro.props; +const posts = await getPostsByTag(locale, tag.slug); +const pageTitle = `${tag.name} — ${SITE[locale].title}`; +const pageDescription = `${t(locale, 'tag.postsTagged')} ${tag.name}`; +--- + + + + + + diff --git a/src/components/TagsPage.astro b/src/components/TagsPage.astro new file mode 100644 index 0000000..1beceb3 --- /dev/null +++ b/src/components/TagsPage.astro @@ -0,0 +1,57 @@ +--- +import BaseLayout from '~/layouts/BaseLayout.astro'; +import { type Locale, SITE } from '~/consts'; +import { getTagsByLocale, tagHref } from '~/i18n/posts'; +import { t } from '~/i18n/ui'; + +interface Props { + locale: Locale; +} + +const { locale } = Astro.props; +const tags = await getTagsByLocale(locale); +const pageTitle = `${t(locale, 'tags.title')} — ${SITE[locale].title}`; +const pageDescription = t(locale, 'tags.description'); +--- + + +
+

{t(locale, 'tags.title')}

+

{pageDescription}

+ +
+
+ + diff --git a/src/components/Webmentions.astro b/src/components/Webmentions.astro new file mode 100644 index 0000000..5d0f588 --- /dev/null +++ b/src/components/Webmentions.astro @@ -0,0 +1,300 @@ +--- +import { DEFAULT_LOCALE, type Locale } from '~/consts'; +import { getLocaleFromUrl, t } from '~/i18n/ui'; + +declare global { + // eslint-disable-next-line no-var + var __WEBMENTION_TOKEN__: string; +} +const tokenRaw = (globalThis as unknown as { __WEBMENTION_TOKEN__?: string }).__WEBMENTION_TOKEN__; +const WEBMENTION_TOKEN = typeof tokenRaw === 'string' ? tokenRaw : ''; + +interface WMAuthor { + name?: string; + url?: string; + photo?: string; +} +interface WMEntry { + author?: WMAuthor; + url: string; + published?: string; + 'wm-received'?: string; + 'wm-id'?: number; + 'wm-property'?: string; + content?: { text?: string }; +} + +interface Props { + target: string | URL; + locale?: Locale; +} + +const { target, locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE } = Astro.props; + +async function fetchMentions(target: string): Promise { + const token = WEBMENTION_TOKEN; + if (!token) return []; + const withSlash = target.endsWith('/') ? target : `${target}/`; + const withoutSlash = target.replace(/\/+$/, ''); + const fetchOne = async (t: string) => { + const url = new URL('https://webmention.io/api/mentions.jf2'); + url.searchParams.set('target', t); + url.searchParams.set('token', token); + url.searchParams.set('per-page', '100'); + const res = await fetch(url); + if (!res.ok) return [] as WMEntry[]; + const json = (await res.json()) as { children?: WMEntry[] }; + return json.children ?? []; + }; + const [a, b] = await Promise.all([fetchOne(withSlash), fetchOne(withoutSlash)]); + const seen = new Set(); + const merged: WMEntry[] = []; + for (const m of [...a, ...b]) { + const id = m['wm-id']; + if (id == null || seen.has(id)) continue; + seen.add(id); + merged.push(m); + } + return merged; +} + +const targetStr = target.toString(); +const all = await fetchMentions(targetStr); + +const likes = all.filter((m) => m['wm-property'] === 'like-of'); +const reposts = all.filter((m) => m['wm-property'] === 'repost-of'); +const replies = all.filter((m) => m['wm-property'] === 'in-reply-to'); +const mentions = all.filter( + (m) => !['like-of', 'repost-of', 'in-reply-to', 'bookmark-of'].includes(m['wm-property'] ?? ''), +); +const facepile = [...likes, ...reposts]; + +function authorInitial(m: WMEntry) { + return m.author?.name?.trim()?.[0]?.toUpperCase() ?? '?'; +} + +function formatDate(iso?: string) { + if (!iso) return ''; + const d = new Date(iso); + return d.toLocaleDateString(locale === 'de' ? 'de-DE' : 'en-US', { + year: 'numeric', + month: 'short', + day: 'numeric', + }); +} + +const hasAny = facepile.length > 0 || replies.length > 0 || mentions.length > 0; +--- + +{ + hasAny && ( +
+

{t(locale, 'webmentions.title')}

+ + {facepile.length > 0 && ( +
+ {likes.length > 0 && ( +
+

+ {`${likes.length} ${t(locale, likes.length === 1 ? 'webmentions.like' : 'webmentions.likes')}`} +

+ +
+ )} + + {reposts.length > 0 && ( +
+

+ {`${reposts.length} ${t(locale, reposts.length === 1 ? 'webmentions.repost' : 'webmentions.reposts')}`} +

+ +
+ )} +
+ )} + + {replies.length > 0 && ( +
+

{t(locale, 'webmentions.replies')}

+
    + {replies.map((m) => ( +
  1. + + {m.content?.text &&

    {m.content.text}

    } +
  2. + ))} +
+
+ )} + + {mentions.length > 0 && ( +
+

{t(locale, 'webmentions.mentions')}

+ +
+ )} +
+ ) +} + + diff --git a/src/consts.ts b/src/consts.ts new file mode 100644 index 0000000..828f139 --- /dev/null +++ b/src/consts.ts @@ -0,0 +1,14 @@ +export const LOCALES = ['de', 'en'] as const; +export type Locale = (typeof LOCALES)[number]; +export const DEFAULT_LOCALE: Locale = 'de'; + +export const SITE: Record = { + de: { + title: 'Adrian Altner', + description: 'Willkommen auf meiner Website!', + }, + en: { + title: 'Adrian Altner', + description: 'Welcome to my website!', + }, +}; diff --git a/src/content.config.ts b/src/content.config.ts new file mode 100644 index 0000000..b7f64de --- /dev/null +++ b/src/content.config.ts @@ -0,0 +1,42 @@ +import { defineCollection, reference } from 'astro:content'; +import { glob } from 'astro/loaders'; +import { z } from 'astro/zod'; + +// Shared per-locale layout: +// src/content/posts//… — posts +// src/content/categories//… — categories +// Entry `id` is always `/`. A blog post's `category` references a +// category by that id (e.g. "de/technik" or "en/tech"). + +// Optional `translationKey`: entries in different locales that represent the +// same logical piece of content share one key. Used to wire up the language +// switcher so it points at the translated URL instead of 404-ing. + +const posts = defineCollection({ + loader: glob({ base: './src/content/posts', pattern: '{de,en}/**/*.{md,mdx}' }), + schema: ({ image }) => + z.object({ + title: z.string(), + description: z.string(), + pubDate: z.coerce.date(), + updatedDate: z.coerce.date().optional(), + heroImage: z.optional(image()), + category: z.optional(reference('categories')), + // Free-form tags (aka Stichwörter). Plain strings kept inline on each + // post; no separate collection. The tag listing pages aggregate them + // across posts per locale. + tags: z.array(z.string()).optional(), + translationKey: z.string().optional(), + }), +}); + +const categories = defineCollection({ + loader: glob({ base: './src/content/categories', pattern: '{de,en}/**/*.md' }), + schema: z.object({ + name: z.string(), + description: z.string().optional(), + translationKey: z.string().optional(), + }), +}); + +export const collections = { posts, categories }; diff --git a/src/content/categories/de/allgemein.md b/src/content/categories/de/allgemein.md new file mode 100644 index 0000000..18f362c --- /dev/null +++ b/src/content/categories/de/allgemein.md @@ -0,0 +1,5 @@ +--- +name: Allgemein +description: Sammelkategorie für alles andere. +translationKey: general +--- diff --git a/src/content/categories/de/technik.md b/src/content/categories/de/technik.md new file mode 100644 index 0000000..3d45c4f --- /dev/null +++ b/src/content/categories/de/technik.md @@ -0,0 +1,5 @@ +--- +name: Technik +description: Beiträge rund um Technik, Entwicklung und Tools. +translationKey: tech +--- diff --git a/src/content/categories/en/general.md b/src/content/categories/en/general.md new file mode 100644 index 0000000..b74e487 --- /dev/null +++ b/src/content/categories/en/general.md @@ -0,0 +1,5 @@ +--- +name: General +description: Catch-all category. +translationKey: general +--- diff --git a/src/content/categories/en/tech.md b/src/content/categories/en/tech.md new file mode 100644 index 0000000..058a99f --- /dev/null +++ b/src/content/categories/en/tech.md @@ -0,0 +1,5 @@ +--- +name: Tech +description: Posts about technology, development and tools. +translationKey: tech +--- diff --git a/src/content/posts/de/first-post.md b/src/content/posts/de/first-post.md new file mode 100644 index 0000000..80f7b4e --- /dev/null +++ b/src/content/posts/de/first-post.md @@ -0,0 +1,18 @@ +--- +title: 'First post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 08 2022' +heroImage: '../../../assets/blog-placeholder-3.jpg' +category: de/allgemein +translationKey: hello-world +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. + +Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. + +Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. + +Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi. + +Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. diff --git a/src/content/posts/de/markdown-style-guide.md b/src/content/posts/de/markdown-style-guide.md new file mode 100644 index 0000000..c8e002f --- /dev/null +++ b/src/content/posts/de/markdown-style-guide.md @@ -0,0 +1,218 @@ +--- +title: 'Markdown Style Guide' +description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.' +pubDate: 'Jun 19 2024' +heroImage: '../../../assets/blog-placeholder-1.jpg' +category: de/technik +tags: + - markdown + - astro +--- + +Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro. + +## Headings + +The following HTML `

`—`

` elements represent six levels of section headings. `

` is the highest section level while `

` is the lowest. + +# H1 + +## H2 + +### H3 + +#### H4 + +##### H5 + +###### H6 + +## Paragraph + +Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat. + +Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat. + +## Images + +### Syntax + +```markdown +![Alt text](./full/or/relative/path/of/image) +``` + +### Output + +![blog placeholder](../../../assets/blog-placeholder-about.jpg) + +## Blockquotes + +The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a `footer` or `cite` element, and optionally with in-line changes such as annotations and abbreviations. + +### Blockquote without attribution + +#### Syntax + +```markdown +> Tiam, ad mint andaepu dandae nostion secatur sequo quae. +> **Note** that you can use _Markdown syntax_ within a blockquote. +``` + +#### Output + +> Tiam, ad mint andaepu dandae nostion secatur sequo quae. +> **Note** that you can use _Markdown syntax_ within a blockquote. + +### Blockquote with attribution + +#### Syntax + +```markdown +> Don't communicate by sharing memory, share memory by communicating.
+> — Rob Pike[^1] +``` + +#### Output + +> Don't communicate by sharing memory, share memory by communicating.
+> — Rob Pike[^1] + +[^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015. + +## Tables + +### Syntax + +```markdown +| Italics | Bold | Code | +| --------- | -------- | ------ | +| _italics_ | **bold** | `code` | +``` + +### Output + +| Italics | Bold | Code | +| --------- | -------- | ------ | +| _italics_ | **bold** | `code` | + +## Code Blocks + +### Syntax + +we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntax, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash + +````markdown +```html + + + + + Example HTML5 Document + + +

Test

+ + +``` +```` + +### Output + +```html + + + + + Example HTML5 Document + + +

Test

+ + +``` + +## List Types + +### Ordered List + +#### Syntax + +```markdown +1. First item +2. Second item +3. Third item +``` + +#### Output + +1. First item +2. Second item +3. Third item + +### Unordered List + +#### Syntax + +```markdown +- List item +- Another item +- And another item +``` + +#### Output + +- List item +- Another item +- And another item + +### Nested list + +#### Syntax + +```markdown +- Fruit + - Apple + - Orange + - Banana +- Dairy + - Milk + - Cheese +``` + +#### Output + +- Fruit + - Apple + - Orange + - Banana +- Dairy + - Milk + - Cheese + +## Other Elements — abbr, sub, sup, kbd, mark + +### Syntax + +```markdown +GIF is a bitmap image format. + +H2O + +Xn + Yn = Zn + +Press CTRL + ALT + Delete to end the session. + +Most salamanders are nocturnal, and hunt for insects, worms, and other small creatures. +``` + +### Output + +GIF is a bitmap image format. + +H2O + +Xn + Yn = Zn + +Press CTRL + ALT + Delete to end the session. + +Most salamanders are nocturnal, and hunt for insects, worms, and other small creatures. diff --git a/src/content/posts/de/second-post.md b/src/content/posts/de/second-post.md new file mode 100644 index 0000000..637a1e2 --- /dev/null +++ b/src/content/posts/de/second-post.md @@ -0,0 +1,17 @@ +--- +title: 'Second post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 15 2022' +heroImage: '../../../assets/blog-placeholder-4.jpg' +category: de/allgemein +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. + +Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. + +Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. + +Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi. + +Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. diff --git a/src/content/posts/de/setting-up-forgejo-actions-runner.md b/src/content/posts/de/setting-up-forgejo-actions-runner.md new file mode 100644 index 0000000..5767861 --- /dev/null +++ b/src/content/posts/de/setting-up-forgejo-actions-runner.md @@ -0,0 +1,237 @@ +--- +title: 'Forgejo Actions Runner für self-hosted CI/CD einrichten' +description: 'Wie ich manuelle SSH-Deploys durch eine Push-to-Deploy-Pipeline mit einem self-hosted Forgejo Actions Runner auf demselben VPS ersetzt habe.' +pubDate: 'Apr 22 2026' +heroImage: '../../../assets/blog-placeholder-2.jpg' +category: de/technik +tags: + - forgejo + - ci + - self-hosted + - devops + - podman +translationKey: forgejo-actions-runner +--- + +Nachdem ich meine Git-Repos von GitHub auf eine self-hosted Forgejo-Instanz umgezogen hatte, war der nächste logische Schritt, das Deployment von meinem Laptop wegzubekommen. Statt lokal `./scripts/deploy.sh` auszuführen und zu hoffen, dass nichts uncommittet ist, sollte `git push` den Build anstoßen und den Container automatisch ausrollen. + +Dieser Beitrag dokumentiert das komplette Setup: Forgejo Actions Runner auf demselben VPS installieren, an einen Workflow koppeln und Secrets sauber aus dem Repo halten. + +## Das Setup + +- **VPS**: eine Debian-Maschine, die sowohl Forgejo (rootless Podman-Container) als auch die Astro-Website (`/opt/websites/adrian-altner.de`, verwaltet über einen `podman-compose@` systemd-Service) hostet. +- **Forgejo**: v11 LTS, rootless, läuft unter einem eigenen `git` System-User. +- **Ziel**: bei jedem Push auf `main` das Production-Image neu bauen und den Service neu starten — alles auf derselben Maschine. + +## Warum ein eigener Runner-User + +Der Runner führt beliebigen Code aus Workflow-Dateien aus. Ihn als `git`-User laufen zu lassen (der Zugriff auf Forgejos Datenbank und jedes Repo hat) wäre keine gute Idee. Ich habe einen separaten System-User mit abgeschottetem Home-Verzeichnis angelegt: + +```bash +sudo useradd --system --create-home \ + --home-dir /var/lib/forgejo-runner \ + --shell /bin/bash forgejo-runner +``` + +Dieser User bekommt standardmäßig kein sudo — wir erteilen gezielt nur die Rechte, die der Deploy tatsächlich braucht. + +## Runner-Binary installieren + +Der Runner wird als einzelnes statisches Binary aus Forgejos eigener Registry verteilt. Ich hole mir das neueste Release programmatisch: + +```bash +LATEST=$(curl -s https://code.forgejo.org/api/v1/repos/forgejo/runner/releases \ + | grep -oE '"tag_name":"[^"]+"' | head -1 | cut -d'"' -f4) +VER="${LATEST#v}" + +cd /tmp +curl -L -o forgejo-runner \ + "https://code.forgejo.org/forgejo/runner/releases/download/${LATEST}/forgejo-runner-${VER}-linux-amd64" +chmod +x forgejo-runner +sudo mv forgejo-runner /usr/local/bin/ +``` + +Ein kurzes `forgejo-runner --version` bestätigt v12.9.0 — die aktuelle Major-Version, kompatibel mit Forgejo v10, v11 und allem darüber. + +## Actions in Forgejo aktivieren + +Actions sind bei einer Forgejo-Instanz standardmäßig aus. Die minimale Konfiguration kommt in die `app.ini` (bei mir im rootless-Container-Volume unter `/home/git/forgejo-data/custom/conf/app.ini`): + +```ini +[actions] +ENABLED = true +DEFAULT_ACTIONS_URL = https://code.forgejo.org +``` + +`DEFAULT_ACTIONS_URL` ist wichtig, weil der GitHub Actions Marketplace nicht direkt erreichbar ist — Forgejo pflegt eigene Mirrors der gängigen Actions wie `actions/checkout` unter `code.forgejo.org/actions/*`. Nach einem Container-Restart taucht das Verzeichnis `actions_artifacts` in den Logs auf. + +## Runner registrieren + +Runner können auf ein einzelnes Repo, einen User-Account oder die gesamte Instanz registriert werden. Ich habe mit einer Repo-Registrierung für meine Website angefangen und dann auf User-Scope umgestellt, damit derselbe Runner alle meine Repos bedienen kann, ohne sich neu registrieren zu müssen. + +Der Registrierungstoken kommt aus `Benutzer-Einstellungen → Actions → Runner → Neuen Runner erstellen`: + +```bash +sudo -iu forgejo-runner /usr/local/bin/forgejo-runner register \ + --no-interactive \ + --instance https://git.altner.cloud \ + --token \ + --name arcturus-runner \ + --labels "self-hosted:host" +``` + +Das Label `self-hosted:host` bedeutet: "Jobs mit Label `self-hosted` laufen direkt auf dem Host". Kein Container-Runtime für den Runner selbst nötig — Podman haben wir ja schon für die Anwendung. + +Umstellung eines bestehenden Runners von Repo- auf User-Scope: Service stoppen, alten Runner-Eintrag in der Forgejo-UI löschen, `/var/lib/forgejo-runner/.runner` lokal entfernen, neuen User-Level-Token holen, neu registrieren, Service starten. Gleiches Binary, anderer Scope. + +## Docker-Abhängigkeit abschalten + +Beim ersten Start hat sich der Runner geweigert zu laufen: + +``` +Error: daemon Docker Engine socket not found and docker_host config was invalid +``` + +Auch wenn man nur das Host-Label nutzt, prüft der Runner beim Start auf einen Docker-Socket. Da der Server nur rootless Podman hat, habe ich eine Config-Datei erzeugt und den Docker-Check explizit deaktiviert: + +```bash +sudo -iu forgejo-runner /usr/local/bin/forgejo-runner generate-config \ + > /tmp/runner-config.yaml +sudo mv /tmp/runner-config.yaml /var/lib/forgejo-runner/config.yaml +sudo chown forgejo-runner:forgejo-runner /var/lib/forgejo-runner/config.yaml + +sudo -iu forgejo-runner sed -i \ + -e 's|docker_host: .*|docker_host: "-"|' \ + -e 's| labels: \[\]| labels: ["self-hosted:host"]|' \ + /var/lib/forgejo-runner/config.yaml +``` + +## Systemd-Service + +```ini +[Unit] +Description=Forgejo Actions Runner +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=forgejo-runner +Group=forgejo-runner +WorkingDirectory=/var/lib/forgejo-runner +ExecStart=/usr/local/bin/forgejo-runner --config /var/lib/forgejo-runner/config.yaml daemon +Restart=on-failure +RestartSec=5s +NoNewPrivileges=false +ProtectSystem=full +ProtectHome=read-only +ReadWritePaths=/var/lib/forgejo-runner + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now forgejo-runner +``` + +## Nur die nötigen sudo-Rechte + +Der Deploy-Step muss ein Podman-Image bauen und den systemd-Service neu starten, der es ausführt. Beides braucht Root. Statt dem Runner-User breites sudo zu geben, habe ich eine eng gefasste Allowlist unter `/etc/sudoers.d/forgejo-runner-deploy` angelegt: + +``` +forgejo-runner ALL=(root) NOPASSWD: /usr/bin/podman build *, \ + /usr/bin/podman container prune *, \ + /usr/bin/podman image prune *, \ + /usr/bin/podman builder prune *, \ + /usr/bin/systemctl restart podman-compose@adrian-altner.de.service, \ + /usr/bin/rsync * +``` + +`visudo -cf` prüft die Syntax, bevor man sich versehentlich komplett aus sudo aussperrt. + +## Der Workflow + +Workflows liegen unter `.forgejo/workflows/*.yml`. Der Deploy-Flow macht dasselbe wie mein altes Shell-Skript, nur ohne SSH: + +```yaml +name: Deploy + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: self-hosted + env: + DEPLOY_DIR: /opt/websites/adrian-altner.de + steps: + - uses: actions/checkout@v4 + + - name: Sync to deploy directory + run: | + sudo rsync -a --delete \ + --exclude='.env' \ + --exclude='.env.production' \ + --exclude='.git/' \ + --exclude='node_modules/' \ + ./ "${DEPLOY_DIR}/" + + - name: Build image + run: | + cd "${DEPLOY_DIR}" + sudo podman build \ + --build-arg WEBMENTION_TOKEN="${{ secrets.WEBMENTION_TOKEN }}" \ + -t localhost/adrian-altner.de:latest . + + - name: Restart service + run: sudo systemctl restart podman-compose@adrian-altner.de.service + + - name: Prune + run: | + sudo podman container prune -f 2>/dev/null || true + sudo podman image prune --external -f 2>/dev/null || true + sudo podman image prune -f 2>/dev/null || true + sudo podman builder prune -af 2>/dev/null || true +``` + +## Secrets bleiben in Forgejo + +Alles Sensible — in meinem Fall API-Tokens für webmention.io und webmention.app — liegt in `Settings → Actions → Secrets` und wird als `${{ secrets.NAME }}` in den Job injiziert. Forgejo speichert sie verschlüsselt, und Workflow-Logs maskieren die Werte automatisch. Die Tokens werden an genau zwei Stellen referenziert: in der CI-Workflow-Datei (committet) und im verschlüsselten Forgejo-Store (nie im Repo). + +Der Build-Time-Token wird als `ARG` in den Container gereicht, nur während des Build-Stages benutzt und ist im finalen Runtime-Image nicht enthalten — ein schnelles `podman run --rm env | grep -i webmention` bestätigt das. + +## Der eine Stolperstein: Node auf dem Host + +Der erste echte Workflow-Lauf ist sofort gestorben mit: + +``` +Cannot find: node in PATH +``` + +`actions/checkout@v4` ist eine JavaScript-basierte Action. Bei einem Runner mit Host-Label läuft sie direkt auf dem VPS und braucht einen Node-Interpreter im `PATH`. Ein `apt install` später war der Runner zufrieden: + +```bash +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs +sudo systemctl restart forgejo-runner +``` + +## Ergebnis + +Von einem kalten `git push origin main` bis zur komplett durchgelaufenen Pipeline — Checkout, rsync, Podman-Build, systemd-Restart, Prune, Webmention-Pings — vergehen etwa 1 Minute 15 Sekunden. Keine SSH-Keys zu rotieren, kein Laptop involviert, kein Mysterium über den Stand der Live-Version. + +Der Runner selbst belegt im Idle rund 5 MB RAM und pollt Forgejo alle zwei Sekunden auf neue Jobs. Der Ressourcen-Overhead ist vernachlässigbar verglichen mit dem Komfort von Push-to-Deploy auf Infrastruktur, die mir komplett gehört. + +## Runner für neue Projekte wiederverwenden + +Weil der Runner auf User-Scope registriert ist, reduziert sich das Anhängen von CI an ein neues Repo auf drei Schritte: + +1. Eine `.forgejo/workflows/deploy.yml` mit `runs-on: self-hosted` ins Repo packen. +2. Projekt-spezifische Secrets unter den Actions-Settings des Repos anlegen. +3. Falls das Projekt einen eigenen systemd-Service hat, `/etc/sudoers.d/forgejo-runner-deploy` um eine Zeile `systemctl restart ` erweitern. Sonst muss auf dem Server nichts geändert werden. + +Die einmaligen Infrastrukturkosten — User-Account, Binary, Config, systemd-Unit, Node-Runtime, sudoers — amortisieren sich über jedes weitere Projekt. diff --git a/src/content/posts/de/third-post.md b/src/content/posts/de/third-post.md new file mode 100644 index 0000000..2f24af7 --- /dev/null +++ b/src/content/posts/de/third-post.md @@ -0,0 +1,17 @@ +--- +title: 'Third post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 22 2022' +heroImage: '../../../assets/blog-placeholder-2.jpg' +category: de/allgemein +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. + +Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. + +Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. + +Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi. + +Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. diff --git a/src/content/posts/de/using-mdx.mdx b/src/content/posts/de/using-mdx.mdx new file mode 100644 index 0000000..f615ef2 --- /dev/null +++ b/src/content/posts/de/using-mdx.mdx @@ -0,0 +1,35 @@ +--- +title: 'Using MDX' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jun 01 2024' +heroImage: '../../../assets/blog-placeholder-5.jpg' +category: de/technik +tags: + - markdown + - astro +--- + +This theme comes with the [@astrojs/mdx](https://docs.astro.build/en/guides/integrations-guide/mdx/) integration installed and configured in your `astro.config.mjs` config file. If you prefer not to use MDX, you can disable support by removing the integration from your config file. + +## Why MDX? + +MDX is a special flavor of Markdown that supports embedded JavaScript & JSX syntax. This unlocks the ability to [mix JavaScript and UI Components into your Markdown content](https://docs.astro.build/en/guides/integrations-guide/mdx/#mdx-in-astro) for things like interactive charts or alerts. + +If you have existing content authored in MDX, this integration will hopefully make migrating to Astro a breeze. + +## Example + +Here is how you import and use a UI component inside of MDX. +When you open this page in the browser, you should see the clickable button below. + +import HeaderLink from '~/components/HeaderLink.astro'; + + + Embedded component in MDX + + +## More Links + +- [MDX Syntax Documentation](https://mdxjs.com/docs/what-is-mdx) +- [Astro Usage Documentation](https://docs.astro.build/en/basics/astro-pages/#markdownmdx-pages) +- **Note:** [Client Directives](https://docs.astro.build/en/reference/directives-reference/#client-directives) are still required to create interactive components. Otherwise, all components in your MDX will render as static HTML (no JavaScript) by default. diff --git a/src/content/posts/en/hello-world.md b/src/content/posts/en/hello-world.md new file mode 100644 index 0000000..6f19250 --- /dev/null +++ b/src/content/posts/en/hello-world.md @@ -0,0 +1,12 @@ +--- +title: 'Hello World' +description: 'First English post.' +pubDate: 'Apr 20 2026' +heroImage: '../../../assets/blog-placeholder-1.jpg' +category: en/general +tags: + - markdown +translationKey: hello-world +--- + +This is the first English post. diff --git a/src/content/posts/en/setting-up-forgejo-actions-runner.md b/src/content/posts/en/setting-up-forgejo-actions-runner.md new file mode 100644 index 0000000..a9edc7d --- /dev/null +++ b/src/content/posts/en/setting-up-forgejo-actions-runner.md @@ -0,0 +1,237 @@ +--- +title: 'Setting up a Forgejo Actions runner for self-hosted CI/CD' +description: 'How I replaced manual SSH deploys with a push-to-deploy pipeline using a self-hosted Forgejo Actions runner on the same VPS.' +pubDate: 'Apr 22 2026' +heroImage: '../../../assets/blog-placeholder-2.jpg' +category: en/tech +tags: + - forgejo + - ci + - self-hosted + - devops + - podman +translationKey: forgejo-actions-runner +--- + +After moving my Git repositories from GitHub to a self-hosted Forgejo instance, the next logical step was to move deployment off my laptop. Instead of running `./scripts/deploy.sh` locally and hoping nothing was uncommitted, I wanted `git push` to trigger the build and roll out the container automatically. + +This post documents the full setup: installing a Forgejo Actions runner on the same VPS that runs Forgejo, wiring it to a workflow, and keeping secrets out of the repo. + +## The setup + +- **VPS**: single Debian machine hosting both Forgejo (rootless Podman container) and the Astro website (`/opt/websites/adrian-altner.de`, managed by a `podman-compose@` systemd service). +- **Forgejo**: v11 LTS, rootless, running under a dedicated `git` system user. +- **Goal**: on every push to `main`, rebuild the production image and restart the service — all on the same box. + +## Why a dedicated runner user + +The runner executes arbitrary code defined in workflow files. Running it as the `git` user (which has access to Forgejo's database and every repo) would be a bad idea. I created a separate system user with a locked-down home directory: + +```bash +sudo useradd --system --create-home \ + --home-dir /var/lib/forgejo-runner \ + --shell /bin/bash forgejo-runner +``` + +That user gets no sudo by default — we'll grant targeted privileges later only for the specific commands the deploy needs. + +## Installing the runner binary + +The runner is distributed as a single static binary from Forgejo's own registry. I grabbed the latest release programmatically: + +```bash +LATEST=$(curl -s https://code.forgejo.org/api/v1/repos/forgejo/runner/releases \ + | grep -oE '"tag_name":"[^"]+"' | head -1 | cut -d'"' -f4) +VER="${LATEST#v}" + +cd /tmp +curl -L -o forgejo-runner \ + "https://code.forgejo.org/forgejo/runner/releases/download/${LATEST}/forgejo-runner-${VER}-linux-amd64" +chmod +x forgejo-runner +sudo mv forgejo-runner /usr/local/bin/ +``` + +A quick `forgejo-runner --version` confirmed v12.9.0 was in place — which is the current major, compatible with Forgejo v10, v11, and beyond. + +## Enabling Actions in Forgejo + +Actions are off by default on Forgejo instances. I added the minimal configuration to `app.ini` (found inside the rootless container's volume at `/home/git/forgejo-data/custom/conf/app.ini`): + +```ini +[actions] +ENABLED = true +DEFAULT_ACTIONS_URL = https://code.forgejo.org +``` + +`DEFAULT_ACTIONS_URL` matters because GitHub's Actions marketplace isn't reachable as-is — Forgejo maintains its own mirrors of common actions like `actions/checkout` at `code.forgejo.org/actions/*`. A container restart and the `actions_artifacts` storage directory appeared in the logs. + +## Registering the runner + +Runners can be scoped to a single repo, to a user account, or to the whole instance. I started with a repo-scoped registration for my website, then moved it to user-scope so the same runner can serve every repo I own without re-registration. + +The registration token came from `User Settings → Actions → Runners → Create new Runner`: + +```bash +sudo -iu forgejo-runner /usr/local/bin/forgejo-runner register \ + --no-interactive \ + --instance https://git.altner.cloud \ + --token \ + --name arcturus-runner \ + --labels "self-hosted:host" +``` + +The label `self-hosted:host` means "jobs labelled `self-hosted` run directly on the host". No container runtime required for the runner itself — we already have Podman for the application. + +To switch an existing runner from repo to user scope: stop the service, delete the old runner entry in the Forgejo UI, remove `/var/lib/forgejo-runner/.runner` locally, grab a new user-level token, re-register, start the service. Same binary, different scope. + +## Making it not-need-Docker + +On first boot, the runner refused to start with: + +``` +Error: daemon Docker Engine socket not found and docker_host config was invalid +``` + +Even when using only the host label, the runner checks for a Docker socket on startup. Since the server only has rootless Podman, I generated a config file and explicitly disabled the Docker check: + +```bash +sudo -iu forgejo-runner /usr/local/bin/forgejo-runner generate-config \ + > /tmp/runner-config.yaml +sudo mv /tmp/runner-config.yaml /var/lib/forgejo-runner/config.yaml +sudo chown forgejo-runner:forgejo-runner /var/lib/forgejo-runner/config.yaml + +sudo -iu forgejo-runner sed -i \ + -e 's|docker_host: .*|docker_host: "-"|' \ + -e 's| labels: \[\]| labels: ["self-hosted:host"]|' \ + /var/lib/forgejo-runner/config.yaml +``` + +## Systemd service + +```ini +[Unit] +Description=Forgejo Actions Runner +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=forgejo-runner +Group=forgejo-runner +WorkingDirectory=/var/lib/forgejo-runner +ExecStart=/usr/local/bin/forgejo-runner --config /var/lib/forgejo-runner/config.yaml daemon +Restart=on-failure +RestartSec=5s +NoNewPrivileges=false +ProtectSystem=full +ProtectHome=read-only +ReadWritePaths=/var/lib/forgejo-runner + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now forgejo-runner +``` + +## Granting just enough sudo + +The deploy step needs to build a Podman image and restart the systemd service that runs it. Both require root. Instead of giving the runner user broad sudo, I created a narrow allowlist in `/etc/sudoers.d/forgejo-runner-deploy`: + +``` +forgejo-runner ALL=(root) NOPASSWD: /usr/bin/podman build *, \ + /usr/bin/podman container prune *, \ + /usr/bin/podman image prune *, \ + /usr/bin/podman builder prune *, \ + /usr/bin/systemctl restart podman-compose@adrian-altner.de.service, \ + /usr/bin/rsync * +``` + +`visudo -cf` parses it to catch syntax errors before you accidentally lock yourself out of sudo entirely. + +## The workflow + +Workflows live under `.forgejo/workflows/*.yml`. The deploy flow mirrors what my old shell script did, minus the SSH: + +```yaml +name: Deploy + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: self-hosted + env: + DEPLOY_DIR: /opt/websites/adrian-altner.de + steps: + - uses: actions/checkout@v4 + + - name: Sync to deploy directory + run: | + sudo rsync -a --delete \ + --exclude='.env' \ + --exclude='.env.production' \ + --exclude='.git/' \ + --exclude='node_modules/' \ + ./ "${DEPLOY_DIR}/" + + - name: Build image + run: | + cd "${DEPLOY_DIR}" + sudo podman build \ + --build-arg WEBMENTION_TOKEN="${{ secrets.WEBMENTION_TOKEN }}" \ + -t localhost/adrian-altner.de:latest . + + - name: Restart service + run: sudo systemctl restart podman-compose@adrian-altner.de.service + + - name: Prune + run: | + sudo podman container prune -f 2>/dev/null || true + sudo podman image prune --external -f 2>/dev/null || true + sudo podman image prune -f 2>/dev/null || true + sudo podman builder prune -af 2>/dev/null || true +``` + +## Secrets stay in Forgejo + +Anything sensitive — API tokens for webmention.io and webmention.app in my case — lives in `Settings → Actions → Secrets` and is injected into the job as `${{ secrets.NAME }}`. Forgejo stores them encrypted, and the workflow logs automatically mask the values. The tokens are referenced from exactly two places: the CI workflow file (committed) and Forgejo's encrypted store (never in the repo). + +The build-time token is passed into the container as an `ARG`, used only during the build stage, and not present in the final runtime image — a quick `podman run --rm env | grep -i webmention` confirms it's gone. + +## The one gotcha: Node on the host + +The first real workflow run failed immediately with: + +``` +Cannot find: node in PATH +``` + +`actions/checkout@v4` is a JavaScript-based action. On a runner using the host label, it runs directly on the VPS and needs a Node interpreter available in `PATH`. One apt install later and the runner was happy: + +```bash +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs +sudo systemctl restart forgejo-runner +``` + +## Result + +From a cold `git push origin main`, the whole pipeline — checkout, rsync, Podman build, systemd restart, prune, Webmention pings — completes in about 1 minute 15 seconds. No SSH keys to rotate, no laptop involved, no mystery about which version of the code is live. + +The runner itself uses about 5 MB of RAM while idle, polling Forgejo every two seconds for new jobs. Resource overhead is negligible compared to the convenience of push-to-deploy on infrastructure I fully control. + +## Reusing the runner for new projects + +Because the runner is registered at user scope, adding CI to a new repository boils down to three steps: + +1. Drop a `.forgejo/workflows/deploy.yml` into the repo with `runs-on: self-hosted`. +2. Add any project-specific secrets under the repo's Actions settings. +3. If the project has its own systemd service, extend `/etc/sudoers.d/forgejo-runner-deploy` with a line allowing `systemctl restart `. Nothing else on the server needs to change. + +The one-time infrastructure cost — user account, binary, config, systemd unit, Node runtime, sudoers — gets amortised across every project from here on. diff --git a/src/i18n/posts.ts b/src/i18n/posts.ts new file mode 100644 index 0000000..2a5bc0b --- /dev/null +++ b/src/i18n/posts.ts @@ -0,0 +1,152 @@ +import { type CollectionEntry, getCollection, getEntry } from 'astro:content'; +import { type Locale } from '~/consts'; +import { isLocale, localizePath } from '~/i18n/ui'; + +export function entryLocale(entry: { id: string }): Locale { + const first = entry.id.split('/')[0]; + if (!isLocale(first)) { + throw new Error(`Content entry "${entry.id}" is not under a locale folder (de/ or en/).`); + } + return first; +} + +export function entrySlug(entry: { id: string }): string { + return entry.id.split('/').slice(1).join('/'); +} + +// Back-compat aliases used across the codebase. +export const postLocale = entryLocale; +export const postSlug = entrySlug; + +export async function getPostsByLocale(locale: Locale) { + const posts = await getCollection('posts', (p) => entryLocale(p) === locale); + return posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()); +} + +export async function getCategoriesByLocale(locale: Locale) { + const categories = await getCollection('categories', (c) => entryLocale(c) === locale); + return categories.sort((a, b) => a.data.name.localeCompare(b.data.name)); +} + +export async function getPostsByCategory(category: CollectionEntry<'categories'>) { + const locale = entryLocale(category); + const posts = await getCollection( + 'posts', + (p) => entryLocale(p) === locale && p.data.category?.id === category.id, + ); + return posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()); +} + +/** Convert a tag name into a URL-safe slug. */ +export function tagSlug(tag: string): string { + return tag + .toLowerCase() + .trim() + .normalize('NFKD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/ß/g, 'ss') + .replace(/ä/g, 'ae') + .replace(/ö/g, 'oe') + .replace(/ü/g, 'ue') + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); +} + +/** Aggregated tag info across posts in one locale. */ +export interface TagEntry { + name: string; + slug: string; + count: number; +} + +export async function getTagsByLocale(locale: Locale): Promise { + const posts = await getPostsByLocale(locale); + const byName = new Map(); + for (const post of posts) { + for (const raw of post.data.tags ?? []) { + const name = raw.trim(); + if (!name) continue; + const existing = byName.get(name); + if (existing) existing.count++; + else byName.set(name, { name, slug: tagSlug(name), count: 1 }); + } + } + return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name)); +} + +/** Resolve a tag slug for a locale back to its canonical TagEntry. */ +export async function findTagBySlug(locale: Locale, slug: string): Promise { + const tags = await getTagsByLocale(locale); + return tags.find((t) => t.slug === slug); +} + +export async function getPostsByTag(locale: Locale, slug: string) { + const posts = await getPostsByLocale(locale); + return posts.filter((p) => (p.data.tags ?? []).some((name) => tagSlug(name) === slug)); +} + +export async function resolveCategory(post: CollectionEntry<'posts'>) { + if (!post.data.category) return undefined; + return await getEntry(post.data.category); +} + +/** URL segment used for category detail pages per locale. */ +export function categorySegment(locale: Locale): string { + return locale === 'de' ? 'kategorie' : 'category'; +} + +/** URL segment used for the category listing page per locale. */ +export function categoryIndexSegment(locale: Locale): string { + return locale === 'de' ? 'kategorien' : 'categories'; +} + +/** URL segment used for the about page per locale. */ +export function aboutSegment(locale: Locale): string { + return locale === 'de' ? 'ueber-mich' : 'about'; +} + +/** URL segment used for tag detail pages per locale. */ +export function tagSegment(locale: Locale): string { + return locale === 'de' ? 'schlagwort' : 'tag'; +} + +/** URL segment used for the tag listing page per locale. */ +export function tagIndexSegment(locale: Locale): string { + return locale === 'de' ? 'schlagwoerter' : 'tags'; +} + +export function categoryHref(category: CollectionEntry<'categories'>): string { + const locale = entryLocale(category); + return localizePath(`/${categorySegment(locale)}/${entrySlug(category)}/`, locale); +} + +export function postHref(post: CollectionEntry<'posts'>): string { + const locale = entryLocale(post); + return localizePath(`/${entrySlug(post)}/`, locale); +} + +export function tagHref(locale: Locale, tag: string | TagEntry): string { + const slug = typeof tag === 'string' ? tagSlug(tag) : tag.slug; + return localizePath(`/${tagSegment(locale)}/${slug}/`, locale); +} + +/** Canonical URL for any translatable entry. */ +export function entryHref(entry: CollectionEntry<'posts' | 'categories'>): string { + return entry.collection === 'categories' ? categoryHref(entry) : postHref(entry); +} + +/** + * Find the translation of an entry in the target locale, matched via the + * shared `translationKey` frontmatter field. Returns `undefined` when no + * matching translation exists. + */ +export async function findTranslation( + entry: CollectionEntry<'posts' | 'categories'>, + target: Locale, +): Promise | undefined> { + const key = entry.data.translationKey; + if (!key) return undefined; + const collection = entry.collection; + const all = await getCollection(collection, (e) => entryLocale(e) === target); + return all.find((e) => e.data.translationKey === key); +} diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts new file mode 100644 index 0000000..038b321 --- /dev/null +++ b/src/i18n/ui.ts @@ -0,0 +1,134 @@ +import { DEFAULT_LOCALE, type Locale, LOCALES } from '~/consts'; + +export const ui = { + de: { + 'nav.home': 'Start', + 'nav.about': 'Über mich', + 'nav.categories': 'Kategorien', + 'nav.tags': 'Schlagwörter', + 'post.lastUpdated': 'Zuletzt aktualisiert am', + 'post.category': 'Kategorie', + 'post.tags': 'Schlagwörter', + 'post.translationAvailable': 'Dieser Beitrag ist auch auf Englisch verfügbar:', + 'post.translationLink': 'Englische Version lesen', + 'categories.title': 'Kategorien', + 'categories.description': 'Alle Kategorien im Überblick.', + 'category.postsIn': 'Beiträge in', + 'category.noPosts': 'Noch keine Beiträge in dieser Kategorie.', + 'tags.title': 'Schlagwörter', + 'tags.description': 'Alle Schlagwörter im Überblick.', + 'tag.postsTagged': 'Beiträge mit', + 'tag.noPosts': 'Noch keine Beiträge mit diesem Stichwort.', + 'footer.contact': 'Kontakt', + 'footer.imprint': 'Impressum', + 'footer.privacy': 'Datenschutz', + 'webmentions.title': 'Reaktionen', + 'webmentions.like': 'Like', + 'webmentions.likes': 'Likes', + 'webmentions.repost': 'Repost', + 'webmentions.reposts': 'Reposts', + 'webmentions.replies': 'Antworten', + 'webmentions.mentions': 'Erwähnungen', + 'lang.de': 'Deutsch', + 'lang.en': 'English', + }, + en: { + 'nav.home': 'Home', + 'nav.about': 'About', + 'nav.categories': 'Categories', + 'nav.tags': 'Tags', + 'post.lastUpdated': 'Last updated on', + 'post.category': 'Category', + 'post.tags': 'Tags', + 'post.translationAvailable': 'This post is also available in German:', + 'post.translationLink': 'Read the German version', + 'categories.title': 'Categories', + 'categories.description': 'All categories at a glance.', + 'category.postsIn': 'Posts in', + 'category.noPosts': 'No posts in this category yet.', + 'tags.title': 'Tags', + 'tags.description': 'All tags at a glance.', + 'tag.postsTagged': 'Posts tagged', + 'tag.noPosts': 'No posts with this tag yet.', + 'footer.contact': 'Contact', + 'footer.imprint': 'Imprint', + 'footer.privacy': 'Privacy', + 'webmentions.title': 'Reactions', + 'webmentions.like': 'Like', + 'webmentions.likes': 'Likes', + 'webmentions.repost': 'Repost', + 'webmentions.reposts': 'Reposts', + 'webmentions.replies': 'Replies', + 'webmentions.mentions': 'Mentions', + 'lang.de': 'Deutsch', + 'lang.en': 'English', + }, +} as const satisfies Record>; + +export type UIKey = keyof (typeof ui)['de']; + +export function t(locale: Locale, key: UIKey): string { + return ui[locale][key]; +} + +export function isLocale(value: string | undefined): value is Locale { + return !!value && (LOCALES as readonly string[]).includes(value); +} + +export function getLocaleFromUrl(url: URL): Locale { + const seg = url.pathname.split('/').filter(Boolean)[0]; + return isLocale(seg) ? seg : DEFAULT_LOCALE; +} + +/** + * Build a URL for a route within a given locale. `path` is the route without + * any language prefix, e.g. "/" or "/about". + */ +export function localizePath(path: string, locale: Locale): string { + const normalized = path.startsWith('/') ? path : `/${path}`; + if (locale === DEFAULT_LOCALE) return normalized; + if (normalized === '/') return `/${locale}/`; + return `/${locale}${normalized}`; +} + +/** + * Segments whose URL slug differs per locale. The first segment of any + * non-prefixed pathname is translated through this map when switching. + */ +const LOCALIZED_SEGMENTS: Record> = { + de: { + category: 'kategorie', + categories: 'kategorien', + about: 'ueber-mich', + tag: 'schlagwort', + tags: 'schlagwoerter', + contact: 'kontakt', + imprint: 'impressum', + 'privacy-policy': 'datenschutz', + }, + en: { + kategorie: 'category', + kategorien: 'categories', + 'ueber-mich': 'about', + schlagwort: 'tag', + schlagwoerter: 'tags', + kontakt: 'contact', + impressum: 'imprint', + datenschutz: 'privacy-policy', + }, +}; + +/** + * Swap the locale of the current pathname, preserving the rest of the route + * and translating known per-locale URL segments (e.g. `kategorie` ↔ `category`). + */ +export function switchLocalePath(pathname: string, target: Locale): string { + const parts = pathname.split('/').filter(Boolean); + if (parts.length > 0 && isLocale(parts[0])) parts.shift(); + if (parts.length > 0) { + const translated = LOCALIZED_SEGMENTS[target][parts[0]]; + if (translated) parts[0] = translated; + } + const rest = parts.length ? `/${parts.join('/')}` : '/'; + return localizePath(rest === '/' ? '/' : rest, target); +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro new file mode 100644 index 0000000..ce7227c --- /dev/null +++ b/src/layouts/BaseLayout.astro @@ -0,0 +1,57 @@ +--- +import type { ImageMetadata } from 'astro'; +import type { CollectionEntry } from 'astro:content'; +import BaseHead from '~/components/BaseHead.astro'; +import Footer from '~/components/Footer.astro'; +import Header from '~/components/Header.astro'; +import { DEFAULT_LOCALE, type Locale } from '~/consts'; +import { getLocaleFromUrl } from '~/i18n/ui'; + +interface Props { + title: string; + description: string; + locale?: Locale; + image?: ImageMetadata; + /** Current content entry, used for the language switcher's translation lookup. */ + entry?: CollectionEntry<'posts' | 'categories'>; + /** Optional extra class on `` for per-page styling hooks. */ + bodyClass?: string; +} + +const { + title, + description, + image, + entry, + bodyClass, + locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE, +} = Astro.props; +--- + + + + + + + + + +
+
+ +
+