From c70fc72952deb3bc8b0bb0e41b1ad23476786da5 Mon Sep 17 00:00:00 2001 From: Cory Dransfeldt Date: Sat, 16 Nov 2024 16:43:07 -0800 Subject: [PATCH] initial commit --- .env | 6 + .gitignore | 27 + LICENSE | 21 + README.md | 9 + _headers | 67 + _redirects | 72 + astro.config.mjs | 22 + package-lock.json | 6984 +++++++++++++++++ package.json | 28 + public/fonts/ml.woff2 | Bin 0 -> 4388 bytes public/fonts/mlb.woff2 | Bin 0 -> 4396 bytes public/fonts/mlbi.woff2 | Bin 0 -> 4644 bytes public/fonts/mli.woff2 | Bin 0 -> 4580 bytes public/scripts/index.js | 288 + queries/functions/search.psql | 43 + queries/views/content/links.psql | 26 + queries/views/content/posts.psql | 126 + queries/views/feeds/all-content.psql | 79 + queries/views/feeds/search.psql | 109 + queries/views/feeds/sitemap.psql | 65 + queries/views/feeds/syndication.psql | 86 + queries/views/globals/index.psql | 22 + queries/views/globals/nav.psql | 14 + queries/views/globals/pages.psql | 56 + queries/views/media/books.psql | 95 + queries/views/media/movies.psql | 106 + queries/views/media/music/album-releases.psql | 17 + queries/views/media/music/artists.psql | 94 + queries/views/media/music/concerts.psql | 19 + queries/views/media/music/genres.psql | 49 + queries/views/media/music/listens.psql | 28 + queries/views/media/music/month/albums.psql | 20 + queries/views/media/music/month/artists.psql | 19 + queries/views/media/music/month/genres.psql | 16 + queries/views/media/music/month/tracks.psql | 37 + queries/views/media/music/now-playing.psql | 25 + queries/views/media/music/recent-tracks.psql | 23 + queries/views/media/music/week/albums.psql | 20 + queries/views/media/music/week/artists.psql | 19 + queries/views/media/music/week/genres.psql | 16 + queries/views/media/music/week/tracks.psql | 37 + queries/views/media/shows.psql | 94 + scripts/worker-build.mjs | 33 + src/components/BlockRenderer.astro | 35 + src/components/Footer.astro | 34 + src/components/Header.astro | 17 + src/components/IconMapper.astro | 43 + src/components/Intro.astro | 10 + src/components/RecentActivity.astro | 43 + src/components/RecentPosts.astro | 33 + src/components/blocks/AssociatedMedia.astro | 110 + src/components/blocks/Hero.astro | 7 + src/components/blocks/MastodonPost.astro | 7 + src/components/blocks/Modal.astro | 8 + src/components/blocks/NowPlaying.astro | 24 + src/components/blocks/YouTubePlayer.astro | 10 + src/components/blocks/banners/Coffee.astro | 13 + src/components/blocks/banners/Error.astro | 8 + src/components/blocks/banners/GitHub.astro | 9 + src/components/blocks/banners/Npm.astro | 12 + src/components/blocks/banners/OldPost.astro | 14 + src/components/blocks/banners/Rss.astro | 12 + src/components/blocks/banners/Warning.astro | 12 + src/components/nav/Menu.astro | 30 + src/components/nav/NavLink.astro | 24 + src/components/nav/Paginator.astro | 49 + src/env.d.ts | 1 + src/layouts/Layout.astro | 96 + src/pages/[permalink].astro | 33 + src/pages/feeds/syndication.xml.js | 64 + src/pages/index.astro | 29 + src/pages/posts/[...page].astro | 59 + src/pages/posts/[year]/[title].astro | 102 + src/pages/robots.txt.js | 26 + src/styles/base/fonts.css | 31 + src/styles/base/index.css | 487 ++ src/styles/base/reset.css | 131 + src/styles/base/vars.css | 162 + src/styles/components/addon-links.css | 14 + src/styles/components/badge-grid.css | 20 + src/styles/components/banners.css | 63 + src/styles/components/buttons.css | 28 + src/styles/components/forms.css | 65 + src/styles/components/mastodon-post.css | 22 + src/styles/components/media-grid.css | 67 + src/styles/components/menu.css | 136 + src/styles/components/modal.css | 63 + src/styles/components/music-chart.css | 103 + src/styles/components/paginator.css | 25 + src/styles/components/progress-bar.css | 13 + src/styles/components/tab-buttons.css | 38 + src/styles/components/text-toggle.css | 23 + src/styles/components/youtube-player.css | 15 + src/styles/feed.liquid | 81 + src/styles/index.css | 39 + src/styles/pages/about.css | 24 + src/styles/pages/books.css | 87 + src/styles/pages/contact.css | 36 + src/styles/pages/links.css | 15 + src/styles/pages/media.css | 42 + src/styles/pages/music.css | 37 + src/styles/pages/watching.css | 29 + src/styles/pages/webrings.css | 20 + src/styles/plugins/prism.css | 110 + src/styles/styles.json | 3 + src/utils/data/activity.js | 24 + src/utils/data/albumReleases.js | 43 + src/utils/data/artists.js | 38 + src/utils/data/blogroll.js | 22 + src/utils/data/books.js | 50 + src/utils/data/concerts.js | 32 + src/utils/data/genres.js | 18 + src/utils/data/globals.js | 19 + src/utils/data/links.js | 31 + src/utils/data/movies.js | 42 + src/utils/data/music.js | 79 + src/utils/data/nav.js | 39 + src/utils/data/nowPlaying.js | 24 + src/utils/data/pages.js | 16 + src/utils/data/posts.js | 32 + src/utils/data/robots.js | 29 + src/utils/data/search.js | 19 + src/utils/data/syndication.js | 20 + src/utils/data/tv.js | 46 + src/utils/helpers.js | 45 + workers/analytics/index.js | 40 + workers/analytics/wrangler.template.toml | 13 + workers/artist-import/index.js | 184 + workers/artist-import/wrangler.template.toml | 15 + workers/contact/index.js | 101 + workers/contact/wrangler.template.toml | 12 + workers/mastodon/index.js | 149 + workers/mastodon/wrangler.template.toml | 21 + workers/playing/index.js | 45 + workers/playing/wrangler.template.toml | 12 + workers/rebuild/index.js | 20 + workers/rebuild/wrangler.template.toml | 10 + workers/scrobble/index.js | 250 + workers/scrobble/wrangler.template.toml | 15 + workers/search/index.js | 44 + workers/search/wrangler.template.toml | 12 + workers/sitemap/index.js | 51 + workers/sitemap/wrangler.template.toml | 12 + 143 files changed, 13594 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 _headers create mode 100644 _redirects create mode 100644 astro.config.mjs create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/fonts/ml.woff2 create mode 100644 public/fonts/mlb.woff2 create mode 100644 public/fonts/mlbi.woff2 create mode 100644 public/fonts/mli.woff2 create mode 100644 public/scripts/index.js create mode 100644 queries/functions/search.psql create mode 100644 queries/views/content/links.psql create mode 100644 queries/views/content/posts.psql create mode 100644 queries/views/feeds/all-content.psql create mode 100644 queries/views/feeds/search.psql create mode 100644 queries/views/feeds/sitemap.psql create mode 100644 queries/views/feeds/syndication.psql create mode 100644 queries/views/globals/index.psql create mode 100644 queries/views/globals/nav.psql create mode 100644 queries/views/globals/pages.psql create mode 100644 queries/views/media/books.psql create mode 100644 queries/views/media/movies.psql create mode 100644 queries/views/media/music/album-releases.psql create mode 100644 queries/views/media/music/artists.psql create mode 100644 queries/views/media/music/concerts.psql create mode 100644 queries/views/media/music/genres.psql create mode 100644 queries/views/media/music/listens.psql create mode 100644 queries/views/media/music/month/albums.psql create mode 100644 queries/views/media/music/month/artists.psql create mode 100644 queries/views/media/music/month/genres.psql create mode 100644 queries/views/media/music/month/tracks.psql create mode 100644 queries/views/media/music/now-playing.psql create mode 100644 queries/views/media/music/recent-tracks.psql create mode 100644 queries/views/media/music/week/albums.psql create mode 100644 queries/views/media/music/week/artists.psql create mode 100644 queries/views/media/music/week/genres.psql create mode 100644 queries/views/media/music/week/tracks.psql create mode 100644 queries/views/media/shows.psql create mode 100644 scripts/worker-build.mjs create mode 100644 src/components/BlockRenderer.astro create mode 100644 src/components/Footer.astro create mode 100644 src/components/Header.astro create mode 100644 src/components/IconMapper.astro create mode 100644 src/components/Intro.astro create mode 100644 src/components/RecentActivity.astro create mode 100644 src/components/RecentPosts.astro create mode 100644 src/components/blocks/AssociatedMedia.astro create mode 100644 src/components/blocks/Hero.astro create mode 100644 src/components/blocks/MastodonPost.astro create mode 100644 src/components/blocks/Modal.astro create mode 100644 src/components/blocks/NowPlaying.astro create mode 100644 src/components/blocks/YouTubePlayer.astro create mode 100644 src/components/blocks/banners/Coffee.astro create mode 100644 src/components/blocks/banners/Error.astro create mode 100644 src/components/blocks/banners/GitHub.astro create mode 100644 src/components/blocks/banners/Npm.astro create mode 100644 src/components/blocks/banners/OldPost.astro create mode 100644 src/components/blocks/banners/Rss.astro create mode 100644 src/components/blocks/banners/Warning.astro create mode 100644 src/components/nav/Menu.astro create mode 100644 src/components/nav/NavLink.astro create mode 100644 src/components/nav/Paginator.astro create mode 100644 src/env.d.ts create mode 100644 src/layouts/Layout.astro create mode 100644 src/pages/[permalink].astro create mode 100644 src/pages/feeds/syndication.xml.js create mode 100644 src/pages/index.astro create mode 100644 src/pages/posts/[...page].astro create mode 100644 src/pages/posts/[year]/[title].astro create mode 100644 src/pages/robots.txt.js create mode 100644 src/styles/base/fonts.css create mode 100644 src/styles/base/index.css create mode 100644 src/styles/base/reset.css create mode 100644 src/styles/base/vars.css create mode 100644 src/styles/components/addon-links.css create mode 100644 src/styles/components/badge-grid.css create mode 100644 src/styles/components/banners.css create mode 100644 src/styles/components/buttons.css create mode 100644 src/styles/components/forms.css create mode 100644 src/styles/components/mastodon-post.css create mode 100644 src/styles/components/media-grid.css create mode 100644 src/styles/components/menu.css create mode 100644 src/styles/components/modal.css create mode 100644 src/styles/components/music-chart.css create mode 100644 src/styles/components/paginator.css create mode 100644 src/styles/components/progress-bar.css create mode 100644 src/styles/components/tab-buttons.css create mode 100644 src/styles/components/text-toggle.css create mode 100644 src/styles/components/youtube-player.css create mode 100644 src/styles/feed.liquid create mode 100644 src/styles/index.css create mode 100644 src/styles/pages/about.css create mode 100644 src/styles/pages/books.css create mode 100644 src/styles/pages/contact.css create mode 100644 src/styles/pages/links.css create mode 100644 src/styles/pages/media.css create mode 100644 src/styles/pages/music.css create mode 100644 src/styles/pages/watching.css create mode 100644 src/styles/pages/webrings.css create mode 100644 src/styles/plugins/prism.css create mode 100644 src/styles/styles.json create mode 100644 src/utils/data/activity.js create mode 100644 src/utils/data/albumReleases.js create mode 100644 src/utils/data/artists.js create mode 100644 src/utils/data/blogroll.js create mode 100644 src/utils/data/books.js create mode 100644 src/utils/data/concerts.js create mode 100644 src/utils/data/genres.js create mode 100644 src/utils/data/globals.js create mode 100644 src/utils/data/links.js create mode 100644 src/utils/data/movies.js create mode 100644 src/utils/data/music.js create mode 100644 src/utils/data/nav.js create mode 100644 src/utils/data/nowPlaying.js create mode 100644 src/utils/data/pages.js create mode 100644 src/utils/data/posts.js create mode 100644 src/utils/data/robots.js create mode 100644 src/utils/data/search.js create mode 100644 src/utils/data/syndication.js create mode 100644 src/utils/data/tv.js create mode 100644 src/utils/helpers.js create mode 100644 workers/analytics/index.js create mode 100644 workers/analytics/wrangler.template.toml create mode 100644 workers/artist-import/index.js create mode 100644 workers/artist-import/wrangler.template.toml create mode 100644 workers/contact/index.js create mode 100644 workers/contact/wrangler.template.toml create mode 100644 workers/mastodon/index.js create mode 100644 workers/mastodon/wrangler.template.toml create mode 100644 workers/playing/index.js create mode 100644 workers/playing/wrangler.template.toml create mode 100644 workers/rebuild/index.js create mode 100644 workers/rebuild/wrangler.template.toml create mode 100644 workers/scrobble/index.js create mode 100644 workers/scrobble/wrangler.template.toml create mode 100644 workers/search/index.js create mode 100644 workers/search/wrangler.template.toml create mode 100644 workers/sitemap/index.js create mode 100644 workers/sitemap/wrangler.template.toml diff --git a/.env b/.env new file mode 100644 index 0000000..706bf39 --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +ACCOUNT_ID_PLEX= +SUPABASE_URL= +SUPABASE_KEY= +CF_ACCOUNT_ID= +CF_ZONE_ID= +RSS_TO_MASTODON_KV_NAMESPACE_ID= \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e17a9b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# build output +dist/ + +# workers +wrangler.toml +.wrangler + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env.local + +# macOS-specific files +.DS_Store + +# VS Code files +.vscode/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bd2d7ed --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Cory Dransfeldt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d04f881 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# coryd.dev + +Hi! I'm Cory. 👋🏻 + +This is the code for my personal website and portfolio. Built using [11ty](https://www.11ty.dev) and [other tools](https://coryd.dev/colophon). + +[![Follow @cory@follow.coryd.dev on Mastodon](https://cdn.coryd.dev/aec0ea1d-5234-40b3-b7c4-9705fd9cd0e4.png?class=w200)](https://follow.coryd.dev/@cory) [![Buy me a Coffee](https://cdn.coryd.dev/f5b2cae1-331a-4ea0-9962-58ac429cac4a.png?class=w200)](https://www.buymeacoffee.com/cory) [![Made with 11ty](https://cdn.coryd.dev/03c57479-cfa6-423f-8f60-87f3bbef156c.png?class=w200)](https://eleventy.dev) + +[Music](https://coryd.dev/music) / [Watching](https://coryd.dev/watching) / [Books](https://coryd.dev/books) / [Now](https://coryd.dev/now) diff --git a/_headers b/_headers new file mode 100644 index 0000000..d870296 --- /dev/null +++ b/_headers @@ -0,0 +1,67 @@ +/feeds/album-releases + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/album-releases.json + Content-Type: application/json + +/feeds/all + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/all.json + Content-Type: application/json + +/feeds/books + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/books.json + Content-Type: application/json + +/feeds/links + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/links.json + Content-Type: application/json + +/feeds/posts + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/posts.json + Content-Type: application/json + +/feeds/movies + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/feeds/movies.json + Content-Type: application/json + +/feeds/syndication + Content-Type: application/xml; charset=utf-8 + x-content-type-options: nosniff + +/api/search + Content-Type: application/json + +/.well-known/webfinger + Content-Type: application/jrd+json; charset=utf-8 + +/blogroll.opml + Content-Disposition: attachment; filename=cory-dransfeldt-blogroll.opml + +/music/releases.ics + Content-Type: text/calendar + Cache-Control: public, max-age=0, must-revalidate + Access-Control-Allow-Origin: * + Content-Disposition: inline; filename="releases.ics" + +/* + Content-Security-Policy: upgrade-insecure-requests; block-all-mixed-content; + X-Frame-Options: DENY + X-XSS-Protection: 1; mode=block + Referrer-Policy: strict-origin-when-cross-origin, no-referrer-when-downgrade + Permissions-Policy: autoplay=(), camera=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=() \ No newline at end of file diff --git a/_redirects b/_redirects new file mode 100644 index 0000000..6b2361f --- /dev/null +++ b/_redirects @@ -0,0 +1,72 @@ +# 404s +/now.html /now 301 +/contact.html /contact 301 + +# feeds +/feed.xml /feeds/posts 301 +/follow.xml /feeds/all 301 +/feeds/posts.xml /feeds/posts 301 +/feeds/links.xml /feeds/links 301 +/feeds/books.xml /feeds/books 301 +/feeds/movies.xml /feeds/movies 301 +/feeds/all.xml /feeds/all 301 +/feeds/posts/ /feeds/posts 301 +/feeds/links/ /feeds/links 301 +/feeds/books/ /feeds/books 301 +/feeds/movies/ /feeds/movies 301 +/feeds/all/ /feeds/all 301 + +# general +/articles/ /posts/ 301 +/tags /search 301 + +# blog posts +/blog/fixing-safari-icloud-syncing /posts/2022/fixing-safari-icloud-syncing/ 301 +/blog/migrating-to-fastmail /posts/2022/migrating-to-fastmail/ 301 +/blog/client-side-webmentions-in-nextjs /posts/2023/client-side-webmentions-in-nextjs/ 301 +/blog/apple-centric-digital-privacy-tools /posts/2022/apple-centric-digital-privacy-tools/ 301 +/blog/automating-rss-syndication-with-nextjs-github /posts/2023/automating-rss-syndication-with-nextjs-github/ 301 +/blog/apple-music-a-tale-of-woe /posts/2021/apple-music-a-tale-of-woe/ 301 +/blog/adding-client-side-rendered-webmentions-to-my-blog /posts/2023/client-side-webmentions-in-nextjs/ 301 +/blog/automating-email-cleanup-in-gmail /posts/2022/automating-email-cleanup-in-gmail/ 301 +/blog/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt /posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ 301 +/blog/simple-api-fetch-hooks-with-swr /posts/2022/simple-api-fetch-hooks-with-swr/ 301 +/2023/02/automatingandprobablyoverengineeringmy-nowpage /posts/2023/automating-and-overengineering-my-now-page/ 301 +/2023/01/workflows-handling-inbound-email-on-fastmail-with-regular-expressions /posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ 301 +/posts/2023/i-block-ads/null /posts/2023/i-block-ads/ 301 +/posts/2023/i-dont-want-streaming-music/null /posts/2023/i-dont-want-streaming-music/ 301 +/posts/2022/migrating-to-fastmail/null /posts/2022/migrating-to-fastmail/ 301 +/posts/2023/webmentions-in-eleventy/null /posts/2023/webmentions-in-eleventy/ 301 +/posts/2023/a-safari-specific-guide-to-making-the-modern-web-suck-less/null /posts/2023/a-safari-specific-guide-to-making-the-modern-web-suck-less/ 301 +/posts/2024/dont-be-afraid-to-admit-when-you-dont-know-something/ /posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ 301 +/posts/2024/data-sharing-should-always-be-opt-in/ /posts/2024/access-to-data-isnt-a-grant-to-exploit-it/ 301 +/posts/2023/popular-posts-widget-using-eleventy-plausible/ /posts/2023/building-a-popular-posts-widget-in-eleventy-using-plausible-analytics/ 301 +/posts/2023/i-dont-want-streaming-music/ /posts/2023/i-dont-want-streaming-music-i-just-want-to-stream-my-music/ 301 +/posts/2021/apple-music-a-tale-of-woe/ /posts/2022/apple-music-a-tale-of-woe/ 301 +/posts/2024/weaving-music-in-and-out-of-my-personal-site/ /posts/2024/weaving-music-data-in-and-out-of-my-personal-website/ 301 +/posts/2023/fastmail-handling-inbound-email-with-regex-filters-now-with-chatgpt/ /posts/2023/workflows-handling-inbound-email-on-fastmail-with-regular-expressions-now-featuring-chatgpt/ 301 +/-want-anything-your-ai-generates/ /posts/2024/i-dont-want-anything-your-ai-generates/ 301 +/posts/2023/default-apps-2023/ /posts/2023/my-default-apps-2023-edition/ 301 +/posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ /posts/2024/dont-be-afraid-to-admin-when-you-dont-know-something/ 301 +/posts/2023/displaying-listening-data-from-apple-music-using-musickit/ /posts/2023/displaying-listening-data-from-apple-music-using-musickitjs/ 301 +/posts/2024/2024-minimalism-as-self-preservation/ /posts/2024/minimalism-as-self-preservation/ 301 +/posts/2023/client-side-webmentions-in-nextjs/ /posts/2023/adding-client-side-webmentions-to-my-nextjs-blog/ 301 +/posts/2024/2024-adblocker-required/ /posts/2024/adblocker-required/ 301 +/posts/2023/scheduled-eleventy-builds-cron-github-actions/ /posts/2023/scheduled-eleventy-builds-on-vercel-with-cron-triggered-github-actions/ 301 +/posts/2024/against-the-commercial-web/ /posts/2024/against-the-commercial-internet/ 301 +/posts/2023/i-removed-tailwind-from-my-site/ /posts/2024/i-removed-tailwind-from-my-site/ +/posts/2024/handling-images-with-b2-netlify-image-cdn-hazel-mountain-duck/ /posts/2024/handling-images-with-b2-netlifys-image-cdn-hazel-and-mountain-duck/ 301 +/posts/2023/my-default-apps-2023-edition/ /uses 301 +/posts/2024/link-blogging-using-readwise/ /posts/2024/link-blogging-using-readwise-reader/ 301 +/2022/12/automating-email-cleanup-in-gmail /posts/2022/automating-email-cleanup-in-gmail/ 301 +/posts/2023/automate-syndicate-content-mastodon-eleventy/ /posts/2023/automate-and-syndicate-content-from-eleventy-to-mastodon/ 301 +/posts/2023/road-to-madness-apple-music-charts/ /posts/2023/road-to-madness-charting-apple-music-listening-data/ 301 +/posts/2023/semi-automated-hashtags-syndicated-posts/ /posts/2023/semi-automated-hashtags-for-syndicated-posts/ 301 +/posts/2023/automating-rss-syndication-with-nextjs-github/ /posts/2023/automating-rss-syndication-and-sharing-with-nextjs-and-github/ 301 +/posts/2023/locally-stored-music-and-storage-as-a-meaningful-constraint/ /posts/2023/doppler-locally-stored-music-and-storage-as-a-beneficial-constraint/ 301 +/blog/digital-privacy-tools /posts/2021/digital-privacy-tools/ 301 +/posts/2023/now-page-update-matter-favorites/ /posts/2023/now-page-update-favorite-articles-from-matter/ 301 +/posts/2023/now-playing-eleventy-netlify-edge-functions-emoji/ /posts/2023/displaying-now-playing-data-with-matching-emoji-using-netlify-edge-functions-and-eleventy/ 301 +/posts/2014/sublime-text-ctrl-tab-key-bindings/ /posts/2014/sublime-text-3-ctrl-tab-key-bindings/ 301 +/posts/2022/simple-api-fetch-hooks-with-swr/ /posts/2022/simple-data-fetching-with-custom-react-hooks-and-swr/ 301 +/posts/2023/drying-up-now-page-templates-eleventy/ /posts/2023/drying-up-now-page-templates-and-normalizing-data-in-eleventy/ 301 \ No newline at end of file diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..d59e758 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,22 @@ +import { defineConfig } from "astro/config"; +import cloudflare from "@astrojs/cloudflare"; +import react from "@astrojs/react"; + +export default defineConfig({ + output: "server", + adapter: cloudflare(), + integrations: [react()], + vite: { + resolve: { + alias: { + "@cdransf": "node_modules/@cdransf", + "@components": "/src/components", + "@data": "/src/utils/data", + "@layouts": "/src/layouts", + "@scripts": "/src/scripts", + "@styles": "/src/styles", + "@utils": "/src/utils", + }, + }, + }, +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c9e75be --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6984 @@ +{ + "name": "coryd.dev", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "coryd.dev", + "version": "0.0.1", + "dependencies": { + "@astrojs/cloudflare": "^11.2.0", + "@astrojs/react": "^3.6.2", + "@tabler/icons-react": "^3.19.0", + "astro": "^4.16.13", + "luxon": "^3.5.0" + }, + "devDependencies": { + "@supabase/supabase-js": "^2.45.4", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-footnote": "^4.0.0", + "markdown-it-prism": "^2.3.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@astrojs/cloudflare": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@astrojs/cloudflare/-/cloudflare-11.2.0.tgz", + "integrity": "sha512-XSDAYg2NJVo88GLD8kC20sG3ftQb446/+Jvqzd/wTxyLseMIioExdDNYCS51LmxG4De6YHphAF/f0AyyKItSjg==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.4.1", + "@astrojs/underscore-redirects": "^0.3.4", + "@cloudflare/workers-types": "^4.20241022.0", + "@inox-tools/astro-when": "^0.2.4", + "esbuild": "^0.21.5", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12", + "miniflare": "^3.20241018.0", + "tiny-glob": "^0.2.9", + "wrangler": "^3.82.0" + }, + "peerDependencies": { + "astro": "^4.10.3" + } + }, + "node_modules/@astrojs/compiler": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.10.3.tgz", + "integrity": "sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==", + "license": "MIT" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.4.1.tgz", + "integrity": "sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==", + "license": "MIT" + }, + "node_modules/@astrojs/markdown-remark": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-5.3.0.tgz", + "integrity": "sha512-r0Ikqr0e6ozPb5bvhup1qdWnSPUvQu6tub4ZLYaKyG50BXZ0ej6FhGz3GpChKpH7kglRFPObJd/bDyf2VM9pkg==", + "license": "MIT", + "dependencies": { + "@astrojs/prism": "3.1.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "import-meta-resolve": "^4.1.0", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.1", + "remark-smartypants": "^3.0.2", + "shiki": "^1.22.0", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/prism": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.1.0.tgz", + "integrity": "sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.29.0" + }, + "engines": { + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + } + }, + "node_modules/@astrojs/react": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-3.6.2.tgz", + "integrity": "sha512-fK29lYI7zK/KG4ZBy956x4dmauZcZ18osFkuyGa8r3gmmCQa2NZ9XNu9WaVYEUm0j89f4Gii4tbxLoyM8nk2MA==", + "license": "MIT", + "dependencies": { + "@vitejs/plugin-react": "^4.3.1", + "ultrahtml": "^1.5.3" + }, + "engines": { + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + }, + "peerDependencies": { + "@types/react": "^17.0.50 || ^18.0.21", + "@types/react-dom": "^17.0.17 || ^18.0.6", + "react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.1.0.tgz", + "integrity": "sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.0.0", + "debug": "^4.3.4", + "dlv": "^1.1.3", + "dset": "^3.1.3", + "is-docker": "^3.0.0", + "is-wsl": "^3.0.0", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + } + }, + "node_modules/@astrojs/underscore-redirects": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@astrojs/underscore-redirects/-/underscore-redirects-0.3.4.tgz", + "integrity": "sha512-vYuYtIrTwxFlDRIhuekscorsHdLL8Hr3mgOczfM1tRWVPn54dDNcKG0DmfL4DlC5YJRoqVaVdUs508Hw643NTw==", + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz", + "integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz", + "integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", + "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "mime": "^3.0.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241106.1.tgz", + "integrity": "sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241106.1.tgz", + "integrity": "sha512-j3dg/42D/bPgfNP3cRUBxF+4waCKO/5YKwXNj+lnVOwHxDu+ne5pFw9TIkKYcWTcwn0ZUkbNZNM5rhJqRn4xbg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241106.1.tgz", + "integrity": "sha512-Ih+Ye8E1DMBXcKrJktGfGztFqHKaX1CeByqshmTbODnWKHt6O65ax3oTecUwyC0+abuyraOpAtdhHNpFMhUkmw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241106.1.tgz", + "integrity": "sha512-mdQFPk4+14Yywn7n1xIzI+6olWM8Ybz10R7H3h+rk0XulMumCWUCy1CzIDauOx6GyIcSgKIibYMssVHZR30ObA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241106.1.tgz", + "integrity": "sha512-4rtcss31E/Rb/PeFocZfr+B9i1MdrkhsTBWizh8siNR4KMmkslU2xs2wPaH1z8+ErxkOsHrKRa5EPLh5rIiFeg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-shared": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-shared/-/workers-shared-0.7.1.tgz", + "integrity": "sha512-46cP5FCrl3TrvHeoHLb5SRuiDMKH5kc9Yvo36SAfzt8dqJI/qJRoY1GP3ioHn/gP7v2QIoUOTAzIl7Ml7MnfrA==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "mime": "^3.0.0", + "zod": "^3.22.3" + }, + "engines": { + "node": ">=16.7.0" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20241112.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20241112.0.tgz", + "integrity": "sha512-Q4p9bAWZrX14bSCKY9to19xl0KMU7nsO5sJ2cTVspHoypsjPUMeQCsjHjmsO2C4Myo8/LPeDvmqFmkyNAPPYZw==", + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild-plugins/node-globals-polyfill": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", + "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "license": "ISC", + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", + "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "license": "ISC", + "dependencies": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "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.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "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.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "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.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "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.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "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.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "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.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "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.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "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.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "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.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "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.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "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.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "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.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "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.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "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/@inox-tools/astro-when": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@inox-tools/astro-when/-/astro-when-0.2.4.tgz", + "integrity": "sha512-A1urUbru+Ni7UnsWui0Cq3rGXE75XsiVmU3vmJXhA9duQ4JyIYxLZALDSsqsT0pAzBrUWokZ09fALJ5eJUPtZQ==", + "license": "MIT", + "dependencies": { + "astro-integration-kit": "~0.16.1", + "debug": "^4.3.7" + }, + "peerDependencies": { + "astro": "^4" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "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/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.23.0.tgz", + "integrity": "sha512-J4Fo22oBlfRHAXec+1AEzcowv+Qdf4ZQkuP/X/UHYH9+KA9LvyFXSXyS+HxuBRFfon+u7bsmKdRBjoZlbDVRkQ==", + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.23.0", + "@shikijs/engine-oniguruma": "1.23.0", + "@shikijs/types": "1.23.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.23.0.tgz", + "integrity": "sha512-CcrppseWShG+8Efp1iil9divltuXVdCaU4iu+CKvzTGZO5RmXyAiSx668M7VbX8+s/vt1ZKu75Vn/jWi8O3G/Q==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.23.0", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-es": "0.1.2" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.23.0.tgz", + "integrity": "sha512-gS8bZLqVvmZXX+E5JUMJICsBp+kx6gj79MH/UEpKHKIqnUzppgbmEn6zLa6mB5D+sHse2gFei3YYJxQe1EzZXQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.23.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/types": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.23.0.tgz", + "integrity": "sha512-HiwzsihRao+IbPk7FER/EQT/D0dEEK3n5LAtHDzL5iRT+JMblA7y9uitUnjEnHeLkKigNM+ZplrP7MuEyyc5kA==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "license": "MIT" + }, + "node_modules/@supabase/auth-js": { + "version": "2.65.0", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.65.0.tgz", + "integrity": "sha512-+wboHfZufAE2Y612OsKeVP4rVOeGZzzMLD/Ac3HrTQkkY4qXNjI6Af9gtmxwccE5nFvTiF114FEbIQ1hRq5uUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.1.tgz", + "integrity": "sha512-8sZ2ibwHlf+WkHDUZJUXqqmPvWQ3UHN0W30behOJngVh/qHHekhJLCFbh0AjkE9/FqqXtf9eoVvmYgfCLk5tNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.16.1.tgz", + "integrity": "sha512-EOSEZFm5pPuCPGCmLF1VOCS78DfkSz600PBuvBND/IZmMciJ1pmsS3ss6TkB6UkuvTybYiBh7gKOYyxoEO3USA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.10.2.tgz", + "integrity": "sha512-qyCQaNg90HmJstsvr2aJNxK2zgoKh9ZZA8oqb7UT2LCh3mj9zpa3Iwu167AuyNxsxrUE8eEJ2yH6wLCij4EApA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14", + "@types/phoenix": "^1.5.4", + "@types/ws": "^8.5.10", + "ws": "^8.14.2" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.0.tgz", + "integrity": "sha512-iZenEdO6Mx9iTR6T7wC7sk6KKsoDPLq8rdu5VRy7+JiT1i8fnqfcOr6mfF2Eaqky9VQzhP8zZKQYjzozB65Rig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.45.4", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.45.4.tgz", + "integrity": "sha512-E5p8/zOLaQ3a462MZnmnz03CrduA5ySH9hZyL03Y+QZLIOO4/Gs8Rdy4ZCKDHsN7x0xdanVEWWFN3pJFQr9/hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@supabase/auth-js": "2.65.0", + "@supabase/functions-js": "2.4.1", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.16.1", + "@supabase/realtime-js": "2.10.2", + "@supabase/storage-js": "2.7.0" + } + }, + "node_modules/@tabler/icons": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.19.0.tgz", + "integrity": "sha512-A4WEWqpdbTfnpFEtwXqwAe9qf9sp1yRPvzppqAuwcoF0q5YInqB+JkJtSFToCyBpPVeLxJUxxkapLvt2qQgnag==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-react": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.19.0.tgz", + "integrity": "sha512-AqEWGI0tQWgqo6ZjMO5yJ9sYT8oXLuAM/up0hN9iENS6IdtNZryKrkNSiMgpwweNTpl8wFFG/dAZ959S91A/uQ==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "3.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "react": ">= 16" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" + }, + "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/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "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/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "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": "22.7.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", + "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.5.tgz", + "integrity": "sha512-xegpDuR+z0UqG9fwHqNoy3rI7JDlvaPh2TY47Fl80oq6g+hXT+c/LEuE43X48clZ6lOfANl5WrPur9fYO1RJ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/react": "*" + } + }, + "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/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz", + "integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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/as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "license": "MIT", + "dependencies": { + "printable-characters": "^1.0.42" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astro": { + "version": "4.16.13", + "resolved": "https://registry.npmjs.org/astro/-/astro-4.16.13.tgz", + "integrity": "sha512-Mtd76+BC0zLWqoXpf9xc731AhdH4MNh5JFHYdLRvSH0Nqn48hA64dPGh/cWsJvh/DZFmC0NTZusM1Qq2gyNaVg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^2.10.3", + "@astrojs/internal-helpers": "0.4.1", + "@astrojs/markdown-remark": "5.3.0", + "@astrojs/telemetry": "3.1.0", + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/types": "^7.26.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.1.3", + "@types/babel__core": "^7.20.5", + "@types/cookie": "^0.6.0", + "acorn": "^8.14.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "boxen": "8.0.1", + "ci-info": "^4.0.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^1.0.1", + "cookie": "^0.7.2", + "cssesc": "^3.0.0", + "debug": "^4.3.7", + "deterministic-object-hash": "^2.0.2", + "devalue": "^5.1.1", + "diff": "^5.2.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "es-module-lexer": "^1.5.4", + "esbuild": "^0.21.5", + "estree-walker": "^3.0.3", + "fast-glob": "^3.3.2", + "flattie": "^1.1.1", + "github-slugger": "^2.0.0", + "gray-matter": "^4.0.3", + "html-escaper": "^3.0.3", + "http-cache-semantics": "^4.1.1", + "js-yaml": "^4.1.0", + "kleur": "^4.1.5", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", + "micromatch": "^4.0.8", + "mrmime": "^2.0.0", + "neotraverse": "^0.6.18", + "ora": "^8.1.1", + "p-limit": "^6.1.0", + "p-queue": "^8.0.1", + "preferred-pm": "^4.0.0", + "prompts": "^2.4.2", + "rehype": "^13.0.2", + "semver": "^7.6.3", + "shiki": "^1.22.2", + "tinyexec": "^0.3.1", + "tsconfck": "^3.1.4", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.3", + "vite": "^5.4.10", + "vitefu": "^1.0.3", + "which-pm": "^3.0.0", + "xxhash-wasm": "^1.0.2", + "yargs-parser": "^21.1.1", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.23.5", + "zod-to-ts": "^1.2.0" + }, + "bin": { + "astro": "astro.js" + }, + "engines": { + "node": "^18.17.1 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "optionalDependencies": { + "sharp": "^0.33.3" + } + }, + "node_modules/astro-integration-kit": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/astro-integration-kit/-/astro-integration-kit-0.16.1.tgz", + "integrity": "sha512-N/iam0PAFrRT9azYZqscP1HowQhC77Dwlp912P0/72k+kwUVgO3m73F26XXukHYoZBsrHgrUrfsWBxuCH3kEUg==", + "license": "MIT", + "dependencies": { + "pathe": "^1.1.2", + "recast": "^0.23.7" + }, + "peerDependencies": { + "astro": "^4.12.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/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", + "license": "MIT" + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "license": "MIT" + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001680", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", + "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + } + }, + "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/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT", + "optional": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "optional": true + }, + "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/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "license": "ISC" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT", + "peer": true + }, + "node_modules/data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/deterministic-object-hash": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", + "license": "MIT", + "dependencies": { + "base-64": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/devalue": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", + "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": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "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/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/electron-to-chromium": { + "version": "1.5.62", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.62.tgz", + "integrity": "sha512-t8c+zLmJHa9dJy96yBZRXGQYoiCEnHYgFwn1asvSPZSUdVxnB62A4RASd7k41ytG3ErFBA0TpHlKg9D9SQBmLg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "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/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-yarn-workspace-root2": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", + "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2", + "pkg-dir": "^4.2.0" + } + }, + "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/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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "license": "Unlicense", + "dependencies": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "license": "MIT" + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "license": "MIT" + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.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.0.4", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", + "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", + "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-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "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": "^6.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-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.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": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.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.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "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-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/itty-time": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/itty-time/-/itty-time-1.0.6.tgz", + "integrity": "sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/load-yaml-file": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz", + "integrity": "sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.5", + "js-yaml": "^3.13.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/load-yaml-file/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/load-yaml-file/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-9.2.0.tgz", + "integrity": "sha512-sa2ErMQ6kKOA4l31gLGYliFQrMKkqSO0ZJgGhDHKijPf0pNFM9vghjAh3gn26pS4JDRs7Iwa9S36gxm3vgZTzg==", + "dev": true, + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it-footnote": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-4.0.0.tgz", + "integrity": "sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/markdown-it-prism": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-prism/-/markdown-it-prism-2.3.0.tgz", + "integrity": "sha512-ePtHY80gZyeje4bn3R3SL0jpd1C9HFaYffJW2Ma0YD+tspqa2v9TuVwUyFwboFu4jnFNcO8oPQROgbcYJbmBvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prismjs": "1.29.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "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.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "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-find-and-replace/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/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "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.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "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.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "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-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.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "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.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "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-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/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "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.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "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-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "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-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "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.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "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.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "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.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/miniflare": { + "version": "3.20241106.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20241106.0.tgz", + "integrity": "sha512-PjOoJKjUUofCueQskfhXlGvvHxZj36UAJAp1DnquMK88MFF50zCULblh0KXMSNM+bXeQYA94Gj06a7kfmBGxPw==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "stoppable": "^1.1.0", + "undici": "^5.28.4", + "workerd": "1.20241106.1", + "ws": "^8.18.0", + "youch": "^3.2.2", + "zod": "^3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "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/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "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-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" + }, + "node_modules/ohash": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz", + "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==", + "license": "MIT" + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oniguruma-to-es": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-0.1.2.tgz", + "integrity": "sha512-sBYKVJlIMB0WPO+tSu/NNB1ytSFeHyyJZ3Ayxfx3f/QUuXu0lvZk0VB4K7npmdlHSC0ldqanzh/sUSlAbgCTfw==", + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^4.4.0", + "regex-recursion": "^4.1.0" + } + }, + "node_modules/ora": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.1.tgz", + "integrity": "sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "license": "MIT" + }, + "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": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "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.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preferred-pm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-4.0.0.tgz", + "integrity": "sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==", + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0", + "find-yarn-workspace-root2": "1.2.16", + "which-pm": "^3.0.0" + }, + "engines": { + "node": ">=18.12" + } + }, + "node_modules/printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "license": "Unlicense" + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/regex": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.4.0.tgz", + "integrity": "sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==", + "license": "MIT" + }, + "node_modules/regex-recursion": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-4.2.1.tgz", + "integrity": "sha512-QHNZyZAeKdndD1G3bKAbBEKOSSK4KOHQrAJ01N1LJeb0SoH4DJIeFhp0uUpETgONifS4+P3sOgoA1dhzgrQvhA==", + "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-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.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "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-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.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "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/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", + "license": "MIT", + "dependencies": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "node_modules/rollup-plugin-inject/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "license": "MIT" + }, + "node_modules/rollup-plugin-inject/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "license": "MIT", + "dependencies": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "license": "MIT", + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/shiki": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.23.0.tgz", + "integrity": "sha512-xfdu9DqPkIpExH29cmiTlgo0/jBki5la1Tkfhsv+Wu5TT3APLNHslR1acxuKJOCWqVdSc+pIbs/2ozjVRGppdg==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.23.0", + "@shikijs/engine-javascript": "1.23.0", + "@shikijs/engine-oniguruma": "1.23.0", + "@shikijs/types": "1.23.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "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/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "license": "MIT" + }, + "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/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "license": "Unlicense", + "dependencies": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "license": "MIT", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "license": "MIT", + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.4.tgz", + "integrity": "sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==", + "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.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.3.tgz", + "integrity": "sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==", + "license": "MIT" + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unenv": { + "name": "unenv-nightly", + "version": "2.0.0-20241024-111401-d4156ac", + "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-2.0.0-20241024-111401-d4156ac.tgz", + "integrity": "sha512-xJO1hfY+Te+/XnfCYrCbFbRcgu6XEODND1s5wnVbaBCkuQX7JXF7fHEXPrukFE2j8EOH848P8QN19VO47XN8hw==", + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "ohash": "^1.1.4", + "pathe": "^1.1.2", + "ufo": "^1.5.4" + } + }, + "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/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.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "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-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.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "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.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "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": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.3.tgz", + "integrity": "sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.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/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-pm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-3.0.0.tgz", + "integrity": "sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==", + "license": "MIT", + "dependencies": { + "load-yaml-file": "^0.2.0" + }, + "engines": { + "node": ">=18.12" + } + }, + "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/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workerd": { + "version": "1.20241106.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20241106.1.tgz", + "integrity": "sha512-1GdKl0kDw8rrirr/ThcK66Kbl4/jd4h8uHx5g7YHBrnenY5SX1UPuop2cnCzYUxlg55kPjzIqqYslz1muRFgFw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20241106.1", + "@cloudflare/workerd-darwin-arm64": "1.20241106.1", + "@cloudflare/workerd-linux-64": "1.20241106.1", + "@cloudflare/workerd-linux-arm64": "1.20241106.1", + "@cloudflare/workerd-windows-64": "1.20241106.1" + } + }, + "node_modules/wrangler": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.87.0.tgz", + "integrity": "sha512-BExktnSLeGgG+uxgnr4h9eZ5nefdpTVcTHR+gEIWRvqk07XL04nJwpPYAOIPKPpB7E2tMdDJgNLGQN/CY6e1xQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.3.4", + "@cloudflare/workers-shared": "0.7.1", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "blake3-wasm": "^2.1.5", + "chokidar": "^4.0.1", + "date-fns": "^4.1.0", + "esbuild": "0.17.19", + "itty-time": "^1.0.6", + "miniflare": "3.20241106.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.3.0", + "resolve": "^1.22.8", + "resolve.exports": "^2.0.2", + "selfsigned": "^2.0.1", + "source-map": "^0.6.1", + "unenv": "npm:unenv-nightly@2.0.0-20241024-111401-d4156ac", + "workerd": "1.20241106.1", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=16.17.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20241106.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/wrangler/node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "license": "MIT" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/youch": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz", + "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==", + "license": "MIT", + "dependencies": { + "cookie": "^0.7.1", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.23.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.5.tgz", + "integrity": "sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.23.3" + } + }, + "node_modules/zod-to-ts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", + "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", + "peerDependencies": { + "typescript": "^4.9.4 || ^5.0.2", + "zod": "^3" + } + }, + "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..2606701 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "coryd.dev", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro", + "build:worker": "node scripts/worker-build.mjs $WORKER_NAME", + "deploy:worker": "wrangler deploy --env production --config workers/$npm_config_worker/wrangler.toml" + }, + "dependencies": { + "@astrojs/cloudflare": "^11.2.0", + "@astrojs/react": "^3.6.2", + "@tabler/icons-react": "^3.19.0", + "astro": "^4.16.13", + "luxon": "^3.5.0" + }, + "devDependencies": { + "@supabase/supabase-js": "^2.45.4", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-footnote": "^4.0.0", + "markdown-it-prism": "^2.3.0" + } +} diff --git a/public/fonts/ml.woff2 b/public/fonts/ml.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..e987e0783c9cebf19a53a69b520459d4e36bb970 GIT binary patch literal 4388 zcmV+<5!>!}Pew8T0RR9101+er3;+NC03b8~01(aq0t43o00000000000000000000 z0000RAO>JRQ&d4zNC1I03bQz;E&(2d11@>JiZ=1R@T^YfigPR_&{%PFV4Z{cXRTA=>6`&B`jw#7Lxkq8@nt z2jS628x;i;qnX24r?D=U9Sta;0FWrU&2AAy7KEHw3aLES`A_E-B10@5h(+l|;VtU@ z1?ZrpHO(Av@>oWps$BnXEwwW#ZCr^Jv9?vSf0q8u9%QdHVcgAKfxy=Fc@{3=DF@iK z64~MNC{&HCH^4%hzG`c$u$ocK@8zJL9f(i`ukj{;0B{UtLg|_L3PK?RK;S4*62s{1U9-yFJut} z0wEL(K;H!!nZLm4n!DhCtpunSf=pA1umbuVfK5suM0(pQ1p^3>2|A3Dv0C;d%@>X| zQ!=|6Zp{{3?p}QsQDUWVs3k_VSW*@W1P;~}mSMw%)4nu{#==r0b{_josvLH;Y&1oR zWphZAFIBE|8LCvMltou2kD^AQ1|`asss<1m0l;Md9|IvHfsX(z1h}-2=}`nWf*=VR zK#M;ZD7yuNF%+2L46=?yZG+8aEx0j=Y*tt5+cWzDEe_s49+Z8vt&vv84THw%`}tI? zlDM&qS@N@|UfwTqj4x7;{W@o|Ub{(WF^gk=)$7vpSm-N9wa+u3#C=W%~NYvtqXC0{)Ra^7ad2Mm8x_2^NB%DZ1p+`Sd<|8!9;x-K}g2mAIb zIoEOSK`VD4L>4l)B}sk;?mh3qLlg{Q3j;^adMSv&d+m$gK{Cp{0rF zFvd-Y4eYd8#%&eZY8f8W#jfS6|E;6FMe zaNuTzUe5iOn0#|Nw>wx{JDddiQqCoh=X;S!^Tw)rAi@Wd1oN=KksT!ZUrqQPHK8EE z7#>c-Q##Ti%KNYNS?5W1VdGBnM!*icC&+-J?3(sYA-#BnW@CI}N!-6#eiGjl7yK()g!RQ>+@xMuS z>?ATTNYTcaB$VnIN~}K^>`vr&cCemjLBH3-B=kI2d1Uy*Ol7#=)W*2fBxLSP;1r%p zfR{bj^jJR`LmcyLqN~8#SpNK0cz0@{7a`%l@HURdJoPYOH3WocJex4(_{jCA@+wiu zt3^e)(sk#cw36B|_{5#y^h?ICYMH5!UO?0J`a2Mwl|n~)fbS^^7rd8~JszWr^%T={ zkd)gps=9I(S>o{N##ZQ$jjKh|FK|Uu4?-FQ zr?}+96STzRyN#Q;yt%E@U_(nPL5by7(VTRI$xv+Z6^%yJ!kot9if8fYPQg)T$}#>X ztVeL3NUZ+ML&$msLq(Sj-UPCy68N4V_is(4uVBch%}} zU4PaRa+LS>;f8&o`hDNL4v-_4WDSJrf>zZ_lN>8`9SDRNE2xHh^=Xex`fVom;B+qg z&R7E(fVDMYLn!VbPwpA^O%2>S)c|Cgi9uGg(Tkc-()VEn_7H3!rAzrlKe30_V~l15 zy`oTf0fF4mIWgJPXv|@xB0n@!otKd|Y=ko4ifYJQu`8S-l!BY2_DQW%#xFFcr{;U`+Z%Hpt z6QcF%vU~$7POZmFVf0#P=rvAy|NeFFkC~x0^nv3Wmqk!879(w1n7m3U;7if8ZoD}! zAAf=)`tO`e2pfVQ4cm$A1a~St6l!YRuGwOw;TmRdTFtGNgK-|mhnKw$VtuByb2)2} zH9_yF?u86eZbijI^BcrC2&PKtUM$;7=^5Ta@O9%fZ+DCLfRIC_B*Y_1v%GQdDwci4 z7Wut3%iP>P@jD!aVmLe^E={q$Q)abo1;=4UGY*cCj1$|Ym=+rKwLNW9`?_mcY2V2< zv52hrmN3nZ(8c1?c6CcW3~*jh!+GZ8<`wm7t=OH26Bpxo;n_CJ zlmwyN=0?cMz7IV z*CppGxG^3z+Cq;ivy9G|eIu*6(R2{lZT+OLW~*K|mpDYZh}{BkmesSv6iFBjX2`;D zCn@nY&nZq^9Fdq#=ZG5>+|P$6uEAacCy50^LWdQ&q?UfT)zpG6$v$(at#zn5Ta~7( zx z>7EK7OBnZz-Dq{#VGes_ad==lZ$QC{~3|J6-6%0EGN5K?d=`}js)(4h7 zmi6)-BLnvy1Dx9eO11q+KZw;jAx*e%%Xla@ zO+J*1A~6+sz#grD%v{I>B2nXDoSn;0hMIF|7(?$ppkSGNp_z;J@67dEAW+6eFnHrqFe{jy zoQwqWkPeD_#) zWkdv;z@QbSL?x!|4d(|(pN)rWOfIdNuGKm7n)!TS6XS#%@J4d&m6<7-qBguu)T`@o zz|bQ9kZV_w*9c&p_&1}W_5qgW`p@WUy!@{fECI{ayYdG$pwf{nW^k45d}jwQdZIKN zQI^&fRCjoS6pXMKmO|=DWUuP8Sq&~*QjM0h>I)|*loMXwHzOi$db2qkDPJN~Kn$)- z0E^^o9)h?wz&gf#S&QGVXSio}Z){-T0ozD}dg^&JDra5BbzN-h4#h<6Nh&lErn_PP--J83?>u zum1i%zj+n-fB-PbZ#y*imBuQ5g-X(60QgUGtA)M=U->J_P0Dp#ihRpKPdldMsaMg{6btCOi%taPt%V-d8QX{^u9h%!^V{|DA; z)8!%7n;2k-#Pm@mC0aa#)7VJ3{_+SwV^3lyE$(KS1Q{S^UrqwaVYJn_OeYN2I-MZ` zpH7#M?&s+;V*E2b2!qpmS}>wAaXtbJR6%diC9l$DvQ5zED_T&8F(_qMQ$IXBqY(?*|9om!3=LW2`LKBGY zR@P~~fTcn@&6@%AZpN^R5^btDnbIhV#R=Gj{;sOqpJgC4b2H{}Gwo$DVAquHZ_*$~ e*BA_$V=iDT#`+7gLt83nCtPew8T0RR9101+$z3;+NC03bvF01(&!0t43o00000000000000000000 z0000RAO>JRQ&d4zL;!&{3bQz;69F~?Bm;p=3xP}k1Rw>35C|FhiTh^9u2zK=s%+9H# zJH!(n)w`G^ldO@~X^~Lqcqml%2Y#D9U19}u);X*oQky6R6p3_#f(1_GgM1W=P*!Q& zjCGtBxSf}gtNYj0X0pL%Hit@eVut#c6~rZ5lDtPpMQ7>}%(tRC9_epy`-x>3cu0Y2 zw~L#ip{M28`C9Y8K?$benkMD+9)Ks*{%5LD&>Yp#&1Hy3beDsCv=ZR%lTjW2hpQ_4)?`u0tHo4JoAT_jiB*QA%VA8yF#y z!+H$B-va=^^tQ{^5Z1e@0T|!Ll?5Or5zv@KoLcZ&9T4EIh8}qntjIEQ<@~Pzo4{GV zQmxbFsVb~N5W*;s-$_m5$-*wjuKx4NUSaWsVWef#C5CSGsbqn4g;GEd(BV3NH7^*) z-ipzrTpcZgZaoH#_&87nf(lGJ#z?-!(9mJ|KJwSMyAEPq2?s{rpRZNZQ>P zQ_+)zos4lz`44r8~RGZ4eZY?f5moFY#o{1TKV< zI!@t5W}!v~D8VXt<;4aEOfA*W6PvRjsmuB)<8frd?$(O_YIFcC$oabF;njs|{3 z`S${cVTIiQliCTRGzAe#OQBp;YNPmB4}idZzr-WQ33pj*7HOT;LWMR*Qe**}v@m?s zV7bW0;h+{5yd(jcYDM_(!n9L%>m2YXEs+xpQ0G-f%wcKJXF^tSXry~6<0-zOR__RZ z_E?R(l}~|)s4^+i^9)E5i!Q0!HYS@0wSdib8WP_)RkFR0DehABqjSX_Y|zrZ(%juk&aKjKb$q&{hl4?*(>KQC6$^T`_2f1p8f@ z6)UzN0~fMMd8&c{rIN1Iiu&siI~e|ea8GCOJb0O_Yor%i%2k^MW8N~@8oWyNc-qs; zR^Si!D}IM6S#T{46qMZo)ht!_B?BQB8d^j%IYxpLX~_V(ADg4b#w|q&S}WvWF~l9H zRSnfjX(<)fHfSwbJLW?Mu0>qz@3xdT(ag=X#jnm}XUO=Ss9&=KRg$D#8x^A!^AiI6 z5DcD%X>f`YKu1g)1Z?pkgLWUEp8Xm`Qlv-1FH=HpA}0WUCfjNOwV2HeQHk8xF7jL3 zZ{=9%3K~C4FGS~%g;_Wo+RAqC>W>{GM*vd1 zds}z(D7!N9$N!xZ9HXVYh(2>}N@9z(MfTp+GykQ5%?RjO(%zpm8Q>}zXV6*ZujKr~)y;eMLgM=Wm20&lmsVFQ15`n@NXu{cSX}>UT=Vq*iPYP) znVt#Kq0*B5q#b8*u<}nuV=ZxhqgkO!HPw|eNFCV;~3yf%xFFk33+H z$i{BNi{NA^xExe06N^uBP!8Oh2sQ>!)xL|qyDSe0fXwJS7-vc7ZpVqQPkru&pRA8b z?*D#J{`-OZt&+j4ljmLM!RYqeH|s|~2U%#|xT*m9S;z_blN)9BbXw!G&v1Sahi2dT zH~UUtxf>srFx#&#y4dH&HQJHwR~FGd<(NiSIeanItW>6&=19Z~#V;K51tM$?{f3S@ zErVPAzEN~*9goT6)one|6NJ}Kn-#6~+0-9JuI=+G$88QpZn1Y5EW-|T8l9)S7yoVg z9%cTJC3vGExcX%6VL0I598cg+<1&)iKd|DOb1J3WPG7&9)RB1A+u52>TvL&=iEoO$ zC&e)&9P{?x@sjSCOh4Qj3yueGhSs8M;R(#ZAo@n|Id*Y5BaQuB@Op4$s|T*_i>Uio zoG$G4!Lv2f-?mT0m~<0PV~Ki_0zBk^gB3;QAmZR6CKw; z(Qhmv+$Sx_9ez8<$%rp6Q6|5Q*b4QgUXyP9x)^R{Y{R(iBSRGrUc!uT_wJrJJR&sH z$Yz1J>UUZx6U(pGR@C$Hru5LDhPDMRVtV!kw)RXLYE-qBM2`2%p46$ESiZKN)!`%y z)h%R6brsS6wuzD|cp5Xhb$oYlVSE7D>dP&fX{|dPlfeD7h{+J?^fe8_k`C-X`vZMg z3OsMD-+ZLhXYXi@vEUPZ$@ZkryFQ1Hq~~H;8OhoEHg-wa6^F%fF$e25ZM%}L<5X#tzfk(*5wimT6zAL;zJN%vbz}m%6 zia6iYET$mSk1;!JkDYxP$qlRihLZW{!T@WN7~VJ>j>U$36(J%sX+`vM zdGl7ceeRkO>$rlxJG&||De2!XY)l-Lz~twA%+yVup8)?wXt* zw2$l<-7WJOBDrF*g6e84FSe*CHkn^tlYIOc;R2?6@93VH>6yaT2=sj)<>vued4<7A z6{}yqSx{Qd+mzM7l;ImH;FXVN_aLus*sk|ZQr{mI{YwNg3I*=nZIZD=Qat^iPQ0O&ryN*I&JPW z4S3H{=cnTr6X)Tvc_jGqu~>d?Z$iDAy~rfG;6Dwsut3} z4Heu7UO9!#Ch<6|vXZvu{}(CdX7i2u(=33d50ozfj`7Q-5v6W z1H;oDeW8v`%N>Lce0FyyanoS1^9xsec9aW#|6*0p3v{|K+b;vjorVS&xY)}3OWMgvBYF`g2vH7C9B@T@+gZN@=&0MXe1>GSw8d0*<~aN4yfGRv!9&# zzl9BAkgTg2<4&+eXa;*xbj-zO#y_D-=A~}vU#D*9%^A|to9nE&Z*0@U7N5H|qy4=-Pw9D{(q<(VHSv!p*Z!61Pix9$F?;{&%w zV`S%fQun`>kbbYA+rUsxsrU1Qw0_{8KX$UoJ()m}CEV~zNQ3U|cpoV$LekQG@?-X; zvn3n}Uo2FzYPgL8QN4oAL>((cK+nrnYegy>7z4f?zy?JJA)!+Jv`vrjacd#13$1OhgxAksc z_#37OfDj6Rz>hf{z0F9ucLCNz4_u-zgbYwmheD`>UI{5Vtp;t%NEBNnt9S2!`V*|Q-AjT-xuAouiAD4Cw1J=6&m+Ma#;qR^v17h5H`-(+? zJYQ}*jP0B>}*@9A} z`$6MTrDT-c)u@e?S+mGaP9JDUs{6hKL{yb{*yNg2YC4AQSkpaSRxgxxBa#KuCuLc3 mY^k5Fv_}JRQ&d4zKmdU@3biDtdI2^9Bm;p=3xP}k1Rw>2S_dE-FBzkvoYHn6`0E2s zu3{aG)HbyZH8j)_@fe^6P#GJ);jIjd2nc*Nbi>_r*gWz12uWrkqWyle_x6hmcodcF zjYLR9JP{I^5;PGC9S?=dAL6(9=X6dKlLr=7A_ka53)(~qia~~e(dfijlr?ox!7_ez z@cjSZoBN&rX=c*8RgFLc9894Aw$2``LRlVaci1-k+pYYiAERbO64f>K{{Iq?M8W#k znR2@;`>G2Pj{eC0I>G=@=M*gh2?AC4_1M(a*5K}4`?Q<8GCE}MlF33Qv)A`G|0w$l z2bA&_fLtA*1hjQPsDOOm300wL91A6CSx8Y|6`RJgyG$645Mun>yJKx-MB`9O>;5jE z1_5qa$pZEc8iXK(0$Ts;Tv>CPYu0k+B2s|G@x_50!ZifI48>&`^^JW1Y0Z7j>T7uh}-&u2i&^5Kaa}Td!JkcB<=cWK9-K zA&`u_2f4#2a%ZYX6`B_9^bGn8)&DFkUW|ZFu7h?r>UU1GZZD_#tE`G3i(+rf1{gFF zHv1VOwOVwL5^Kg)LyoBdLmifCZ4_E@NC?yuYS%=CM}|)cAdUdw72phT%mdu70Ji|A z8ZwtHF=K6A6#9?^E6lVua<)zVAE8TMh7uz1X-x?05jyOFFbbmz&;oTtYpeAGvQZjA z#5R;O_fa8Ka%i|)9a_;&&Zp?vID*~?f65i%k1JM#!okFl5OsPZ0dzDxHyniaM`=u8 z-G8O%v&9cDSx(oBdTwi}FV7|uR)6o(7b z{tKi;k6=y4dCL+5lu0=4a96Dj7sg!_;wqVyTwRZ-6V1}5KuX&CjvX_{MeW+;Iz|jg zt~n49|CE?dFSE*R&=Uhc@3VYiaFw*8`O10E#+_Dl@5 z;nV&P@x$Gk3B2-2=OM!=TJ`sICBbbgLVDc)0url~ZkC=Tnwl8fpoYQ$wwi6Q1d`Q8 zERfs*t-4wGQiGgTUns@mIT34`yG*09g*xW$@6##OnY-y^??ad3x=w%fGx}1}7NGnH z#I){o&-qmQlC!w3wyN~jp{gCit5igx=m1(>u|5%RTf$9Y+umpv93d)v6)JUjjXvWcDvLs57( z;h7jiL^sY{KJNcteQi4M>G-FwrnLHkQE~jWGtZ%v_o&oa~tsYDiBXsA^=mY>9Qq&ePRnyyo>wy;8$VtR4Lf z)RQkPCU-}#OulK#_2VHwo@j;;G>rsyI1d$N?z%K&W-vnK2|&KyVE7jT{xo}gwgq2X zr!no_N)OKO9b)g~P(NS#O6_rMm;8Fhk#_b_E%B7zm74>tV7dp_>FSrR%4=HEWU4`< zpz$qH#zdSgKnBZ`u%cBttFYKoaHVa_@cU@h-sRY_l$Ol|ylU%w^k_S^X{qznh5Pxk zN^1l825J=Hc_MZV>CYW%U8`jIed&p%vHQ>3Bu^c?gLwe}lAHMyE?8X<}Puy}UoH5XK8jH1vxWAy8>Kj4#0pC-&E zDAT~_A0?|8REZL^gIBJAVM?v(Uew5GPkNQXIylm+eD&a%TGAm+oD8qo0Ji!6wHpTl zh64uLp6+vLzOZ?=PzAF5*?{`wIL2=|Tk_k}z)}Ar$kSg<(9lB%AkU-i2V0RI1vuz` z5AqC$nk~NFvz?H;6YPdL2ZjcB`A8x`Y_XFB_b90o2^aw20IY0~?E z_pn43)zzFKp?E7Gcgre=Yb}$gZ_bP^HCPh%wY?xg3#0V-;i2Kd)IFVkVW)tJn?Z z8B%M3CL#jm1y#-|i_>@84|#$i514~#1|T>8MIZO^$&D4||DEDK@->``o!l}t0F>)Y z^G9!u+z^)c)pY!}v^+y}bi#ZmKEC5=$s7xjusn_4Yjv;>%trnJY5v#*`pIz4!o*4| zEtLMKa&<^n8A^YawwgW>#+e@ke?|BTBYayfDz*mA3wkr(?41X=iCgdQaY3FpW5;iP zaApGG`4Y^)cw+MVK_JQ1zLs|!IYO{)tsu$ z`QYJ1S7`~SB3s2GMiPq*=)a-f&T^~Cs8MVA2e&8{wTkjoHJmdBHo*j43N7n|M^#5| zpg!%YVvdb|Y?$Ae&eqk@y{^V#3x2t%kU>Z@*5G$y!4a52-KCKnUhe3Ww>5D{%$8mp zw@3i7B4rt3L>`5P&82e7c?67(N#>C;I_MXK{nu_39&n}f>=6YLUawFd!Hyy9>aK{l zhZOK=%}%`oVK)muiqU=qcBJssBCU9FufUcs57i0YfY*rnr)s4&jq#AH2F>8LNF$mf z#SecisU-KgDE08VRDWHD0Mc~owD?&pxUv0eKBlRZzyP)Q`e7csfhms=GKa<}ny>-y z=*M1=1mn687HlB#8OV`d$v6>QMtdG|71u}QfbG)WY%<5o-bTP99MjyV5i*zeI=dgT zgNT%8*UkZAm}+;^!tKVTNb_o7AgC8RyBlF{zD<1oq|K6nwlekm_w5UolhzErUfzmA z+BHFq=jzJyEAzzR%`9Ip%|3Xp1B}$|?@3+S7XwY`Zl$pVwRr{Uq6jX_r=mGHxwV2D z#x--*8@*s3Oruun_(wN&$U8tEJ^#q&i!^$eRq4hW+?C>DMpee}S5L{+60iZrGX$st z%+h`PB-XsvQ0efS-ZK1i*@`Nn$Hi!h5NABwh;Sl1w6*|UvZ@&T{BHgX!toT$kmO^1 zrO!f+XVjlAD(mAmHx3k?44{J(=8nqggs6#zN)jVsT@i&Ub`&(pm6?$HOlNd1o|q85 z-jqvZB!(1KQbf+8=29K7!Rvp2IBiw@d238v%TO&UvR7}tMLI57n@2b7tlkxA4q_e|eUMtXy@ko{gncf|7n zBl?+&%4BM4;V|K4$l(R>ayWZy*@`auMZ`)N;!*VS|HR%|z6@^i`?5%EFaLFK^MlBi zZtrzgKf<1*r^_RRWxS8Fb$ALo&$m04(l} zof?aq>N{>8aCjB(>>p8S&Haw?ws-c9sKtX4S>c?dy#8@srC3%pCn>9cD;KajNCAfu zS6;OFoI8A{ct1g&pFqJx%6RIq(R=&V8(?a-twa*86{sVs7 zu}m?eC}pcWvMI88?ZtW#!hH)h@!DdP0cLDykb1p;)*MClgWZBjs`30+kOz;N=svu= z-|qvrY)7(qbZpK;QYHr;#w8o+yC8S#bj`QQ-L27uN?W6_ZT;kLoI}Wda8;*yYxz+} zv+p$ISra?4VP+#hAD#zWVFQ9ja<$4%|C>f=f(uzyn9GzJZe>ZT{&33PnpA8tjnnBZ zm#ECO?6L|)C;1``H~u~{J>$I+60I1MtX)XHU6)2Kspc8Ck=nse_606?(O69&6#RhB z!5B)5#hKr3{M1ISm#L&eVe`l|TWIz4bx#kz{c+!RWIuT8^6}KUh&wr!a@liz`k4>* zj)5Hi!>McBs_Gq&uIe_G6leW7A3qHBfA_T|OczX7O1I=T2CgPFHix)ae))|Z0}-VM z;5tKyg%h7KC!4Dhb80pkcEf)oI6oZ}!dBtzJ~*4cYe~pKMLWTq<}1JErEAgZqCV}+ zhzU(j`r3bUg7-e|iN6c)0ndKy4%r6xfZpEI2>WR;)q9^`lk$KMehMyJ(pGs0 zP7+el7AX#|!0_axmidy!N58mZf4TtzhA!>zdbG78Qvn6*XJ-s-55(BW$&}+Jpj2cb_{mTHuhOQ>0H;{wj>UEk1KJ{=apOQ zN|<*8X)nSaiLn3hoLdp;0`hl|jf@bKn~DO7jvu}rTmCxQ_+Ctuk`enS*_dza5jfNvq$bjP-G{3!dQa#Gr@Y7U23_8j7ADoPIi34@iF5FMb&r zrYoz$v^JIEN~g-J3gpeDIDAthF18ezs=&pukSXk*X&6OQSxH$h!?Y{Gb<0GiJu4JI zb`@<)SlCt;_~*`HMrZ*+Q*>t}*$;x&$pSF;znT^~`m!!AK-Icq+IY6-8Zu*`BUxHA zkDD@Qv+G!{+s(HFSF@ZO)7G;yH)o1AC6EzclWeo|{HWmo0Cb>512^|V0F5%Nd_tSY z$67@s73s18#o%3w!8=K^DQG##K5!L~7gs6`LZRR6YNClIsYC6JE*4s?B;HC#)VIyr z+}_r|gN`nhXEWL^cSWQB|MUI#`+q-Sd^It8(ueqEfbaot6uL6wn;bmAiM6CJ(_^GZ9PhYkhY7-%BGito|aCx zR7aNGaf)54PQ4G?s6%yKT%3*q9o5+ODTJ2JwAeHi3ihJI$yuX2q3VQdWMv6#2oe0o3No8dHh;NQf ar%0#;Vi~M7s}hLTZ_C0mocXV*0RRB?*W=3o literal 0 HcmV?d00001 diff --git a/public/fonts/mli.woff2 b/public/fonts/mli.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2421f87471a46b00e0d5af6ee148b6b2af2fcda8 GIT binary patch literal 4580 zcmV3;+NC03h@L01=G<0t43o00000000000000000000 z0000RAO>JRQ&d4zL;!&{3bh!i7y&i{Bm;p=3xP}k1Rw>2UrmzpF+^%px8cGFcmy4Abf2k@@xS@U+c;TRY)kMido-MfPzZphRg8jL4OXG8fVQ z=w4KOLgMz@#TIg6fl#1v4I+1Z^GARAEy@bGC6;(%R}eYpa)uYM)HY0B=}f!bl^moe zhL!g0vmZzf0C)b>z*s%AGLtGiJyw|npb^`I9=R^P)5M!>Ud3LJqq)*%zkn>u-sER4 zw>#OxTxs*P|C~!H<@BCVxB@FcTStJZvZ@wsm8ejnt`$<(w>pOy<;CQ`ZqUN^7!KE= zfaKqgg8{MRi!*0@Qi*`Yc!2Ofm@e)0z{XfWv>wX@VD9<+z_y?!7@#tr<3-R|;z$zjPBeE(?cp6d7EUHc8d_3C1eEyXghXtLSxFSqQ$RSVdFYtI>;T450Qdwv z1ftRbvHyS<01q5elE(Ecos@8g0aGI|yvCH?;eU>cHMWRv)lx0waa_oUmbd&JaU%BM z=}qodnSA88^4EG!=u7J_+Yp{{J_{VM_q6_=CwyXFqcl+PxGL~6mezCWbaSS4j{XPjL% znA>!mSqSQ}ofgol-bXzHz~Vl(9zVT4SITt$6nHvHEgXd|r2$AnCvEc$u~|ZkXr|7Z zY-$Km*Q=x)%E(B1B*lg)F^gZEOz(-a!PBQ^aXK)H5kNhHlabTL7}u#B$27}yg;g=r zC%GSt1YQftp6y4bCG?XwT>GOtiEXTq4L3U!7d6dBNo@^u8cvdV?%&hq0 z1O6^#Ik4bH=FVt_CsQ*9&jqVQ`%)Q=nsuN6LnFesq7=KApvYn9f*o~pEZ(?6VU^q~ zZLxa1U<;VPU`v^!Z};_8U;OcV1JgI@I(g~SiS|=@j7gX}N8>=2gykvxj{32hs5_0G zwQs!%K_z#>%V}J+b|VJut0bI+hYIE;9h`Ox$Bx}HWJOqw1jshDn=jLWRW-UPy)4Ou zL#MG7*5jk$G%s4>7_q(qr8>_83gmO~A+5L2A08J}kQ4y_GGC~x#e|CY6mjXxOhs8fErys9fj z#G9gtAsHVcA!3FMm-B%-JnC(zWJpuYx_Kr2ef$-PMse54(2k-PM^cCH^YUCqvQ>T( zTmu_X0BQCQR1-0VOH-yp*2Q;{7EL)iRn^q8Uc$v1ffEz6hER`ovhmJH>$%#9`?lQw zkuOKiBikogkH>Y5g&HXS9P^diN0`iioxnBZ!NV3$0a`XoqKkDeQX?Ehg3NsxXh;;k z=tSh$C>r#emhpIC7VG{`BftCW;u=3nEd8A=_2_`#r)$(^?9r@^z^2~rY?N~UpwcZYwodV zQsS`)$B7YI{s9*_<*(*)zKm~JCJdSPoFnE4MU|a-@MV$y4BMNh!$vDh3ogf4V| z-CpsR4lZn;zrX06$!gd40{wQ02WG9E-#Fh8Z~BtD^T|dJc-!OXnvSPcr2!p~{&>gw zB8=VwPWd4OkM62lWovJ%fZ%el19x+Kr{mW{y?(qV=%0Dkhvu+!q|uvqu!0vQX(!P< zG3V1Wt_FUn>Yo$Qh3gqIuv=T}tZihy7}85BTHlWk44Z7#e%oRE7dHJD+WEdf!(V_q z`qO1WRh*JV1%AqUes}cr^Q(VgOkh8O4`07-FRE%^Pjd~m5v4dj=HFBW&S8Rt?6fP@Vu7!nqd$nQJ(lar*Ri%|pZuk6jqP=gJ+Mw( z1A2xoD2uI&*^ru$$@;rVkVN7!d7_d|HcYSt)naWdI5b^p6ta?YO@BFg33uXo5>Ib- zAs~$50E`$P z{oh+DsR_=!(-65KA`I+iW!PJ9;S%4v%sT^9qNW_tJF2V2`;{_A#*vLs&9@la?Toi~ zqig>K8>zP1{m8*7dqtWdz$_hKRQovtUinx_h{|LO%a+ZIkV5eYb1d? z+X!5ql}~Plm0zgn<|sR4bTKPE6=kJv-L91m6R(JxW;<*JThU#%65+uXuc|=9UKr1$ zTY4`D=MDt=a!dLAc8z^{pg_XTgC&`Lg&YYRoMuCLg#+2K!D%y_VR;@0X~b(uaPSpH zfmp(bN|?dadqr*$wMnV|N=Yq>w4x0G!G)u9B8g6}3Z~{F{bs3@gFsr*h?(D!<~8?RFoUcBO>J-u zH8tm=O%uf8L%MVcMLa4_8!lwsRyDB}pp!*GLAV}Cf(l@d-t&r4zMFl$oK4C}Mf_2P zg9cvP^gb@ARUS8F9#|R`z3%6X&y>C3ss&~UD|KgVO@$<*#bHZ z97u;)iOUGTIle!aA9*R9nUDBLGK(%5LOxVtGGuamRwQ(HOD;F!hj3;AT!WXBJi+}C zf%L6H!_|RdUI8x>GKj-CZrFv^=jj?F(3(%T^o9cNp6R&a;VRr{PV~ag!o@9w>mi$B zo#Q<>$PH#--f2(C?J7%q-q-oK4C-CzAKGpT?F{^H{#yDGV>HvcBzvXcN_bZxNTs9r z>uJ^XOaEL{4T67IP(6pXgg-^E2JhDn;iZ}Z!zGLUSIFRNKgDfCBQZUBdPv9fTM9hA z-)0eQe6>N$HguaLKxjF*d1V!(*^PNI+E+derf$T_Av<5q;gaT>KGR>5eQt-h$#3WX zd!pZEF?!4BhdrEdiJdG&H^y%R9~qR7{xfGsNW&+-s`^c~^Q3Q8{kMSNU|s&Nnk=$_ zA|%+tr!lV7ig3E8Qm--k*A#QY-hX%ys=Wqg>m<>Juu^8N!HO?~emh)=hG(#joA2@J z<~OR<#*V&g(n*W}vujh;GoVDE=!n^)sQPyuo%fJ zKPMlTBoQb=Mfpfh5qP2AZAMNE@pEJnx)z7m&=>+%KCdiq8dVxvlP@xsJMn2ON4tP9re$&^Z@d@l69FElSk@jqAmp^mxkqY zcLWw#P-5net#WB78Uf4O^;zxjpQ06{kZ~rrPF!gEzcYe+7j%&)P}Shy3+lyvs0z?g zwgal%0R&}XXiXSEFC=b8j%|u?mDo#Nt5c6y2;)S)9ax<1q(oI9KYXAx6GuTQDERWy z@PWYWJk_#9Gk_327k#C9X&G8=&>QA2($8n<(VC#L=I}3bAOvjb&jL>PpP@A$Ut0Wq z?81*h_LqLTZk-OO1NeHxz+2UYm|Cp2KQOdI%ZDMv?^` zZT$nDf*&@n;NWPYd3?{;g@SyAmM%iWNuNfAn}Vq_R$7@9cPI;dDx$cUg1oZI9C4Z? z_-mUnNDz{c`Tg3=LYhs#fLxJTMfc4 zEVBfh@LN7bZ@Af7Q&Aip+HEm0POf)pNV5f~${@{aNb}-Ho%w|pI6ispNh-+q>Rb;< za?O3#z5ki2{Q`qh;4y$7g&G0|Q#h}}4%`Uf=Q|yo%+&4dUzQ}?KCQ+&TsAsoE&HnR z=XC(btierJ6h&ve8La}DvkQg)hx7FYv~;j>MQR3>KFVa_$?@sbY+;s=8Pgn@juW_U ziHg;B4QAnrHHFcVJ)t(369w5ZWiJVYzOk+01Fb-=;ErM(W_}Wl?N-`HzLZn|vG<%T z-Egi!d$%HZ>s9BEbXafTGCoCRN|Lp^vmhn7h=slX@3Lu2ozPpf!n(cfuXR%IQgMt| z>Ag4a!D9ab03Yj%h0<#l19a@MvUQQYd~Sk^C1otx!>GU)Q)JjRPo*>{Bb=&__zd}`*|;lhz_T2U^M((SbuE`ks2E5R;-f7EMxUF^{R|GzkR@%Q)O zl|I~M4j}g>BQ^}NWAY9b&vU;4zHYV(0f29Lsy`q54$B?WBg`cV0bua6-jp76^bYcU zcnIfmVbcSW03ztafhRJSd!a0u$nphHjx8s8GzHo$+)V|=O$q&B1`RnSXm~U(t{qIl z(Q5H}(;_HlBop&vs|1UdkD&lVERt9SC{{}2_BnU&^m06Ss6zj79&^w5n>{_Gwkh?2 zu|QGl`=^PwP8>`i-xy{j{B!><1CI6`-t$|6(T#R^R1BAxG9R->oB?JSrK)C#c%IL2 zj2fTeY4*pA2y%m(9!X=;W-^Gk^#@4@vK<6`{94p1SE@|C1pDGJDsn*rmp+w>v(IyD zQ0JuYC9kGh5vSs*x_3&TgK$)9vTmowj6B_*iqEpBl*+5*?2|^yRGtN0s(8sZIoXd} z&W(zQjDjJTm;gd6mrkpPwwBp7VU$LWsg46~rvxtAR&rOuNQG)t8w7Jzs-Y^K)>VYZ Ov0xHv1T=R50001XDY)kV literal 0 HcmV?d00001 diff --git a/public/scripts/index.js b/public/scripts/index.js new file mode 100644 index 0000000..6ad2fc1 --- /dev/null +++ b/public/scripts/index.js @@ -0,0 +1,288 @@ +window.addEventListener("load", () => { + // menu keyboard controls + (() => { + const menuInput = document.getElementById("menu-toggle"); + const menuButtonContainer = document.querySelector( + ".menu-button-container" + ); + const menuItems = document.querySelectorAll(".menu-primary li"); + + menuButtonContainer.addEventListener("keydown", (e) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + menuInput.checked = !menuInput.checked; + } + }); + + menuItems.forEach((item) => { + item.addEventListener("keydown", (e) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + item.querySelector("a").click(); + } + }); + }); + + document.addEventListener("keydown", (e) => { + if (e.key === "Escape" && menuInput.checked) menuInput.checked = false; + }); + })(); + + // modal keyboard controls and scroll management + (() => { + const modalInputs = document.querySelectorAll(".modal-input"); + if (!modalInputs) return; + + const toggleBodyScroll = (disableScroll) => { + if (disableScroll) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = ""; + } + }; + + const checkModals = () => { + let isAnyModalOpen = false; + modalInputs.forEach((modalInput) => { + if (modalInput.checked) isAnyModalOpen = true; + }); + toggleBodyScroll(isAnyModalOpen); + }; + + modalInputs.forEach((modalInput) => { + modalInput.addEventListener("change", checkModals); + }); + + document.addEventListener("keydown", (e) => { + if (e.key === "Escape") { + modalInputs.forEach((modalInput) => { + if (modalInput.checked) modalInput.checked = false; + }); + toggleBodyScroll(false); + } + }); + + checkModals(); + })(); + + // text toggle for media pages + (() => { + const button = document.querySelector("[data-toggle-button]"); + const content = document.querySelector("[data-toggle-content]"); + const text = document.querySelectorAll("[data-toggle-content] p"); + const minHeight = 500; // this needs to match the height set on [data-toggle-content].text-toggle-hidden in text-toggle.css + const interiorHeight = Array.from(text).reduce( + (acc, node) => acc + node.scrollHeight, + 0 + ); + + if (!button || !content || !text) return; + + if (interiorHeight < minHeight) { + content.classList.remove("text-toggle-hidden"); + button.style.display = "none"; + return; + } + + button.addEventListener("click", () => { + const isHidden = content.classList.toggle("text-toggle-hidden"); + button.textContent = isHidden ? "Show more" : "Show less"; + }); + })(); + + // search logic + (() => { + if (typeof MiniSearch === "undefined") return; + + const miniSearch = new MiniSearch({ + fields: ["title", "description", "tags", "type"], + idField: "id", + storeFields: [ + "id", + "title", + "url", + "description", + "type", + "tags", + "total_plays", + ], + searchOptions: { + fields: ["title", "tags"], + prefix: true, + fuzzy: 0.1, + boost: { title: 5, tags: 2, description: 1 }, + }, + }); + + const $form = document.querySelector(".search__form"); + const $fallback = document.querySelector(".search__form--fallback"); + const $input = document.querySelector(".search__form--input"); + const $results = document.querySelector(".search__results"); + const $loadMoreButton = document.querySelector(".search__load-more"); + const $typeCheckboxes = document.querySelectorAll( + '.search__form--type input[type="checkbox"]' + ); + + $form.removeAttribute("action"); + $form.removeAttribute("method"); + if ($fallback) $fallback.remove(); + + const PAGE_SIZE = 10; + let currentPage = 1; + let currentResults = []; + let total = 0; + let debounceTimeout; + + const parseMarkdown = (markdown) => + markdown + ? markdown + .replace(/\*\*(.*?)\*\*/g, "$1") + .replace(/\*(.*?)\*/g, "$1") + .replace(/\[(.*?)\]\((.*?)\)/g, '$1') + .replace(/\n/g, "
") + .replace(/[#*_~`]/g, "") + : ""; + + const truncateDescription = (markdown, maxLength = 150) => { + const plainText = + new DOMParser().parseFromString(parseMarkdown(markdown), "text/html") + .body.textContent || ""; + return plainText.length > maxLength + ? `${plainText.substring(0, maxLength)}...` + : plainText; + }; + + const formatArtistTitle = (title, totalPlays) => + totalPlays > 0 + ? `${title} ${totalPlays} plays` + : title; + + const renderSearchResults = (results) => { + const resultHTML = results + .map( + ({ title, url, description, type, total_plays }) => ` +
  • + +

    ${ + type === "artist" && total_plays + ? formatArtistTitle(title, total_plays) + : title + }

    +
    +

    ${truncateDescription(description)}

    +
  • + ` + ) + .join(""); + + $results.innerHTML = + resultHTML || + '
  • No results found.
  • '; + $results.style.display = "block"; + }; + + const loadSearchIndex = async (query, types, page) => { + try { + const typeQuery = types.join(","); + const response = await fetch( + `https://coryd.dev/api/search?q=${query}&type=${typeQuery}&page=${page}&pageSize=${PAGE_SIZE}` + ); + const { results, total: newTotal } = await response.json(); + total = newTotal; + + const formattedResults = results.map((item) => ({ + ...item, + id: item.result_id, + })); + miniSearch.removeAll(); + miniSearch.addAll(formattedResults); + return formattedResults; + } catch (error) { + console.error("Error fetching search data:", error); + return []; + } + }; + + const getSelectedTypes = () => + Array.from($typeCheckboxes) + .filter((cb) => cb.checked) + .map((cb) => cb.value); + + const updateSearchResults = (results) => { + if (currentPage === 1) { + renderSearchResults(results); + } else { + appendSearchResults(results); + } + $loadMoreButton.style.display = + currentPage * PAGE_SIZE < total ? "block" : "none"; + }; + + const appendSearchResults = (results) => { + const newResultsHTML = results + .map( + ({ title, url, description, type, total_plays }) => ` +
  • + +

    ${ + type === "artist" && total_plays + ? formatArtistTitle(title, total_plays) + : title + }

    +
    +

    ${truncateDescription(description)}

    +
  • + ` + ) + .join(""); + $results.insertAdjacentHTML("beforeend", newResultsHTML); + }; + + const handleSearch = async () => { + const query = $input.value.trim(); + if (!query) { + renderSearchResults([]); + $loadMoreButton.style.display = "none"; + return; + } + + const results = await loadSearchIndex(query, getSelectedTypes(), 1); + currentResults = results; + currentPage = 1; + updateSearchResults(results); + }; + + $input.addEventListener("input", () => { + clearTimeout(debounceTimeout); + debounceTimeout = setTimeout(handleSearch, 300); + }); + + $typeCheckboxes.forEach((cb) => + cb.addEventListener("change", handleSearch) + ); + + $loadMoreButton.addEventListener("click", async () => { + currentPage++; + const nextResults = await loadSearchIndex( + $input.value.trim(), + getSelectedTypes(), + currentPage + ); + currentResults = [...currentResults, ...nextResults]; + updateSearchResults(nextResults); + }); + })(); + + // pagination + (() => { + const dropdown = document.querySelector(".pagination select.client-side"); + + if (dropdown) + dropdown.addEventListener("change", (event) => { + const selectedOption = event.target.options[event.target.selectedIndex]; + const selectedHref = selectedOption.getAttribute("data-href"); + + if (selectedHref) window.location.href = selectedHref; + }); + })(); +}); diff --git a/queries/functions/search.psql b/queries/functions/search.psql new file mode 100644 index 0000000..c1ed995 --- /dev/null +++ b/queries/functions/search.psql @@ -0,0 +1,43 @@ +CREATE OR REPLACE FUNCTION public.search_optimized_index(search_query text, page_size integer, page_offset integer, types text[]) + RETURNS TABLE( + result_id integer, + url text, + title text, + description text, + tags text, + genre_name text, + genre_url text, + type text, + total_plays text, + rank real, + total_count bigint + ) + AS $$ +BEGIN + RETURN QUERY + SELECT + s.id::integer AS result_id, + s.url, + s.title, + s.description, + array_to_string(s.tags, ', ') AS tags, + s.genre_name, + s.genre_url, + s.type, + s.total_plays, + ts_rank_cd(to_tsvector('english', s.title || ' ' || s.description || array_to_string(s.tags, ' ')), plainto_tsquery('english', search_query)) AS rank, + COUNT(*) OVER() AS total_count + FROM + optimized_search_index s + WHERE(types IS NULL + OR s.type = ANY(types)) + AND plainto_tsquery('english', search_query) @@ to_tsvector('english', s.title || ' ' || s.description || array_to_string(s.tags, ' ')) + ORDER BY + s.type = 'post' DESC, + s.content_date DESC NULLS LAST, + rank DESC + LIMIT page_size OFFSET page_offset; +END; +$$ +LANGUAGE plpgsql; + diff --git a/queries/views/content/links.psql b/queries/views/content/links.psql new file mode 100644 index 0000000..28af34e --- /dev/null +++ b/queries/views/content/links.psql @@ -0,0 +1,26 @@ +CREATE OR REPLACE VIEW optimized_links AS +SELECT + l.id, + l.title, + l.date, + l.description, + l.link, + a.mastodon, + a.name, + json_build_object('name', a.name, 'url', a.url, 'mastodon', a.mastodon) AS author, + 'link' AS type, +( + SELECT + array_agg(t.name) + FROM + links_tags lt + LEFT JOIN tags t ON lt.tags_id = t.id + WHERE + lt.links_id = l.id) AS tags, +json_build_object('title', CONCAT(l.title, ' via ', a.name), 'url', l.link, 'description', l.description, 'date', l.date) AS feed +FROM + links l + JOIN authors a ON l.author = a.id +ORDER BY + l.date DESC; + diff --git a/queries/views/content/posts.psql b/queries/views/content/posts.psql new file mode 100644 index 0000000..f63964e --- /dev/null +++ b/queries/views/content/posts.psql @@ -0,0 +1,126 @@ +CREATE OR REPLACE VIEW optimized_posts AS +SELECT + p.id, + p.date, + p.title, + p.description, + p.content, + p.featured, + p.slug AS url, + p.mastodon_url, + CASE WHEN df.filename_disk IS NOT NULL + AND df.filename_disk != '' + AND df.filename_disk != '/' THEN + CONCAT('/', df.filename_disk) + ELSE + NULL + END AS image, + p.image_alt, + CASE WHEN EXTRACT(YEAR FROM AGE(CURRENT_DATE, p.date)) > 3 THEN + TRUE + ELSE + FALSE + END AS old_post, +( + SELECT + json_agg( + CASE WHEN pb.collection = 'youtube_player' THEN + json_build_object('type', pb.collection, 'url', yp.url) + WHEN pb.collection = 'github_banner' THEN + json_build_object('type', pb.collection, 'url', gb.url) + WHEN pb.collection = 'npm_banner' THEN + json_build_object('type', pb.collection, 'url', nb.url, 'command', nb.command) + WHEN pb.collection = 'rss_banner' THEN + json_build_object('type', pb.collection, 'url', rb.url, 'text', rb.text) + WHEN pb.collection = 'hero' THEN + json_build_object('type', pb.collection, 'image', CONCAT('/', df_hero.filename_disk), 'alt_text', h.alt_text) + WHEN pb.collection = 'markdown' THEN + json_build_object('type', pb.collection, 'text', md.text) + WHEN pb.collection = 'divider' THEN + json_build_object('type', pb.collection, 'markup', d.markup) + ELSE + json_build_object('type', pb.collection) + END) + FROM + posts_blocks pb + LEFT JOIN youtube_player yp ON pb.collection = 'youtube_player' + AND yp.id = pb.item::integer + LEFT JOIN github_banner gb ON pb.collection = 'github_banner' + AND gb.id = pb.item::integer + LEFT JOIN npm_banner nb ON pb.collection = 'npm_banner' + AND nb.id = pb.item::integer + LEFT JOIN rss_banner rb ON pb.collection = 'rss_banner' + AND rb.id = pb.item::integer + LEFT JOIN hero h ON pb.collection = 'hero' + AND h.id = pb.item::integer + LEFT JOIN directus_files df_hero ON h.image = df_hero.id + LEFT JOIN markdown md ON pb.collection = 'markdown' + AND md.id = pb.item::integer + LEFT JOIN divider d ON pb.collection = 'divider' + AND d.id = pb.item::integer +WHERE + pb.posts_id = p.id) AS blocks, +( + SELECT + array_agg(t.name) + FROM + posts_tags pt + LEFT JOIN tags t ON pt.tags_id = t.id +WHERE + pt.posts_id = p.id) AS tags, +( + SELECT + json_agg(json_build_object('name', g.name, 'url', g.slug)) + FROM + posts_genres gp + LEFT JOIN genres g ON gp.genres_id = g.id +WHERE + gp.posts_id = p.id) AS genres, +( + SELECT + json_agg(json_build_object('name', a.name_string, 'url', a.slug, 'country', a.country, 'total_plays', a.total_plays)) + FROM + posts_artists pa + LEFT JOIN artists a ON pa.artists_id = a.id +WHERE + pa.posts_id = p.id) AS artists, +( + SELECT + json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug) + ORDER BY b.title) + FROM + posts_books pbk + LEFT JOIN books b ON pbk.books_id = b.id +WHERE + pbk.posts_id = p.id) AS books, +( + SELECT + json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug) + ORDER BY m.year DESC) + FROM + posts_movies pm + LEFT JOIN movies m ON pm.movies_id = m.id +WHERE + pm.posts_id = p.id) AS movies, +( + SELECT + json_agg(json_build_object('title', s.title, 'year', s.year, 'url', s.slug)) + FROM + posts_shows ps + LEFT JOIN shows s ON ps.shows_id = s.id +WHERE + ps.posts_id = p.id) AS shows, +json_build_object('title', p.title, 'url', CONCAT('https://coryd.dev', p.slug), 'description', p.content, 'date', p.date, 'image', CASE WHEN df.filename_disk IS NOT NULL + AND df.filename_disk != '' + AND df.filename_disk != '/' THEN + CONCAT('/', df.filename_disk) + ELSE + NULL + END) AS feed +FROM + posts p + LEFT JOIN directus_files df ON p.image = df.id +GROUP BY + p.id, + df.filename_disk; + diff --git a/queries/views/feeds/all-content.psql b/queries/views/feeds/all-content.psql new file mode 100644 index 0000000..43bd3c8 --- /dev/null +++ b/queries/views/feeds/all-content.psql @@ -0,0 +1,79 @@ +CREATE OR REPLACE VIEW optimized_all_activity AS +WITH feed_data AS ( + SELECT + p.date AS content_date, + p.title, + p.content AS description, + CONCAT('https://coryd.dev', p.url) AS url, + NULL AS image, + NULL AS rating, + p.tags, + json_build_object('title', p.title, 'url', CONCAT('https://coryd.dev', p.url), 'description', p.content, 'date', p.date) AS feed + FROM + optimized_posts p + UNION ALL + SELECT + l.date AS content_date, + l.title, + l.description, + l.link AS url, + NULL AS image, + NULL AS rating, + l.tags, + json_build_object('title', CONCAT(l.title, ' via ', l.name), 'url', l.link, 'description', l.description, 'date', l.date) AS feed + FROM + optimized_links l +UNION ALL +SELECT + b.date_finished AS content_date, + b.title, + b.description, + CONCAT('https://coryd.dev', b.url) AS url, + b.image, + b.rating, + b.tags, + CASE WHEN LOWER(b.status) = 'finished' THEN + json_build_object('title', b.title, 'url', CONCAT('https://coryd.dev', b.url), 'description', CASE WHEN b.review IS NOT NULL THEN + b.review + ELSE + b.description + END, 'image', b.image, 'rating', b.rating, 'date', b.date_finished) + ELSE + NULL + END AS feed +FROM + optimized_books b +UNION ALL +SELECT + m.last_watched AS content_date, + m.title, + m.description, + CONCAT('https://coryd.dev', m.url) AS url, + m.image, + m.rating, + m.tags, + CASE WHEN m.last_watched IS NOT NULL THEN + json_build_object('title', m.title, 'url', CONCAT('https://coryd.dev', m.url), 'description', CASE WHEN m.review IS NOT NULL THEN + m.review + ELSE + m.description + END, 'image', m.backdrop, 'rating', m.rating, 'date', m.last_watched) + ELSE + NULL + END AS feed +FROM + optimized_movies m +) +SELECT + json_agg(feed_data.* ORDER BY feed_data.content_date DESC) AS feed +FROM ( + SELECT + * + FROM + feed_data + WHERE + feed IS NOT NULL + ORDER BY + content_date DESC + LIMIT 20) AS feed_data; + diff --git a/queries/views/feeds/search.psql b/queries/views/feeds/search.psql new file mode 100644 index 0000000..3df4c6a --- /dev/null +++ b/queries/views/feeds/search.psql @@ -0,0 +1,109 @@ +CREATE OR REPLACE VIEW optimized_search_index AS +WITH search_data AS ( + SELECT + 'post' AS type, + CONCAT('📝 ', p.title) AS title, + CONCAT('https://coryd.dev', p.url) AS url, + p.description AS description, + p.tags, + NULL AS genre_name, + NULL AS genre_url, + NULL::text AS total_plays, + p.date AS content_date + FROM + optimized_posts p + UNION ALL + SELECT + 'link' AS type, + CONCAT('🔗 ', l.title, ' via ', l.name) AS title, + l.link AS url, + l.description AS description, + l.tags, + NULL AS genre_name, + NULL AS genre_url, + NULL::text AS total_plays, + l.date AS content_date + FROM + optimized_links l + UNION ALL + SELECT + 'book' AS type, + CASE WHEN b.rating IS NOT NULL THEN + CONCAT('📖 ', b.title, ' (', b.rating, ')') + ELSE + CONCAT('📖 ', b.title) + END AS title, + CONCAT('https://coryd.dev', b.url) AS url, + b.description AS description, + b.tags, + NULL AS genre_name, + NULL AS genre_url, + NULL::text AS total_plays, + b.date_finished AS content_date + FROM + optimized_books b + WHERE + LOWER(b.status) = 'finished' + UNION ALL + SELECT + 'artist' AS type, + CONCAT(COALESCE(ar.emoji, ar.genre_emoji, '🎧'), ' ', ar.name) AS title, + CONCAT('https://coryd.dev', ar.url) AS url, + ar.description AS description, + ARRAY[ar.genre_name] AS tags, + ar.genre_name, + CONCAT('https://coryd.dev', ar.genre_slug) AS genre_url, + to_char(ar.total_plays::numeric, 'FM999,999,999,999') AS total_plays, + NULL AS content_date + FROM + optimized_artists ar + UNION ALL + SELECT + 'genre' AS type, + CONCAT(COALESCE(g.emoji, '🎵'), ' ', g.name) AS title, + CONCAT('https://coryd.dev', g.url) AS url, + g.description AS description, + NULL AS tags, + g.name AS genre_name, + CONCAT('https://coryd.dev', g.url) AS genre_url, + NULL::text AS total_plays, + NULL AS content_date + FROM + optimized_genres g + UNION ALL + SELECT + 'show' AS type, + CONCAT('📺 ', s.title, ' (', s.year, ')') AS title, + CONCAT('https://coryd.dev', s.url) AS url, + s.description AS description, + s.tags, + NULL AS genre_name, + NULL AS genre_url, + NULL::text AS total_plays, + s.last_watched_at AS content_date + FROM + optimized_shows s + WHERE + s.last_watched_at IS NOT NULL + UNION ALL + SELECT + 'movie' AS type, + CONCAT('🎬 ', m.title, ' (', m.rating, ')') AS title, + CONCAT('https://coryd.dev', m.url) AS url, + m.description AS description, + m.tags, + NULL AS genre_name, + NULL AS genre_url, + NULL::text AS total_plays, + m.last_watched AS content_date + FROM + optimized_movies m + WHERE + m.rating IS NOT NULL +) +SELECT + ROW_NUMBER() OVER (ORDER BY url) AS id, + * +FROM + search_data; + diff --git a/queries/views/feeds/sitemap.psql b/queries/views/feeds/sitemap.psql new file mode 100644 index 0000000..5654db0 --- /dev/null +++ b/queries/views/feeds/sitemap.psql @@ -0,0 +1,65 @@ +CREATE OR REPLACE VIEW optimized_sitemap AS +WITH sitemap_data AS ( + SELECT + p.date AS content_date, + p.title, + CONCAT('https://coryd.dev', p.url) AS url, + 'monthly' AS changefreq, + 0.7 AS priority + FROM + optimized_posts p + UNION ALL + SELECT + b.date_finished AS content_date, + b.title, + CONCAT('https://coryd.dev', b.url) AS url, + 'monthly' AS changefreq, + 0.5 AS priority + FROM + optimized_books b + UNION ALL + SELECT + m.last_watched AS content_date, + m.title, + CONCAT('https://coryd.dev', m.url) AS url, + 'weekly' AS changefreq, + 0.6 AS priority + FROM + optimized_movies m + UNION ALL + SELECT + NULL AS content_date, + ar.name AS title, + CONCAT('https://coryd.dev', ar.url) AS url, + 'monthly' AS changefreq, + 0.5 AS priority + FROM + optimized_artists ar + UNION ALL + SELECT + NULL AS content_date, + g.name AS title, + CONCAT('https://coryd.dev', g.url) AS url, + 'yearly' AS changefreq, + 0.3 AS priority + FROM + optimized_genres g + UNION ALL + SELECT + s.last_watched_at AS content_date, + s.title, + CONCAT('https://coryd.dev', s.url) AS url, + 'weekly' AS changefreq, + 0.8 AS priority + FROM + optimized_shows s +) +SELECT + url, + title, + content_date AS lastmod, + changefreq, + priority +FROM + sitemap_data; + diff --git a/queries/views/feeds/syndication.psql b/queries/views/feeds/syndication.psql new file mode 100644 index 0000000..e8561e5 --- /dev/null +++ b/queries/views/feeds/syndication.psql @@ -0,0 +1,86 @@ +CREATE OR REPLACE VIEW optimized_syndication AS +WITH syndication_data AS ( + SELECT + p.date AS content_date, + p.title, + p.description, + CONCAT('https://coryd.dev', p.url) AS url, + p.tags, + json_build_object('title', CONCAT('📝 ', p.title, ' ',( + SELECT + array_to_string(array_agg('#' || initcap(replace(t.name, ' ', ''))), ' ') + FROM unnest(p.tags) AS t(name))), 'description', p.description, 'url', CONCAT('https://coryd.dev', p.url), 'date', p.date) AS syndication + FROM + optimized_posts p + UNION ALL + SELECT + l.date AS content_date, + l.title, + l.description, + l.link AS url, + l.tags, + json_build_object('title', CONCAT('🔗 ', l.title, CASE WHEN l.mastodon IS NOT NULL THEN + ' via @' || split_part(l.mastodon, '@', 2) || '@' || split_part(split_part(l.mastodon, 'https://', 2), '/', 1) + ELSE + CONCAT(' via ', l.name) + END, ' ',( + SELECT + array_to_string(array_agg('#' || initcap(replace(t.name, ' ', ''))), ' ') + FROM unnest(l.tags) AS t(name))), 'description', l.description, 'url', l.link, 'date', l.date) AS syndication + FROM + optimized_links l + UNION ALL + SELECT + b.date_finished AS content_date, + b.title, + b.description, + CONCAT('https://coryd.dev', b.url) AS url, + b.tags, + CASE WHEN LOWER(b.status) = 'finished' THEN + json_build_object('title', CONCAT('📖 ', b.title, CASE WHEN b.rating IS NOT NULL THEN + ' (' || b.rating || ')' + ELSE + '' + END, ' ',( + SELECT + array_to_string(array_agg('#' || initcap(replace(t.name, ' ', ''))), ' ') + FROM unnest(b.tags) AS t(name))), 'description', b.description, 'url', CONCAT('https://coryd.dev', b.url), 'date', b.date_finished) + ELSE + NULL + END AS syndication + FROM + optimized_books b + UNION ALL + SELECT + m.last_watched AS content_date, + m.title, + m.description, + CONCAT('https://coryd.dev', m.url) AS url, + m.tags, + CASE WHEN m.last_watched IS NOT NULL THEN + json_build_object('title', CONCAT('🎥 ', m.title, CASE WHEN m.rating IS NOT NULL THEN + ' (' || m.rating || ')' + ELSE + '' + END, ' ',( + SELECT + array_to_string(array_agg('#' || initcap(replace(t.name, ' ', ''))), ' ') + FROM unnest(m.tags) AS t(name))), 'description', m.description, 'url', CONCAT('https://coryd.dev', m.url), 'date', m.last_watched) + ELSE + NULL + END AS syndication + FROM + optimized_movies m +) +SELECT + json_agg(limited_data.*) AS syndication +FROM ( + SELECT + * + FROM + syndication_data + WHERE + syndication IS NOT NULL + ORDER BY + content_date DESC + LIMIT 20) AS limited_data; \ No newline at end of file diff --git a/queries/views/globals/index.psql b/queries/views/globals/index.psql new file mode 100644 index 0000000..a51018a --- /dev/null +++ b/queries/views/globals/index.psql @@ -0,0 +1,22 @@ +CREATE OR REPLACE VIEW optimized_globals AS +SELECT + g.site_name, + g.site_description, + g.intro, + g.author, + g.email, + g.mastodon, + g.url, + g.cdn_url, + g.theme_color, + g.site_type, + g.locale, + g.lang, + g.webfinger_username, + g.webfinger_hostname, + CONCAT('/', df.filename_disk) AS avatar, + CONCAT('/', df2.filename_disk) AS avatar_transparent +FROM + globals g + LEFT JOIN directus_files df ON g.avatar = df.id + LEFT JOIN directus_files df2 ON g.avatar_transparent = df2.id diff --git a/queries/views/globals/nav.psql b/queries/views/globals/nav.psql new file mode 100644 index 0000000..946344d --- /dev/null +++ b/queries/views/globals/nav.psql @@ -0,0 +1,14 @@ +CREATE OR REPLACE VIEW optimized_navigation AS +SELECT + n.id, + n.menu_location, + n.permalink, + n.icon, + n.title, + n.sort, + p.title AS page_title, + p.permalink AS page_permalink +FROM + navigation n + LEFT JOIN pages p ON n.pages = p.id; + diff --git a/queries/views/globals/pages.psql b/queries/views/globals/pages.psql new file mode 100644 index 0000000..d645e2a --- /dev/null +++ b/queries/views/globals/pages.psql @@ -0,0 +1,56 @@ +CREATE OR REPLACE VIEW optimized_pages AS +SELECT + p.id, + p.title, + p.permalink, + p.description, + CONCAT('/', df.filename_disk) AS open_graph_image, + p.updated, +( + SELECT + json_agg( + CASE WHEN pb.collection = 'youtube_player' THEN + json_build_object('type', pb.collection, 'url', yp.url) + WHEN pb.collection = 'github_banner' THEN + json_build_object('type', pb.collection, 'url', gb.url) + WHEN pb.collection = 'npm_banner' THEN + json_build_object('type', pb.collection, 'url', nb.url, 'command', nb.command) + WHEN pb.collection = 'rss_banner' THEN + json_build_object('type', pb.collection, 'url', rb.url, 'text', rb.text) + WHEN pb.collection = 'hero' THEN + json_build_object('type', pb.collection, 'image', CONCAT('/', df_hero.filename_disk), 'alt', h.alt_text) + WHEN pb.collection = 'markdown' THEN + json_build_object('type', pb.collection, 'text', md.text) + WHEN pb.collection = 'divider' THEN + json_build_object('type', pb.collection, 'markup', d.markup) + WHEN pb.collection = 'addon_links' THEN + json_build_object('type', pb.collection, 'addon_links', d.title) + ELSE + json_build_object('type', pb.collection) + END ORDER BY pb.sort) + FROM + pages_blocks pb + LEFT JOIN youtube_player yp ON pb.collection = 'youtube_player' + AND yp.id = pb.item::integer + LEFT JOIN github_banner gb ON pb.collection = 'github_banner' + AND gb.id = pb.item::integer + LEFT JOIN npm_banner nb ON pb.collection = 'npm_banner' + AND nb.id = pb.item::integer + LEFT JOIN rss_banner rb ON pb.collection = 'rss_banner' + AND rb.id = pb.item::integer + LEFT JOIN hero h ON pb.collection = 'hero' + AND h.id = pb.item::integer + LEFT JOIN directus_files df_hero ON h.image = df_hero.id + LEFT JOIN markdown md ON pb.collection = 'markdown' + AND md.id = pb.item::integer + LEFT JOIN divider d ON pb.collection = 'divider' + AND d.id = pb.item::integer +WHERE + pb.pages_id = p.id) AS blocks +FROM + pages p + LEFT JOIN directus_files df ON p.open_graph_image = df.id +GROUP BY + p.id, + df.filename_disk; + diff --git a/queries/views/media/books.psql b/queries/views/media/books.psql new file mode 100644 index 0000000..ed8bbaa --- /dev/null +++ b/queries/views/media/books.psql @@ -0,0 +1,95 @@ +CREATE OR REPLACE VIEW optimized_books AS +SELECT + b.date_finished, + EXTRACT(YEAR FROM b.date_finished) AS year, + b.author, + b.description, + b.title, + b.progress, + b.read_status AS status, + b.star_rating AS rating, + b.review, + b.slug AS url, + CONCAT('/', df.filename_disk) AS image, + b.favorite, + b.tattoo, +( + SELECT + array_agg(t.name) + FROM + books_tags bt + LEFT JOIN tags t ON bt.tags_id = t.id + WHERE + bt.books_id = b.id) AS tags, +( + SELECT + json_agg(json_build_object('name', a.name_string, 'url', a.slug, 'country', a.country, 'total_plays', a.total_plays)) + FROM + books_artists ba + LEFT JOIN artists a ON ba.artists_id = a.id +WHERE + ba.books_id = b.id) AS artists, +( + SELECT + json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug)) + FROM + movies_books mb + LEFT JOIN movies m ON mb.movies_id = m.id +WHERE + mb.books_id = b.id) AS movies, +( + SELECT + json_agg(json_build_object('name', g.name, 'url', g.slug)) + FROM + genres_books gb + LEFT JOIN genres g ON gb.genres_id = g.id +WHERE + gb.books_id = b.id) AS genres, +( + SELECT + json_agg(json_build_object('title', s.title, 'year', s.year, 'url', s.slug)) + FROM + shows_books sb + LEFT JOIN shows s ON sb.shows_id = s.id +WHERE + sb.books_id = b.id) AS shows, +( + SELECT + json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC) + FROM + posts_books pb + LEFT JOIN posts p ON pb.posts_id = p.id +WHERE + pb.books_id = b.id) AS posts, +( + SELECT + json_agg(json_build_object('title', rb.title, 'author', rb.author, 'url', rb.slug) + ORDER BY rb.title) + FROM + related_books rbk + LEFT JOIN books rb ON rbk.related_books_id = rb.id +WHERE + rbk.books_id = b.id) AS related_books, +json_build_object('title', CONCAT(b.title, ' by ', b.author), 'image', CONCAT('/', df.filename_disk), 'url', b.slug, 'alt', CONCAT('Book cover from ', b.title, ' by ', b.author), 'subtext', CASE WHEN b.star_rating IS NOT NULL THEN + b.star_rating + ELSE + NULL + END) AS grid, +CASE WHEN LOWER(b.read_status) = 'finished' + AND b.star_rating IS NOT NULL THEN + json_build_object('title', b.title, 'url', CONCAT('https://coryd.dev', b.slug), 'date', b.date_finished, 'description', CASE WHEN b.review IS NOT NULL THEN + b.review + ELSE + b.description + END, 'image', CONCAT('/', df.filename_disk), 'rating', b.star_rating) +ELSE + NULL +END AS feed +FROM + books b + LEFT JOIN directus_files df ON b.art = df.id +GROUP BY + b.id, + df.filename_disk; + diff --git a/queries/views/media/movies.psql b/queries/views/media/movies.psql new file mode 100644 index 0000000..8f6ffff --- /dev/null +++ b/queries/views/media/movies.psql @@ -0,0 +1,106 @@ +CREATE OR REPLACE VIEW optimized_movies AS +SELECT + m.id, + m.last_watched, + m.title, + m.year, + m.collected, + m.plays, + m.favorite, + m.tattoo, + m.star_rating AS rating, + m.description, + m.review, + m.slug AS url, + CONCAT('/', df.filename_disk) AS image, + CONCAT('/', df2.filename_disk) AS backdrop, + json_build_object('title', m.title, 'url', m.slug, 'image', CONCAT('/', df.filename_disk), 'backdrop', CONCAT('/', df2.filename_disk), 'alt', CONCAT('Poster from ', m.title, ' (', m.year, ')'), 'subtext', CASE WHEN m.star_rating IS NOT NULL THEN + CONCAT(m.star_rating, ' (', m.year, ')') + ELSE + CONCAT('(', m.year, ')') + END) AS grid, +( + SELECT + array_agg(t.name) + FROM + movies_tags mt + LEFT JOIN tags t ON mt.tags_id = t.id + WHERE + mt.movies_id = m.id) AS tags, +( + SELECT + json_agg(json_build_object('name', g.name, 'url', g.slug) + ORDER BY g.name ASC) + FROM + genres_movies gm + LEFT JOIN genres g ON gm.genres_id = g.id +WHERE + gm.movies_id = m.id) AS genres, +( + SELECT + json_agg(json_build_object('name', a.name_string, 'url', a.slug, 'country', a.country, 'total_plays', a.total_plays) + ORDER BY a.name_string ASC) + FROM + movies_artists ma + LEFT JOIN artists a ON ma.artists_id = a.id +WHERE + ma.movies_id = m.id) AS artists, +( + SELECT + json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug) + ORDER BY b.title ASC) + FROM + movies_books mb + LEFT JOIN books b ON mb.books_id = b.id +WHERE + mb.movies_id = m.id) AS books, +( + SELECT + json_agg(json_build_object('title', s.title, 'year', s.year, 'url', s.slug) + ORDER BY s.year DESC) + FROM + shows_movies sm + LEFT JOIN shows s ON sm.shows_id = s.id +WHERE + sm.movies_id = m.id) AS shows, +( + SELECT + json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC) + FROM + posts_movies pm + LEFT JOIN posts p ON pm.posts_id = p.id +WHERE + pm.movies_id = m.id) AS posts, +( + SELECT + json_agg(json_build_object('title', rm.title, 'year', rm.year, 'url', rm.slug) + ORDER BY rm.year DESC) + FROM + related_movies r + LEFT JOIN movies rm ON r.related_movies_id = rm.id +WHERE + r.movies_id = m.id) AS related_movies, +CASE WHEN m.star_rating IS NOT NULL + AND m.last_watched IS NOT NULL THEN + json_build_object('title', m.title, 'url', CONCAT('https://coryd.dev', m.slug), 'date', m.last_watched, 'description', CASE WHEN m.review IS NOT NULL THEN + m.review + ELSE + m.description + END, 'image', CONCAT('/', df2.filename_disk), 'rating', m.star_rating) +ELSE + NULL +END AS feed +FROM + movies m + LEFT JOIN directus_files df ON m.art = df.id + LEFT JOIN directus_files df2 ON m.backdrop = df2.id +GROUP BY + m.id, + df.filename_disk, + df2.filename_disk +ORDER BY + m.last_watched DESC, + m.favorite DESC, + m.title ASC; + diff --git a/queries/views/media/music/album-releases.psql b/queries/views/media/music/album-releases.psql new file mode 100644 index 0000000..08cae10 --- /dev/null +++ b/queries/views/media/music/album-releases.psql @@ -0,0 +1,17 @@ +CREATE OR REPLACE VIEW optimized_album_releases AS +SELECT + a.name AS title, + a.release_date, + a.release_link AS url, + a.total_plays, + CONCAT('/', df.filename_disk) AS image, + json_build_object('name', ar.name_string, 'url', ar.slug, 'description', ar.description) AS artist, + EXTRACT(EPOCH FROM a.release_date) AS release_timestamp, + json_build_object('title', a.name, 'image', CONCAT('/', df.filename_disk), 'url', a.release_link, 'alt', CONCAT(a.name, ' by ', ar.name_string), 'subtext', CONCAT(ar.name_string, ' / ', TO_CHAR(a.release_date, 'Mon FMDD, YYYY'))) AS grid +FROM + albums a + LEFT JOIN directus_files df ON a.art = df.id + LEFT JOIN artists ar ON a.artist = ar.id +WHERE + a.release_date IS NOT NULL; + diff --git a/queries/views/media/music/artists.psql b/queries/views/media/music/artists.psql new file mode 100644 index 0000000..8c8c241 --- /dev/null +++ b/queries/views/media/music/artists.psql @@ -0,0 +1,94 @@ +CREATE OR REPLACE VIEW optimized_artists AS +SELECT + ar.name_string AS name, + ar.slug AS url, + ar.tentative, + to_char(ar.total_plays, 'FM999,999,999,999') AS total_plays, -- Format total_plays with commas + ar.country, + ar.description, + ar.favorite, + g.name AS genre_name, + g.slug AS genre_slug, + g.emoji AS genre_emoji, + json_build_object('name', g.name, 'url', g.slug, 'emoji', g.emoji) AS genre, + ar.emoji, + ar.tattoo, + CONCAT('/', df.filename_disk) AS image, + json_build_object('alt', CONCAT(to_char(ar.total_plays, 'FM999,999,999,999'), ' plays of ', ar.name_string), -- Format total_plays in alt text + 'subtext', CONCAT(to_char(ar.total_plays, 'FM999,999,999,999'), ' plays') -- Format total_plays in subtext +) AS grid, +( + SELECT + json_agg(json_build_object('name', a.name, 'release_year', a.release_year, 'total_plays', to_char(a.total_plays, 'FM999,999,999,999'), -- Format total_plays here as well + 'art', df_album.filename_disk) + ORDER BY a.release_year) + FROM + albums a + LEFT JOIN directus_files df_album ON a.art = df_album.id + WHERE + a.artist = ar.id) AS albums, +( + SELECT + json_agg(json_build_object('id', c.id, 'date', c.date, 'venue_name', v.name, 'venue_name_short', trim(split_part(v.name, ',', 1)), 'venue_latitude', v.latitude, 'venue_longitude', v.longitude, 'notes', c.notes) + ORDER BY c.date DESC) + FROM + concerts c + LEFT JOIN venues v ON c.venue = v.id + WHERE + c.artist = ar.id) AS concerts, +( + SELECT + json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug) + ORDER BY b.date_finished DESC) + FROM + books_artists ba + LEFT JOIN books b ON ba.books_id = b.id + WHERE + ba.artists_id = ar.id) AS books, +( + SELECT + json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug) + ORDER BY m.year DESC) + FROM + movies_artists ma + LEFT JOIN movies m ON ma.movies_id = m.id + WHERE + ma.artists_id = ar.id) AS movies, +( + SELECT + json_agg(json_build_object('title', s.title, 'year', s.year, 'url', s.slug) + ORDER BY s.year DESC) + FROM + shows_artists sa + LEFT JOIN shows s ON sa.shows_id = s.id + WHERE + sa.artists_id = ar.id) AS shows, +( + SELECT + json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC) + FROM + posts_artists pa + LEFT JOIN posts p ON pa.posts_id = p.id + WHERE + pa.artists_id = ar.id) AS posts, +( + SELECT + json_agg(json_build_object('name', related_ar.name_string, 'url', related_ar.slug, 'country', related_ar.country, 'total_plays', to_char(related_ar.total_plays, 'FM999,999,999,999')) + ORDER BY related_ar.name_string) + FROM + related_artists ra + LEFT JOIN artists related_ar ON ra.related_artists_id = related_ar.id + WHERE + ra.artists_id = ar.id) AS related_artists +FROM + artists ar + LEFT JOIN directus_files df ON ar.art = df.id + LEFT JOIN genres g ON ar.genres = g.id +GROUP BY + ar.id, + df.filename_disk, + g.name, + g.slug, + g.emoji; + diff --git a/queries/views/media/music/concerts.psql b/queries/views/media/music/concerts.psql new file mode 100644 index 0000000..d1e7301 --- /dev/null +++ b/queries/views/media/music/concerts.psql @@ -0,0 +1,19 @@ +CREATE OR REPLACE VIEW optimized_concerts AS +SELECT + c.id, + c.date, + c.notes, + CASE WHEN c.artist IS NOT NULL THEN + json_build_object('name', a.name_string, 'url', a.slug) + ELSE + json_build_object('name', c.artist_name_string, 'url', NULL) + END AS artist, + json_build_object('name', v.name, 'name_short', trim(split_part(v.name, ',', 1)), 'latitude', v.latitude, 'longitude', v.longitude, 'notes', v.notes) AS venue, + c.notes AS concert_notes +FROM + concerts c + LEFT JOIN artists a ON c.artist = a.id + LEFT JOIN venues v ON c.venue = v.id +ORDER BY + c.date DESC; + diff --git a/queries/views/media/music/genres.psql b/queries/views/media/music/genres.psql new file mode 100644 index 0000000..e841dd3 --- /dev/null +++ b/queries/views/media/music/genres.psql @@ -0,0 +1,49 @@ +CREATE OR REPLACE VIEW optimized_genres AS +SELECT + g.id, + g.name, + g.description, + g.emoji, + to_char(g.total_plays, 'FM999,999,999,999') AS total_plays, + g.wiki_link, + g.slug AS url, +( + SELECT + json_agg(json_build_object('name', a.name_string, 'url', a.slug, 'image', CONCAT('/', df_artist.filename_disk), 'total_plays', to_char(a.total_plays, 'FM999,999,999,999')) + ORDER BY a.total_plays DESC) + FROM + artists a + LEFT JOIN directus_files df_artist ON a.art = df_artist.id + WHERE + a.genres = g.id) AS artists, +( + SELECT + json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug)) + FROM + books b + JOIN genres_books gb ON gb.books_id = b.id + WHERE + gb.genres_id = g.id) AS books, +( + SELECT + json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug) + ORDER BY m.year DESC) + FROM + movies m + JOIN genres_movies gm ON gm.movies_id = m.id + WHERE + gm.genres_id = g.id) AS movies, +( + SELECT + json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC) + FROM + posts_genres pg + LEFT JOIN posts p ON pg.posts_id = p.id + WHERE + pg.genres_id = g.id) AS posts + FROM + genres g + ORDER BY + g.id ASC; + diff --git a/queries/views/media/music/listens.psql b/queries/views/media/music/listens.psql new file mode 100644 index 0000000..fe981a6 --- /dev/null +++ b/queries/views/media/music/listens.psql @@ -0,0 +1,28 @@ +CREATE OR REPLACE VIEW optimized_listens AS SELECT DISTINCT ON (l.id, l.listened_at, l.track_name, l.artist_name, l.album_name) + l.id, + l.listened_at, + l.track_name, + l.artist_name, + l.album_name, + l.album_key, + CONCAT('/', df_art.filename_disk) AS artist_art, + a.genres AS artist_genres, + g.name AS genre_name, + g.slug AS genre_url, + a.country AS artist_country, + a.slug AS artist_url, + CONCAT('/', df_album.filename_disk) AS album_art +FROM + listens l + LEFT JOIN artists a ON (l.artist_name = a.name_string) + LEFT JOIN albums al ON (l.album_key = al.key) + LEFT JOIN directus_files df_art ON (a.art = df_art.id) + LEFT JOIN directus_files df_album ON (al.art = df_album.id) + LEFT JOIN genres g ON (a.genres = g.id) +ORDER BY + l.id, + l.listened_at, + l.track_name, + l.artist_name, + l.album_name; + diff --git a/queries/views/media/music/month/albums.psql b/queries/views/media/music/month/albums.psql new file mode 100644 index 0000000..c818b9e --- /dev/null +++ b/queries/views/media/music/month/albums.psql @@ -0,0 +1,20 @@ +CREATE OR REPLACE VIEW month_albums AS +SELECT + ol.album_name, + ol.artist_name, + COUNT(*) AS plays, + ol.album_art, + ol.artist_url, + json_build_object('title', ol.album_name, 'image', ol.album_art, 'url', ol.artist_url, 'alt', CONCAT(ol.album_name, ' by ', ol.artist_name), 'subtext', ol.artist_name) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '30 days' +GROUP BY + ol.album_name, + ol.artist_name, + ol.album_art, + ol.artist_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/month/artists.psql b/queries/views/media/music/month/artists.psql new file mode 100644 index 0000000..27bd349 --- /dev/null +++ b/queries/views/media/music/month/artists.psql @@ -0,0 +1,19 @@ +CREATE OR REPLACE VIEW month_artists AS +SELECT + ol.artist_name, + COUNT(*) AS plays, + ol.artist_art, + ol.artist_url, + ARRAY_AGG(DISTINCT ol.genre_name) AS genres, + json_build_object('title', ol.artist_name, 'image', ol.artist_art, 'url', ol.artist_url, 'alt', CONCAT(COUNT(*), ' plays of ', ol.artist_name), 'subtext', CONCAT(COUNT(*), ' plays')) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '30 days' +GROUP BY + ol.artist_name, + ol.artist_art, + ol.artist_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/month/genres.psql b/queries/views/media/music/month/genres.psql new file mode 100644 index 0000000..ee303ad --- /dev/null +++ b/queries/views/media/music/month/genres.psql @@ -0,0 +1,16 @@ +CREATE OR REPLACE VIEW month_genres AS +SELECT + ol.genre_name, + ol.genre_url, + COUNT(*) AS plays, + json_build_object('alt', ol.genre_name, 'subtext', CONCAT(COUNT(*), ' plays')) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '30 days' +GROUP BY + ol.genre_name, + ol.genre_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/month/tracks.psql b/queries/views/media/music/month/tracks.psql new file mode 100644 index 0000000..d40455d --- /dev/null +++ b/queries/views/media/music/month/tracks.psql @@ -0,0 +1,37 @@ +CREATE OR REPLACE VIEW month_tracks AS +WITH track_stats AS ( + SELECT + ol.track_name, + ol.artist_name, + ol.album_name, + COUNT(*) AS plays, + MAX(ol.listened_at) AS last_listened, + ol.album_art, + ol.artist_url, + MAX(COUNT(*)) OVER () AS most_played + FROM + optimized_listens ol + WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '30 days' + GROUP BY + ol.track_name, + ol.artist_name, + ol.album_name, + ol.album_art, + ol.artist_url +) +SELECT + track_name, + artist_name, + album_name, + plays, + last_listened, + album_art, + artist_url, + json_build_object('title', track_name, 'artist', artist_name, 'url', artist_url, 'plays', plays, 'alt', CONCAT(track_name, ' by ', artist_name), 'subtext', CONCAT(album_name, ' (', plays, ' plays)'), 'percentage', ROUND((plays::decimal / most_played) * 100, 2)) AS chart +FROM + track_stats +ORDER BY + plays DESC, + last_listened DESC; + diff --git a/queries/views/media/music/now-playing.psql b/queries/views/media/music/now-playing.psql new file mode 100644 index 0000000..ad662f9 --- /dev/null +++ b/queries/views/media/music/now-playing.psql @@ -0,0 +1,25 @@ +CREATE VIEW optimized_latest_listen AS +WITH latest_listen AS ( + SELECT + l.track_name, + l.artist_name, + a.emoji AS artist_emoji, + g.emoji AS genre_emoji, + a.slug AS url, + ROW_NUMBER() OVER (ORDER BY l.listened_at DESC) AS row_num + FROM + listens l + JOIN artists a ON l.artist_name = a.name_string + LEFT JOIN genres g ON a.genres = g.id +) +SELECT + track_name, + artist_name, + artist_emoji, + genre_emoji, + url +FROM + latest_listen +WHERE + row_num = 1; + diff --git a/queries/views/media/music/recent-tracks.psql b/queries/views/media/music/recent-tracks.psql new file mode 100644 index 0000000..4121b95 --- /dev/null +++ b/queries/views/media/music/recent-tracks.psql @@ -0,0 +1,23 @@ +CREATE OR REPLACE VIEW recent_tracks AS +SELECT + ol.id, + ol.listened_at, + ol.track_name, + ol.artist_name, + ol.album_name, + ol.album_key, + ol.artist_art, + ol.artist_genres, + ol.genre_name, + ol.artist_country, + ol.album_art, + ol.artist_url, + ol.genre_url, + json_build_object('title', ol.track_name, 'subtext', ol.artist_name, 'alt', CONCAT(ol.track_name, ' by ', ol.artist_name), 'url', ol.artist_url, 'image', ol.album_art, 'played_at', ol.listened_at) AS chart +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '7 days' +ORDER BY + TO_TIMESTAMP(ol.listened_at) DESC; + diff --git a/queries/views/media/music/week/albums.psql b/queries/views/media/music/week/albums.psql new file mode 100644 index 0000000..2ecb844 --- /dev/null +++ b/queries/views/media/music/week/albums.psql @@ -0,0 +1,20 @@ +CREATE OR REPLACE VIEW week_albums AS +SELECT + ol.album_name, + ol.artist_name, + COUNT(*) AS plays, + ol.album_art, + ol.artist_url, + json_build_object('title', ol.album_name, 'image', ol.album_art, 'url', ol.artist_url, 'alt', CONCAT(ol.album_name, ' by ', ol.artist_name), 'subtext', ol.artist_name) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '7 days' +GROUP BY + ol.album_name, + ol.artist_name, + ol.album_art, + ol.artist_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/week/artists.psql b/queries/views/media/music/week/artists.psql new file mode 100644 index 0000000..df8f65f --- /dev/null +++ b/queries/views/media/music/week/artists.psql @@ -0,0 +1,19 @@ +CREATE OR REPLACE VIEW week_artists AS +SELECT + ol.artist_name, + COUNT(*) AS plays, + ol.artist_art, + ol.artist_url, + ARRAY_AGG(DISTINCT ol.genre_name) AS genres, + json_build_object('title', ol.artist_name, 'image', ol.artist_art, 'url', ol.artist_url, 'alt', CONCAT(COUNT(*), ' plays of ', ol.artist_name), 'subtext', CONCAT(COUNT(*), ' plays')) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '7 days' +GROUP BY + ol.artist_name, + ol.artist_art, + ol.artist_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/week/genres.psql b/queries/views/media/music/week/genres.psql new file mode 100644 index 0000000..e0b1502 --- /dev/null +++ b/queries/views/media/music/week/genres.psql @@ -0,0 +1,16 @@ +CREATE OR REPLACE VIEW week_genres AS +SELECT + ol.genre_name, + ol.genre_url, + COUNT(*) AS plays, + json_build_object('alt', ol.genre_name, 'subtext', CONCAT(COUNT(*), ' plays')) AS grid +FROM + optimized_listens ol +WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '7 days' +GROUP BY + ol.genre_name, + ol.genre_url +ORDER BY + plays DESC; + diff --git a/queries/views/media/music/week/tracks.psql b/queries/views/media/music/week/tracks.psql new file mode 100644 index 0000000..9d643d8 --- /dev/null +++ b/queries/views/media/music/week/tracks.psql @@ -0,0 +1,37 @@ +CREATE OR REPLACE VIEW week_tracks AS +WITH track_stats AS ( + SELECT + ol.track_name, + ol.artist_name, + ol.album_name, + COUNT(*) AS plays, + MAX(ol.listened_at) AS last_listened, + ol.album_art, + ol.artist_url, + MAX(COUNT(*)) OVER () AS most_played + FROM + optimized_listens ol + WHERE + TO_TIMESTAMP(ol.listened_at) >= NOW() - INTERVAL '7 days' + GROUP BY + ol.track_name, + ol.artist_name, + ol.album_name, + ol.album_art, + ol.artist_url +) +SELECT + track_name, + artist_name, + album_name, + plays, + last_listened, + album_art, + artist_url, + json_build_object('title', track_name, 'artist', artist_name, 'url', artist_url, 'plays', plays, 'alt', CONCAT(track_name, ' by ', artist_name), 'subtext', CONCAT(album_name, ' (', plays, ' plays)'), 'percentage', ROUND((plays::decimal / most_played) * 100, 2)) AS chart +FROM + track_stats +ORDER BY + plays DESC, + last_listened DESC; + diff --git a/queries/views/media/shows.psql b/queries/views/media/shows.psql new file mode 100644 index 0000000..b71c550 --- /dev/null +++ b/queries/views/media/shows.psql @@ -0,0 +1,94 @@ +CREATE OR REPLACE VIEW optimized_shows AS +SELECT + s.id, + s.title, + s.year, + s.collected, + s.favorite, + s.tattoo, + s.description, + s.review, + s.slug AS url, + CONCAT('/', df_art.filename_disk) AS image, + CONCAT('/', df_backdrop.filename_disk) AS backdrop, + json_build_object('title', s.title, 'image', CONCAT('/', df_art.filename_disk), 'backdrop', CONCAT('/', df_backdrop.filename_disk), 'url', s.slug, 'alt', CONCAT('Poster from ', s.title, ' (', s.year, ')'), 'subtext', COALESCE(( + SELECT + CASE WHEN e1.last_watched_at >= NOW() - INTERVAL '90 days' THEN + CONCAT('S', e1.season_number, 'E', e1.episode_number) + ELSE + CONCAT('(', s.year::text, ')') + END FROM episodes e1 + WHERE + e1.show = s.id ORDER BY e1.last_watched_at DESC, e1.season_number DESC, e1.episode_number DESC LIMIT 1), CONCAT('(', s.year::text, ')'))) AS grid, + json_build_object('title', s.title, 'year', s.year, 'url', s.slug, 'image', CONCAT('/', df_art.filename_disk), 'backdrop', CONCAT('/', df_backdrop.filename_disk), 'formatted_episode', COALESCE(( + SELECT + CONCAT('S', e2.season_number, 'E', e2.episode_number) + FROM episodes e2 + WHERE + e2.show = s.id ORDER BY e2.season_number DESC, e2.episode_number DESC LIMIT 1)), 'last_watched_at', MAX(e.last_watched_at)) AS episode, +( + SELECT + json_agg(json_build_object('title', m.title, 'year', m.year, 'url', m.slug) + ORDER BY m.year DESC) + FROM + shows_movies sm + LEFT JOIN movies m ON sm.movies_id = m.id + WHERE + sm.shows_id = s.id) AS movies, +( + SELECT + json_agg(json_build_object('title', b.title, 'author', b.author, 'url', b.slug) + ORDER BY b.title) + FROM + shows_books sb + LEFT JOIN books b ON sb.books_id = b.id + WHERE + sb.shows_id = s.id) AS books, +( + SELECT + json_agg(json_build_object('title', p.title, 'date', p.date, 'url', p.slug) + ORDER BY p.date DESC) + FROM + posts_shows ps + LEFT JOIN posts p ON ps.posts_id = p.id + WHERE + ps.shows_id = s.id) AS posts, +( + SELECT + array_agg(t.name) + FROM + shows_tags st + LEFT JOIN tags t ON st.tags_id = t.id + WHERE + st.shows_id = s.id) AS tags, +( + SELECT + json_agg(json_build_object('title', rs.title, 'year', rs.year, 'url', rs.slug) + ORDER BY rs.year DESC) + FROM + related_shows sr + LEFT JOIN shows rs ON sr.related_shows_id = rs.id + WHERE + sr.shows_id = s.id) AS related_shows, +( + SELECT + json_agg(json_build_object('name', a.name_string, 'url', a.slug, 'country', a.country, 'total_plays', a.total_plays) + ORDER BY a.name_string) + FROM + shows_artists sa + LEFT JOIN artists a ON sa.artists_id = a.id + WHERE + sa.shows_id = s.id) AS artists, + MAX(e.last_watched_at) AS last_watched_at +FROM + shows s + LEFT JOIN episodes e ON s.id = e.show + LEFT JOIN directus_files df_art ON s.art = df_art.id + LEFT JOIN directus_files df_backdrop ON s.backdrop = df_backdrop.id +GROUP BY + s.id, + df_art.filename_disk, + df_backdrop.filename_disk +ORDER BY + MAX(e.last_watched_at) DESC; + diff --git a/scripts/worker-build.mjs b/scripts/worker-build.mjs new file mode 100644 index 0000000..bf9f438 --- /dev/null +++ b/scripts/worker-build.mjs @@ -0,0 +1,33 @@ +import fs from 'fs/promises' +import dotenv from 'dotenv-flow' + +dotenv.config() + +const workerName = process.argv[2] + +if (!workerName) { + console.error('Please specify a worker name.') + process.exit(1) +} + +const templatePath = `workers/${workerName}/wrangler.template.toml` +const outputPath = `workers/${workerName}/wrangler.toml` + +async function generateToml() { + try { + const template = await fs.readFile(templatePath, 'utf8') + const output = template + .replace(/\${CF_ACCOUNT_ID}/g, process.env.CF_ACCOUNT_ID) + .replace(/\${CF_ZONE_ID}/g, process.env.CF_ZONE_ID) + .replace(/\${RSS_TO_MASTODON_KV_NAMESPACE_ID}/g, process.env.RSS_TO_MASTODON_KV_NAMESPACE_ID) + + await fs.writeFile(outputPath, output) + + console.log(`Generated wrangler.toml for ${workerName}`) + } catch (error) { + console.error('Error generating wrangler.toml:', error) + process.exit(1) + } +} + +generateToml() \ No newline at end of file diff --git a/src/components/BlockRenderer.astro b/src/components/BlockRenderer.astro new file mode 100644 index 0000000..17e391d --- /dev/null +++ b/src/components/BlockRenderer.astro @@ -0,0 +1,35 @@ +--- +import AssociatedMedia from '@components/blocks//AssociatedMedia.astro'; +import GitHub from '@components/blocks/banners/GitHub.astro'; +import Hero from '@components/blocks//Hero.astro'; +import Modal from '@components/blocks//Modal.astro'; +import YouTubePlayer from '@components/blocks//YouTubePlayer.astro'; +import { md } from '@utils/helpers.js'; + +const { block } = Astro.props; +const htmlContent = block.type === 'markdown' ? md(block.text) : ''; +--- + +{block.type === 'youtube_player' && ( + +)} + +{block.type === 'hero' && ( + +)} + +{block.type === 'markdown' && ( +
    +)} + +{block.type === 'modal' && ( + +)} + +{block.type === 'associated_media' && ( + +)} + +{block.type === 'github_banner' && ( + +)} \ No newline at end of file diff --git a/src/components/Footer.astro b/src/components/Footer.astro new file mode 100644 index 0000000..13f4c49 --- /dev/null +++ b/src/components/Footer.astro @@ -0,0 +1,34 @@ +--- +import NavLink from './nav/NavLink.astro'; + +const { nav, updated } = Astro.props; +--- + +
    + {updated && ( +

    + This page was last updated on {new Date(updated).toLocaleDateString()} +

    + )} + + +
    diff --git a/src/components/Header.astro b/src/components/Header.astro new file mode 100644 index 0000000..7ed6a85 --- /dev/null +++ b/src/components/Header.astro @@ -0,0 +1,17 @@ +--- +import Menu from './nav/Menu.astro'; + +const { nav, siteName, url } = Astro.props; +const isHomePage = url === '/'; +--- + +
    +

    + {isHomePage ? ( + siteName + ) : ( + {siteName} + )} +

    + +
    \ No newline at end of file diff --git a/src/components/IconMapper.astro b/src/components/IconMapper.astro new file mode 100644 index 0000000..d0a39f2 --- /dev/null +++ b/src/components/IconMapper.astro @@ -0,0 +1,43 @@ +--- +import { + IconArticle, + IconHeadphones, + IconDeviceTvOld, + IconBooks, + IconLink, + IconInfoCircle, + IconSearch, + IconRss, + IconBrandMastodon, + IconMail, + IconBrandGithub, + IconBrandNpm, + IconCoffee, + IconDeviceWatch, + IconHeartHandshake, +} from '@tabler/icons-react'; + +const { icon } = Astro.props; + +const iconComponents = { + article: IconArticle, + headphones: IconHeadphones, + 'device-tv-old': IconDeviceTvOld, + books: IconBooks, + link: IconLink, + 'info-circle': IconInfoCircle, + search: IconSearch, + rss: IconRss, + 'brand-mastodon': IconBrandMastodon, + mail: IconMail, + 'brand-github': IconBrandGithub, + 'brand-npm': IconBrandNpm, + coffee: IconCoffee, + 'device-watch': IconDeviceWatch, + 'heart-handshake': IconHeartHandshake, +}; + +const SelectedIcon = iconComponents[icon?.toLowerCase()] || null; +--- + +{SelectedIcon ? : null} \ No newline at end of file diff --git a/src/components/Intro.astro b/src/components/Intro.astro new file mode 100644 index 0000000..e3331df --- /dev/null +++ b/src/components/Intro.astro @@ -0,0 +1,10 @@ +--- +import NowPlaying from "@components/blocks/NowPlaying.astro"; + +const { intro } = Astro.props; +--- + +
    +
    +

    +
    diff --git a/src/components/RecentActivity.astro b/src/components/RecentActivity.astro new file mode 100644 index 0000000..0027473 --- /dev/null +++ b/src/components/RecentActivity.astro @@ -0,0 +1,43 @@ +--- +import { fetchMusicData } from '@utils/data/music.js'; +import { fetchShows } from '@utils/data/tv.js'; +import { fetchMovies } from '@utils/data/movies.js'; +import { fetchBooks } from '@utils/data/books.js'; +import { fetchLinks } from '@utils/data/links.js'; +import { IconActivity } from '@tabler/icons-react'; + +import Rss from '@components/blocks/banners/Rss.astro'; + +const music = await fetchMusicData(); +const tv = await fetchShows(); +const movies = await fetchMovies(); +const books = await fetchBooks(); +const links = await fetchLinks(); + +const track = music.week?.tracks[0]; +const show = tv.recentlyWatched[0]; +const movie = movies.recentlyWatched[0]; +const book = books.currentYear[0]; +const link = links[0]; +--- + + \ No newline at end of file diff --git a/src/components/RecentPosts.astro b/src/components/RecentPosts.astro new file mode 100644 index 0000000..5b19e0e --- /dev/null +++ b/src/components/RecentPosts.astro @@ -0,0 +1,33 @@ +--- +import { IconClock, IconStar, IconArrowRight } from '@tabler/icons-react'; +import { fetchAllPosts } from '../utils/data/posts.js'; +import { md } from '@utils/helpers.js'; + +const posts = await fetchAllPosts(); +--- + +

    + + Recent posts +

    +{posts.slice(0, 5).map(post => ( +
    + +

    + {post.title} +

    +

    +
    +))} + + View all posts + \ No newline at end of file diff --git a/src/components/blocks/AssociatedMedia.astro b/src/components/blocks/AssociatedMedia.astro new file mode 100644 index 0000000..3f2aef2 --- /dev/null +++ b/src/components/blocks/AssociatedMedia.astro @@ -0,0 +1,110 @@ +--- +const { + artists = [], + books = [], + genres = [], + movies = [], + posts = [], + shows = [], +} = Astro.props; + +const media = [ + ...(artists || []), + ...(books || []), + ...(genres || []), + ...(movies || []), + ...(posts || []), + ...(shows || []), +]; + +if (media.length === 0) return null; + +const sections = [ + { + key: "artists", + icon: "headphones", + cssClass: "music", + label: "Related artist(s)", + items: artists || [], + }, + { + key: "books", + icon: "books", + cssClass: "books", + label: "Related book(s)", + items: books || [], + }, + { + key: "genres", + icon: "headphones", + cssClass: "music", + label: "Related genre(s)", + items: genres || [], + }, + { + key: "movies", + icon: "movie", + cssClass: "movies", + label: "Related movie(s)", + items: movies || [], + }, + { + key: "posts", + icon: "article", + cssClass: "article", + label: "Related post(s)", + items: posts || [], + }, + { + key: "shows", + icon: "device-tv-old", + cssClass: "tv", + label: "Related show(s)", + items: shows || [], + }, +]; +--- + +
    + { + sections.map(({ key, icon, cssClass, label, items }) => { + if (!items.length) return null; + + return ( +
    +

    + {label} +

    +
      + {items.map((item) => ( +
    • + {item.title || item.name} + {key === "artists" && item.total_plays > 0 && ( + + {item.total_plays}{" "} + {item.total_plays === 1 ? "play" : "plays"} + + )} + {key === "books" && by {item.author}} + {(key === "movies" || key === "shows") && ( + ({item.year}) + )} + {key === "posts" && ( + + ( + {new Date(item.date).toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + })} + ) + + )} +
    • + ))} +
    +
    + ); + }) + } +
    diff --git a/src/components/blocks/Hero.astro b/src/components/blocks/Hero.astro new file mode 100644 index 0000000..7f32239 --- /dev/null +++ b/src/components/blocks/Hero.astro @@ -0,0 +1,7 @@ +--- +const { image, alt } = Astro.props; +--- + +
    + {alt} +
    \ No newline at end of file diff --git a/src/components/blocks/MastodonPost.astro b/src/components/blocks/MastodonPost.astro new file mode 100644 index 0000000..06baf3e --- /dev/null +++ b/src/components/blocks/MastodonPost.astro @@ -0,0 +1,7 @@ +--- +const { post } = Astro.props; +--- + +
    +

    {post.content}

    +
    \ No newline at end of file diff --git a/src/components/blocks/Modal.astro b/src/components/blocks/Modal.astro new file mode 100644 index 0000000..882efd5 --- /dev/null +++ b/src/components/blocks/Modal.astro @@ -0,0 +1,8 @@ +--- +const { content } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/blocks/NowPlaying.astro b/src/components/blocks/NowPlaying.astro new file mode 100644 index 0000000..cd629af --- /dev/null +++ b/src/components/blocks/NowPlaying.astro @@ -0,0 +1,24 @@ +--- +import { fetchNowPlaying } from '../../utils/data/nowPlaying.js'; + +const isProduction = import.meta.env.MODE === 'production'; +const nowPlayingData = await fetchNowPlaying(); +--- + + + + +{isProduction && ()} \ No newline at end of file diff --git a/src/components/blocks/YouTubePlayer.astro b/src/components/blocks/YouTubePlayer.astro new file mode 100644 index 0000000..98339c1 --- /dev/null +++ b/src/components/blocks/YouTubePlayer.astro @@ -0,0 +1,10 @@ +--- +const { url } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/blocks/banners/Coffee.astro b/src/components/blocks/banners/Coffee.astro new file mode 100644 index 0000000..b43afd9 --- /dev/null +++ b/src/components/blocks/banners/Coffee.astro @@ -0,0 +1,13 @@ +--- +import { IconCoffee } from "@tabler/icons-react"; +--- + diff --git a/src/components/blocks/banners/Error.astro b/src/components/blocks/banners/Error.astro new file mode 100644 index 0000000..1cb1034 --- /dev/null +++ b/src/components/blocks/banners/Error.astro @@ -0,0 +1,8 @@ +--- +import { IconAlertCircle } from '@tabler/icons-react'; + +const { text } = Astro.props +--- + \ No newline at end of file diff --git a/src/components/blocks/banners/GitHub.astro b/src/components/blocks/banners/GitHub.astro new file mode 100644 index 0000000..d294c77 --- /dev/null +++ b/src/components/blocks/banners/GitHub.astro @@ -0,0 +1,9 @@ +--- +import { IconBrandGithub } from '@tabler/icons-react'; + +const { url } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/blocks/banners/Npm.astro b/src/components/blocks/banners/Npm.astro new file mode 100644 index 0000000..bbde0d3 --- /dev/null +++ b/src/components/blocks/banners/Npm.astro @@ -0,0 +1,12 @@ +--- +import { IconBrandNpm } from '@tabler/icons-react'; + +const { url, command } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/blocks/banners/OldPost.astro b/src/components/blocks/banners/OldPost.astro new file mode 100644 index 0000000..74126ca --- /dev/null +++ b/src/components/blocks/banners/OldPost.astro @@ -0,0 +1,14 @@ +--- +import { IconClockX } from '@tabler/icons-react'; + +const { isOldPost } = Astro.props; +--- + +{isOldPost && ( + +)} \ No newline at end of file diff --git a/src/components/blocks/banners/Rss.astro b/src/components/blocks/banners/Rss.astro new file mode 100644 index 0000000..88ee308 --- /dev/null +++ b/src/components/blocks/banners/Rss.astro @@ -0,0 +1,12 @@ +--- +import { IconRss } from '@tabler/icons-react'; + +const { url, text } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/blocks/banners/Warning.astro b/src/components/blocks/banners/Warning.astro new file mode 100644 index 0000000..f91f433 --- /dev/null +++ b/src/components/blocks/banners/Warning.astro @@ -0,0 +1,12 @@ +--- +import { IconAlertTriangle } from '@tabler/icons-react'; + +const { text } = Astro.props; +--- + + \ No newline at end of file diff --git a/src/components/nav/Menu.astro b/src/components/nav/Menu.astro new file mode 100644 index 0000000..cb64300 --- /dev/null +++ b/src/components/nav/Menu.astro @@ -0,0 +1,30 @@ +--- +import { IconMenu2, IconX } from '@tabler/icons-react'; +import NavLink from './NavLink.astro'; + +const { nav } = Astro.props; +--- + + + + + + + \ No newline at end of file diff --git a/src/components/nav/NavLink.astro b/src/components/nav/NavLink.astro new file mode 100644 index 0000000..abd142c --- /dev/null +++ b/src/components/nav/NavLink.astro @@ -0,0 +1,24 @@ +--- +import IconMapper from '@components/IconMapper.astro'; + +const { url, title, icon } = Astro.props; +const isHttp = url.startsWith('http'); +const isActive = Astro.url.pathname === url; +--- + +{isActive ? ( + + + {title} + +) : ( + + + {title} + +)} \ No newline at end of file diff --git a/src/components/nav/Paginator.astro b/src/components/nav/Paginator.astro new file mode 100644 index 0000000..449ff9f --- /dev/null +++ b/src/components/nav/Paginator.astro @@ -0,0 +1,49 @@ +--- +import { IconArrowLeft, IconArrowRight } from "@tabler/icons-react"; + +const { pagination } = Astro.props; +const { + currentPage, + totalPages, + hasPrevious, + hasNext, + previousPage, + nextPage, + pages, +} = pagination; +--- + + diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..9bc5cb4 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro new file mode 100644 index 0000000..d7fe958 --- /dev/null +++ b/src/layouts/Layout.astro @@ -0,0 +1,96 @@ +--- +import "@styles/index.css"; +import Header from "../components/Header.astro"; +import Footer from "../components/Footer.astro"; +import { fetchNavigation } from "../utils/data/nav.js"; + +const currentUrl = Astro.url.pathname; +const nav = await fetchNavigation(); +const { globals, pageTitle, description, ogImage, fullUrl, schema } = + Astro.props; +const isProduction = import.meta.env.MODE === "production"; +--- + + + + + + + + {globals.site_name} + + + + + + + + + + + + + { + isProduction && ( + <> + + + ) + } + + + + +
    +
    +
    +
    + +
    +
    +
    +
    + + diff --git a/src/pages/[permalink].astro b/src/pages/[permalink].astro new file mode 100644 index 0000000..2378f13 --- /dev/null +++ b/src/pages/[permalink].astro @@ -0,0 +1,33 @@ +--- +import Layout from '@layouts/Layout.astro'; +import BlockRenderer from '@components/BlockRenderer.astro'; +import { fetchGlobals } from '@utils/data/globals.js'; +import { fetchPages } from '@utils/data/pages'; + +export const prerender = true; + +export async function getStaticPaths() { + const pages = await fetchPages(); + return pages.map((page) => ({ + params: { permalink: page.permalink }, + props: { page }, + })); +} + +const globals = await fetchGlobals(); +const { page } = Astro.props; +const currentUrl = Astro.url.pathname; +--- + + + {page.blocks.map((block) => ( + + ))} + diff --git a/src/pages/feeds/syndication.xml.js b/src/pages/feeds/syndication.xml.js new file mode 100644 index 0000000..2d704bc --- /dev/null +++ b/src/pages/feeds/syndication.xml.js @@ -0,0 +1,64 @@ +import fetchSyndication from '../../utils/data/syndication.js'; +import { fetchGlobals } from '../../utils/data/globals.js'; + +export async function GET() { + const globals = await fetchGlobals(); + const entries = await fetchSyndication(); + + if (!entries.length) return new Response('No feed entries found.', { status: 404 }); + + const title = globals.site_name || 'Syndicated content / Cory Dransfeldt'; + const permalink = '/feeds/syndication.xml'; + + const xml = ` + + + + <![CDATA[${title}]]> + + ${globals.url}${permalink} + ${new Date().toUTCString()} + + <![CDATA[${title}]]> + ${globals.url}${permalink} + ${globals.cdn_url}${globals.avatar}?class=w200 + 144 + 144 + + ${entries + .slice(0, 20) + .map( + (entry) => ` + + <![CDATA[${entry.syndication.title}]]> + ${encodeAmp(entry.syndication.url)} + ${new Date(entry.syndication.date).toUTCString()} + ${encodeAmp(entry.syndication.url)} + + ` + ) + .join('')} + +`; + + return new Response(xml, { + status: 200, + headers: { + 'Content-Type': 'application/rss+xml', + }, + }); +} + +function encodeAmp(url) { + return url.replace(/&/g, '&'); +} + +function escapeHTML(str) { + if (!str) return ''; + return str + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 0000000..d8a2a25 --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,29 @@ +--- +import Layout from '../layouts/Layout.astro'; +import Intro from '../components/Intro.astro'; +import { fetchGlobals } from '../utils/data/globals'; +import RecentActivity from '../components/RecentActivity.astro'; +import RecentPosts from '../components/RecentPosts.astro'; + +const globals = await fetchGlobals(); +const schema = 'blog'; +const pageTitle = globals.site_name; +const description = 'This is a blog post description'; +const ogImage = globals.cdn_url + globals.avatar; +const fullUrl = globals.url + '/blog/my-post'; +const themeColor = globals.theme_color; +--- + + + + + \ No newline at end of file diff --git a/src/pages/posts/[...page].astro b/src/pages/posts/[...page].astro new file mode 100644 index 0000000..d38eb4b --- /dev/null +++ b/src/pages/posts/[...page].astro @@ -0,0 +1,59 @@ +--- +import { getCollection } from 'astro:content'; +import { IconStar } from '@tabler/icons-react'; +import { fetchGlobals } from "@data/globals.js"; +import { fetchAllPosts } from "@data/posts.js"; +import Layout from "@layouts/Layout.astro"; +import Paginator from '@components/nav/Paginator.astro'; +import { md } from '@utils/helpers.js'; +import { DateTime } from 'luxon'; + +const globals = await fetchGlobals(); +const posts = await fetchAllPosts(); +const { page } = Astro.props; +const currentUrl = Astro.url.pathname; + +const currentPage = Astro.params.page ? parseInt(Astro.params.page, 10) : 1; +const pageSize = 15; +const totalPosts = posts.length; +const totalPages = Math.ceil(totalPosts / pageSize); +const start = (currentPage - 1) * pageSize; +const end = start + pageSize; +const paginatedPosts = posts.slice(start, end); + +const pagination = { + currentPage, + totalPages, + hasPrevious: currentPage > 1, + hasNext: currentPage < totalPages, + previousPage: currentPage > 1 ? `/posts/${currentPage - 1}` : null, + nextPage: currentPage < totalPages ? `/posts/${currentPage + 1}` : null, + pages: Array.from({ length: totalPages }, (_, i) => ({ + number: i + 1, + href: `/posts/${i + 1}`, + })), +}; +--- + + + {paginatedPosts.map((post) => ( +
    + +

    + {post.title} +

    +

    +
    + ))} + + +
    \ No newline at end of file diff --git a/src/pages/posts/[year]/[title].astro b/src/pages/posts/[year]/[title].astro new file mode 100644 index 0000000..78a0c56 --- /dev/null +++ b/src/pages/posts/[year]/[title].astro @@ -0,0 +1,102 @@ +--- +import { IconStar } from "@tabler/icons-react"; +import { fetchAllPosts } from "@data/posts.js"; +import { fetchGlobals } from "@data/globals.js"; +import { md } from '@utils/helpers.js'; +import OldPost from "@components/blocks/banners/OldPost.astro"; +import BlockRenderer from "@components/BlockRenderer.astro"; +import AssociatedMedia from "@components/blocks/AssociatedMedia.astro"; +import MastodonPost from "@components/blocks/MastodonPost.astro"; +import Layout from "@layouts/Layout.astro"; +import Coffee from "@components/blocks/banners/Coffee.astro"; + +export const prerender = true; + +export async function getStaticPaths() { + const posts = await fetchAllPosts(); + + return posts.map((post) => { + const match = post.url.match(/^\/posts\/(\d{4})\/(.+)$/); + if (!match) throw new Error(`Invalid post URL: ${post.url}`); + + const [, year, title] = match; + + return { + params: { year, title }, + props: { post }, + }; + }); +} + +const { post } = Astro.props; +const { year, title } = Astro.params; +const globals = await fetchGlobals(); +const currentUrl = Astro.url.pathname; +const htmlContent = md(post.content); +--- + + +
    + +

    {post.title}

    +
    + {post.old_post && } + { + post.image && ( + {post.image_alt?.replace(/['"]/g, + ) + } +
    + { + post.blocks && + post.blocks.map((block) => ) + } + + + +
    +
    +
    diff --git a/src/pages/robots.txt.js b/src/pages/robots.txt.js new file mode 100644 index 0000000..fbc6036 --- /dev/null +++ b/src/pages/robots.txt.js @@ -0,0 +1,26 @@ +import { fetchAllRobots } from '../utils//data/robots.js'; + +export async function GET() { + try { + const robots = await fetchAllRobots(); + + const sitemap = `Sitemap: https://coryd.dev/sitemap.xml\n\n`; + const allowAll = `User-agent: *\nDisallow:\n\n`; + const disallowedBots = robots + .map((userAgent) => `User-agent: ${userAgent}`) + .join('\n'); + const disallowAll = `\nDisallow: /`; + + const robotsTxt = `${sitemap}${allowAll}${disallowedBots}${disallowAll}`; + + return new Response(robotsTxt, { + status: 200, + headers: { + 'Content-Type': 'text/plain', + }, + }); + } catch (error) { + console.error('Error generating robots.txt:', error); + return new Response('Error generating robots.txt', { status: 500 }); + } +} \ No newline at end of file diff --git a/src/styles/base/fonts.css b/src/styles/base/fonts.css new file mode 100644 index 0000000..391a80c --- /dev/null +++ b/src/styles/base/fonts.css @@ -0,0 +1,31 @@ +@font-face { + font-family: MonoLisa; + src: url("/fonts/ml.woff2") format("woff2"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: MonoLisa; + src: url("/fonts/mlb.woff2") format("woff2"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: MonoLisa; + src: url("/fonts/mli.woff2") format("woff2"); + font-weight: 400; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: MonoLisa; + src: url("/fonts/mlbi.woff2") format("woff2"); + font-weight: 700; + font-style: italic; + font-display: swap; +} diff --git a/src/styles/base/index.css b/src/styles/base/index.css new file mode 100644 index 0000000..adf2221 --- /dev/null +++ b/src/styles/base/index.css @@ -0,0 +1,487 @@ +html, +body { + font-family: var(--font-mono); + color: var(--text-color); + background: var(--background-color); +} + +html { + scrollbar-color: var(--accent-color) var(--gray-light); +} + +::-webkit-scrollbar { + width: var(--sizing-md); +} + +::-webkit-scrollbar-track { + background: var(--gray-light); +} + +::-webkit-scrollbar-thumb { + background: var(--accent-color); + border-radius: var(--border-radius-full); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--accent-color-hover); +} + +::selection { + color: var(--color-lightest); + background: var(--accent-color); +} + +p { + margin: var(--margin-vertical-base-horizontal-zero); +} + +.highlight-text { + color: var(--text-color-inverted); + background-color: var(--accent-color); + padding: var(--spacing-xs); + border-radius: var(--border-radius-slight); +} + +details > summary { + display: inline; +} + +blockquote { + font-size: var(--font-size-lg); + color: var(--gray-dark); + padding-left: var(--spacing-lg); + border-left: var(--sizing-xs) solid var(--gray-dark); + margin: var(--margin-vertical-base-horizontal-zero); +} + +:is(h1, h2, h3) svg { + stroke-width: var(--stroke-width-bold); +} + +strong, +blockquote { + font-weight: var(--font-weight-bold); +} + +em, +blockquote { + font-style: italic; +} + +svg { + width: var(--sizing-svg-base); + height: var(--sizing-svg-base); + stroke-width: var(--stroke-width-default); +} + +/* images */ +img { + border-radius: var(--border-radius-slight); + + &.image-banner { + border: var(--border-default); + height: auto; + width: 100%; + margin: var(--margin-vertical-base-horizontal-zero); + } +} + +/* lists */ +ul, +ol { + margin: var(--margin-vertical-base-horizontal-zero); + padding-left: var(--spacing-base); + + & li:not(:last-child) { + margin-bottom: var(--spacing-lg); + } +} + +/* brand + section colors */ +.article, +.books, +.brand-github, +.brand-mastodon, +.brand-npm, +.coffee, +.collected, +.concerts, +.country, +.device-tv-old, +.device-watch, +.favorite, +.headphones, +.heart-handshake, +.info-circle, +.link, +.mail, +.mail-plus, +.movies, +.music, +.rss, +.search, +.tattoo, +.tv { + &.article { + --section-color: var(--article); + } + &.books { + --section-color: var(--books); + } + &.brand-github { + --section-color: var(--brand-github); + } + &.brand-mastodon { + --section-color: var(--brand-mastodon); + } + &.brand-npm { + --section-color: var(--brand-npm); + } + &.coffee { + --section-color: var(--brand-buy-me-a-coffee); + } + &.collected { + --section-color: var(--collected); + } + &.concerts { + --section-color: var(--concerts); + } + &.country { + --section-color: var(--country); + } + &.device-tv-old { + --section-color: var(--tv); + } + &.device-watch { + --section-color: var(--now); + } + &.favorite { + --section-color: var(--favorite); + } + &.headphones { + --section-color: var(--music); + } + &.heart-handshake { + --section-color: var(--webrings); + } + &.info-circle { + --section-color: var(--about); + } + &.link { + --section-color: var(--link); + } + &.mail { + --section-color: var(--brand-fastmail); + } + &.mail-plus { + --section-color: var(--newsletter); + } + &.movies, + &.tv { + --section-color: var(--tv); + } + &.music { + --section-color: var(--music); + } + &.rss { + --section-color: var(--brand-rss); + } + &.search { + --section-color: var(--search); + } + &.tattoo { + --section-color: var(--tattoo); + } + + color: var(--section-color); + + & svg { + stroke: var(--section-color); + } +} + +/* links */ +a { + color: var(--accent-color); + + &.back-link { + margin-bottom: var(--spacing-base); + } + + & > img { + border: var(--border-default); + } + + & svg { + stroke: var(--accent-color); + } + + &:is(:hover, :focus, :active) { + color: var(--accent-color-hover); + transition: color var(--transition-duration-default) + var(--transition-ease-in-out); + + & > img { + border: var(--border-default-hover); + transition: border var(--transition-duration-default) + var(--transition-ease-in-out); + } + + & > svg { + stroke: var(--accent-color-hover); + } + } +} + +:is(h1, h2, h3, a, p:not(.banner p), span, th, td, .post-meta):has(svg) { + display: flex; + align-items: center; + gap: var(--spacing-xs); +} + +/* headers */ +h1, +h2, +h3 { + font-weight: var(--font-weight-bold); + line-height: var(--line-height-md); + margin: var(--margin-vertical-base-horizontal-zero); +} + +h1 { + font-size: var(--font-size-2xl); +} + +h2 { + font-size: var(--font-size-xl); + + &.page-title { + margin-top: 0; + } +} + +h3 { + font-size: var(--font-size-lg); +} + +@media screen and (min-width: 768px) { + h1 { + font-size: var(--font-size-3xl); + } + + h2 { + font-size: var(--font-size-2xl); + } + + h3 { + font-size: var(--font-size-xl); + } +} + +/* dividers */ +hr { + color: var(--gray-light); + margin: var(--margin-vertical-base-horizontal-zero); +} + +/* articles */ +article { + margin-bottom: var(--spacing-base); + + &:not([class], :last-of-type) { + border-bottom: var(--border-gray); + } + + &.intro { + border-bottom: var(--border-gray); + + & p { + margin-top: 0; + } + } + + & h3 { + margin-top: 0; + } + + & .post-meta { + & svg { + stroke: var(--gray-dark); + width: var(--sizing-svg-sm); + height: var(--sizing-svg-sm); + } + + & time { + color: var(--gray-dark); + font-size: var(--font-size-sm); + } + } +} + +sup.footnote-ref { + line-height: var(--line-height-xs); + padding: var(--spacing-xs); +} + +/* tables */ +table { + display: block; + border: var(--border-gray); + border-radius: var(--border-radius-slight); + overflow-x: scroll; + white-space: nowrap; + caption-side: bottom; + overscroll-behavior: none; + margin: var(--margin-vertical-base-horizontal-zero); +} + +table, +th, +td { + border-collapse: collapse; +} + +:is(th, td):not(:first-child, :last-child) { + border-right: var(--border-gray); +} + +th, +tr:not(:last-child) { + border-bottom: var(--border-gray); +} + +th, +td { + padding: var(--spacing-sm); + word-break: break-word; + + &:first-child { + position: sticky; + left: 0; + max-width: 200px; + border-inline-end: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + &::after { + content: ""; + position: absolute; + inset-block-start: 0; + inset-inline-end: 0; + width: 1px; + height: 100%; + background: var(--gray-light); + } + } +} + +th { + font-weight: var(--font-weight-bold); + background-color: var(--gray-lighter); + text-align: left; +} + +td { + min-width: calc(var(--spacing-3xl) * 2); + white-space: nowrap; + overflow: hidden; + + &:first-child { + background: var(--background-color); + width: 100%; + } +} + +td:first-of-type, +:where(thead, tfoot) th:nth-child(2) { + border-inline-start: none; +} + +/* header */ +.main-title { + width: 100%; + padding-top: var(--spacing-3xl); + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + & h1 { + margin: 0; + padding: 0; + white-space: nowrap; + } +} + +/* nav */ +.active, +.active svg { + cursor: not-allowed; + color: var(--accent-color-active); + stroke: var(--accent-color-active); +} + +/* layout */ +.default-wrapper { + padding-top: var(--spacing-2xl); +} + +.main-wrapper { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +main { + flex: 1 1 0%; +} + +main, +footer { + width: 80%; + margin: 0 auto; + + @media screen and (min-width: 768px) { + max-width: 768px; + } +} + +footer { + & .updated { + text-align: center; + font-size: var(--font-size-sm); + margin: var(--spacing-3xl) 0 var(--spacing-lg); + } + + & nav { + &.social, + &.sub-pages { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + } + + &.social { + gap: var(--spacing-md); + margin-bottom: var(--spacing-lg); + width: 100%; + + & .icon > span, + & .active > span { + display: none; + } + + & .active { + display: flex; + } + } + + &.sub-pages { + font-size: var(--font-size-sm); + padding-bottom: var(--spacing-3xl); + gap: var(--sizing-sm); + } + } +} \ No newline at end of file diff --git a/src/styles/base/reset.css b/src/styles/base/reset.css new file mode 100644 index 0000000..93d9bde --- /dev/null +++ b/src/styles/base/reset.css @@ -0,0 +1,131 @@ +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:where([hidden]:not([hidden='until-found'])) { + display: none !important; +} + +:where(html) { + font-size: 100%; + -webkit-text-size-adjust: none; + scrollbar-width: thin; + scrollbar-gutter: stable; + tab-size: 2; +} + +:where(html:has(dialog:modal[open])) { + overflow: clip; +} + +@media (prefers-reduced-motion: no-preference) { + :where(html:focus-within) { + scroll-behavior: smooth; + } +} + +:where(body) { + font-size: var(--font-size-base); + line-height: var(--line-height-base); + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; +} + +:where(button) { + all: unset; +} + +:where(input, button, textarea, select) { + font: inherit; + color: inherit; +} + +:where(textarea) { + resize: vertical; + resize: block; +} + +:where(button, label, select, summary, [role='button'], [role='option']) { + cursor: pointer; +} + +:where(:disabled) { + cursor: not-allowed; +} + +:where(label:has(> input:disabled), label:has(+ input:disabled)) { + cursor: not-allowed; +} + +:where(a) { + color: inherit; + text-underline-offset: var(--spacing-xs); +} + +ul { + list-style-type: disc; +} + +ol { + list-style-type: number; +} + +:where(ul, ol) { + list-style-position: inside; +} + +:where(img, svg, video, canvas, audio, iframe, embed, object) { + display: block; +} + +:where(p, h1, h2, h3) { + overflow-wrap: break-word; +} + +:where(hr) { + border: none; + border-block-start: 1px solid; + border-block-start-color: currentColor; + color: inherit; + block-size: 0; + overflow: visible; +} + +:where(dialog, [popover]) { + border: none; + background: none; + color: inherit; + inset: unset; + max-width: unset; + max-height: unset; +} + +:where(dialog:not([open], [popover]), [popover]:not(:popover-open)) { + display: none !important; +} + +:where(:focus-visible) { + outline: var(--border-default); + outline-offset: 1px; + border-radius: var(--border-radius-slight); + box-shadow: 0 0 0 1px var(--accent-color); +} + +:where(:focus-visible, :target) { + scroll-margin-block: 8vh; +} + +:where(.visually-hidden:not(:focus-within, :active)) { + clip-path: inset(50%) !important; + height: 1px !important; + width: 1px !important; + overflow: hidden !important; + position: absolute !important; + white-space: nowrap !important; + border: 0 !important; + user-select: none !important; +} \ No newline at end of file diff --git a/src/styles/base/vars.css b/src/styles/base/vars.css new file mode 100644 index 0000000..66b5429 --- /dev/null +++ b/src/styles/base/vars.css @@ -0,0 +1,162 @@ +:root { + /* colors */ + --blue-100: #a2c4ff; + --blue-200: #6b9eff; + --blue-300: #4a78ff; + --blue-400: #3364ff; + --blue-500: #2553e6; + --blue-600: #1e42c7; + + --gray-100: #f9fafb; + --gray-200: #eceef1; + --gray-300: #dfe3e8; + --gray-400: #959eae; + --gray-500: #7f899b; + --gray-600: #626d7f; + --gray-700: #545e71; + --gray-800: #4a5365; + --gray-900: #14161a; + + --gray-lighter: light-dark(var(--gray-200), var(--gray-700)); + --gray-light: light-dark(var(--gray-300), var(--gray-600)); + --gray-medium: var(--gray-400); + --gray-dark: light-dark(var(--gray-800), var(--gray-300)); + + /* base theme */ + --color-lightest: var(--gray-100); + --color-darkest: var(--gray-900); + --text-color: light-dark(var(--color-darkest), var(--color-lightest)); + --background-color: light-dark(var(--color-lightest), var(--color-darkest)); + --text-color-inverted: light-dark( + var(--color-lightest), + var(--color-darkest) + ); + --background-color-inverted: light-dark( + var(--color-darkest), + var(--color-lightest) + ); + --accent-color: light-dark(var(--blue-400), var(--blue-200)); + --accent-color-hover: light-dark(var(--blue-600), var(--blue-100)); + --accent-color-active: light-dark(var(--blue-600), var(--blue-100)); + + --brand-buy-me-a-coffee: light-dark(#0d0c22, #ffdd00); + --brand-github: light-dark(#333, #f5f5f5); + --brand-fastmail: light-dark(#0067b9, #ffc107); + --brand-mastodon: light-dark(#563acc, #858afa); + --brand-npm: #cb3837; + --brand-rss: #f26522; + + --article: light-dark(#007272, #00ffff); + --about: light-dark(#e4513a, #ff967d); + --books: light-dark(#1a7b1a, #6fff6f); + --collected: light-dark(#9a501a, #ffae73); + --concerts: light-dark(#cb426e, #ff82aa); + --country: light-dark(#146a67, #80dcdc); + --error: light-dark(#b81f1f, #ff8b8b); + --favorite: light-dark(#b03c72, #ff9ccd); + --link: light-dark(#7b5cba, #e2b8ff); + --music: light-dark(#3d7099, #76b8cc); + --newsletter: light-dark(#37b0b0, #91fffa); + --now: light-dark(#cc1076, #ff82d5); + --search: light-dark(#6b5e3a, #c0b594); + --tattoo: light-dark(#951b1b, #ff7373); + --tv: light-dark(#cc3600, #ff8f66); + --warning: light-dark(#cc6f00, #ffbf66); + --webrings: light-dark(#b054b0, #ffb3ff); + + /* borders */ + --border-default: 1px solid var(--accent-color); + --border-default-hover: 1px solid var(--accent-color-hover); + --border-gray: 1px solid var(--gray-light); + + /* fonts */ + --font-mono: MonoLisa, Menlo, Consolas, Monaco, Liberation Mono, + Lucida Console, ui-monospace, monospace; + + /* text */ + --font-size-xs: 0.7rem; + --font-size-sm: 0.85rem; + --font-size-base: 1rem; + --font-size-lg: 1.15rem; + --font-size-xl: 1.3rem; + --font-size-2xl: 1.45rem; + --font-size-3xl: 1.6rem; + + --font-weight-base: 400; + --font-weight-bold: 700; + + --line-height-sm: 1; + --line-height-md: 1.5; + --line-height-base: 2; + + /* sizing */ + --sizing-xs: 0.25rem; + --sizing-sm: 0.5rem; + --sizing-md: 0.75rem; + --sizing-lg: 1rem; + --sizing-base: 1.5rem; + --sizing-xl: 1.75rem; + --sizing-2xl: 2rem; + --sizing-3xl: 2.25rem; + + --sizing-svg-sm: 18px; + --sizing-svg-base: 24px; + + /* spacing */ + --spacing-xs: var(--sizing-xs); + --spacing-sm: var(--sizing-sm); + --spacing-md: var(--sizing-md); + --spacing-lg: var(--sizing-lg); + --spacing-base: var(--sizing-base); + --spacing-xl: var(--sizing-xl); + --spacing-2xl: var(--sizing-2xl); + --spacing-3xl: var(--sizing-3xl); + + --margin-vertical-base-horizontal-zero: var(--spacing-base) 0; + + /* radii */ + --border-radius-slight: var(--sizing-xs); + --border-radius-full: 9999px; + + /* aspect ratios */ + --aspect-ratio-square: 1/1; + --aspect-ratio-vertical: 2/3; + --aspect-ratio-banner: 3/2; + + /* grid columns */ + --grid-columns-one: repeat(1, minmax(0, 1fr)); + --grid-columns-two: repeat(2, minmax(0, 1fr)); + --grid-columns-three: repeat(3, minmax(0, 1fr)); + --grid-columns-four: repeat(4, minmax(0, 1fr)); + --grid-columns-six: repeat(6, minmax(0, 1fr)); + + --grid-poster: var(--grid-columns-two); + --grid-square: var(--grid-columns-two); + --grid-vertical: var(--grid-columns-three); + + @media screen and (min-width: 768px) { + --grid-poster: var(--grid-columns-three); + --grid-square: var(--grid-columns-four); + --grid-vertical: var(--grid-columns-six); + } + + /* transitions */ + --transition-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); + --transition-duration-default: 300ms; + + /* svgs */ + --stroke-width-default: 1.4; + --stroke-width-bold: 2; + --inline-margin-bottom: -5px; + + /* shadows */ + --box-shadow-media: inset 0 -85px 60px -40px var(--color-darkest); + --box-shadow-text-toggle: inset 0 -120px 60px -60px var(--background-color); + --text-shadow-default: rgba(0, 0, 0, 0.7) 0px 0px 10px; + + /* modals */ + --modal-overlay-background: light-dark(#ffffffbf, #000000bf); + + /* input accent color */ + accent-color: var(--accent-color); +} \ No newline at end of file diff --git a/src/styles/components/addon-links.css b/src/styles/components/addon-links.css new file mode 100644 index 0000000..24b32d3 --- /dev/null +++ b/src/styles/components/addon-links.css @@ -0,0 +1,14 @@ +.addon-links { + display: grid; + gap: var(--sizing-base); + grid-template-columns: var(--grid-columns-one); + + @media screen and (min-width: 768px) { + grid-template-columns: var(--grid-columns-two); + } + + & article { + border-bottom: 0; + margin-bottom: 0; + } +} diff --git a/src/styles/components/badge-grid.css b/src/styles/components/badge-grid.css new file mode 100644 index 0000000..6cb671e --- /dev/null +++ b/src/styles/components/badge-grid.css @@ -0,0 +1,20 @@ +.badge-grid { + display: grid; + gap: var(--spacing-md); + grid-template-columns: var(--grid-columns-three); + + @media screen and (min-width: 768px) { + grid-template-columns: var(--grid-columns-four); + } + + & > a { + display: flex; + justify-content: center; + } + + & img { + image-rendering: pixelated; + border: none; + border-radius: 0; + } +} diff --git a/src/styles/components/banners.css b/src/styles/components/banners.css new file mode 100644 index 0000000..117ae9b --- /dev/null +++ b/src/styles/components/banners.css @@ -0,0 +1,63 @@ +.banner { + padding: var(--spacing-md); + margin: var(--margin-vertical-base-horizontal-zero); + border: 1px solid; + border-radius: var(--border-radius-slight); + + & p { + font-size: var(--font-size-sm); + color: var(--text-color); + margin: 0; + + a { + color: var(--text-color); + } + + & svg { + display: inline; + vertical-align: middle; + height: var(--sizing-lg); + width: var(--sizing-lg); + } + } + + &.coffee, + &.error, + &.github, + &.npm, + &.old-post, + &.rss, + &.warning { + &.coffee { + --banner-accent-color: var(--brand-buy-me-a-coffee); + } + &.error { + --banner-accent-color: var(--error); + } + &.github { + --banner-accent-color: var(--brand-github); + } + &.npm { + --banner-accent-color: var(--brand-npm); + } + &.old-post { + --banner-accent-color: var(--gray-dark); + } + &.rss { + --banner-accent-color: var(--brand-rss); + } + &.warning { + --banner-accent-color: var(--warning); + } + + border-color: var(--banner-accent-color); + + & p a:is(:hover, :active, :focus) { + color: var(--banner-accent-color); + } + + & svg { + stroke: var(--banner-accent-color); + } + } +} diff --git a/src/styles/components/buttons.css b/src/styles/components/buttons.css new file mode 100644 index 0000000..5a30827 --- /dev/null +++ b/src/styles/components/buttons.css @@ -0,0 +1,28 @@ +@import url("./tab-buttons.css"); +@import url("./text-toggle.css"); + +button, +.button { + appearance: none; + border: none; + border: 2px solid var(--accent-color); + border-radius: var(--border-radius-full); + padding: var(--spacing-xs) var(--spacing-md); + font-size: var(--font-size-base); + font-weight: var(--font-weight-bold); + line-height: var(--line-height-base); + white-space: nowrap; + color: var(--text-color-inverted); + background-color: var(--accent-color); + transition: color var(--transition-duration-default) + var(--transition-ease-in-out); + + &:not(.active):is(:hover, :active, :focus, :focus-within) { + background-color: var(--accent-color-hover); + border: 2px solid var(--accent-color-hover); + transition: background-color var(--transition-duration-default) + var(--transition-ease-in-out), + border var(--transition-duration-default) var(--transition-ease-in-out), + color var(--transition-duration-default) var(--transition-ease-in-out); + } +} diff --git a/src/styles/components/forms.css b/src/styles/components/forms.css new file mode 100644 index 0000000..2cc8da2 --- /dev/null +++ b/src/styles/components/forms.css @@ -0,0 +1,65 @@ +::placeholder { + color: var(--text-color); + opacity: 0.5; +} + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]), +textarea { + width: 100%; +} + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]), +textarea, +select { + color: var(--text-color); + border-radius: var(--border-radius-slight); + background-color: var(--background-color); + padding: var(--spacing-sm); + border: var(--border-gray); +} + +form, +input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]), +textarea { + margin-bottom: var(--spacing-base); +} + +textarea { + resize: vertical; +} + +.search__form { + margin-top: 0; + + & .search__form--input::-webkit-search-cancel-button { + cursor: pointer; + } +} + +.search__form--type { + display: flex; + gap: var(--spacing-md); + margin-top: var(--sizing-md); + border: none; + + @media screen and (max-width: 768px) { + flex-direction: column; + gap: var(--spacing-xs); + } +} + +.search__results { + margin: 0 0 var(--spacing-base); + padding: 0; + list-style: none; + display: none; + + & li { + margin: var(--spacing-sm) 0; + + &:not(:last-child) { + margin-bottom: var(--sizing-base); + border-bottom: var(--border-gray); + } + } +} diff --git a/src/styles/components/mastodon-post.css b/src/styles/components/mastodon-post.css new file mode 100644 index 0000000..d6f794f --- /dev/null +++ b/src/styles/components/mastodon-post.css @@ -0,0 +1,22 @@ +mastodon-post { + width: 100%; + + .mastodon-post-wrapper { + & dl, + & dt { + display: flex; + } + + & dl { + align-items: center; + + & dd { + margin-left: var(--spacing-xs); + + &:not(:last-child) { + margin-right: var(--spacing-lg); + } + } + } + } +} diff --git a/src/styles/components/media-grid.css b/src/styles/components/media-grid.css new file mode 100644 index 0000000..beccb47 --- /dev/null +++ b/src/styles/components/media-grid.css @@ -0,0 +1,67 @@ +.media-grid { + display: grid; + gap: var(--spacing-sm); + + & ~ .pagination { + margin-top: var(--spacing-base); + } + + &.poster { + grid-template-columns: var(--grid-poster); + + & a { + aspect-ratio: var(--aspect-ratio-banner); + } + } + + &.square { + grid-template-columns: var(--grid-square); + + & a { + aspect-ratio: var(--aspect-ratio-square); + } + } + + &.vertical { + grid-template-columns: var(--grid-vertical); + + & a { + aspect-ratio: var(--aspect-ratio-vertical); + } + } + + &:is(.poster, .square, .vertical) img { + width: 100%; + height: auto; + } + + & .item { + position: relative; + } + + & .meta-text { + color: var(--color-lightest); + position: absolute; + z-index: 2; + padding: 0 var(--spacing-sm); + bottom: var(--spacing-sm); + + & .header, + & .subheader { + color: var(--color-lightest); + font-size: var(--font-size-sm); + line-height: var(--line-height-md); + text-shadow: var(--text-shadow-default); + } + + & .header { + font-weight: var(--font-weight-bold); + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 6; + line-clamp: 6; + text-overflow: ellipsis; + overflow: hidden; + } + } +} diff --git a/src/styles/components/menu.css b/src/styles/components/menu.css new file mode 100644 index 0000000..20c4d92 --- /dev/null +++ b/src/styles/components/menu.css @@ -0,0 +1,136 @@ +menu { + & .menu-primary { + position: absolute; + flex-direction: column; + list-style: none; + padding: 0; + top: calc(var(--spacing-3xl) * 1.75); + left: 0; + width: 100%; + z-index: 3; + + & > li { + overflow: hidden; + margin: 0; + padding: var(--spacing-sm) 0; + width: 100%; + background: var(--background-color); + + & a, + & .active { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + } + + & a { + text-decoration: none; + } + + & .active { + cursor: not-allowed; + } + + :is(.icon, .active) > svg { + display: none; + } + + :is(.icon, .active) > span { + display: inline; + } + } + } + + #menu-toggle { + display: none; + + &:checked + .menu-button-container { + & .menu-closed { + display: none; + } + + & .menu-open { + display: block; + } + } + + &:not(:checked) + .menu-button-container { + & .menu-closed { + display: block; + } + + & .menu-open { + display: none; + } + } + + & ~ .menu-primary li { + height: 0; + padding: 0; + font-size: var(--font-size-lg); + } + + &:checked ~ .menu-primary li { + height: calc(var(--sizing-3xl) * 1.5); + + @media (max-width: 767px) { + border-bottom: var(--border-gray); + } + + &:first-child { + @media (max-width: 767px) { + border-top: var(--border-gray); + } + } + } + } + + .menu-button-container { + display: unset; + + & svg { + cursor: pointer; + } + } + + @media (min-width: 768px) { + .menu-primary { + display: flex; + flex-direction: row; + margin: 0; + gap: var(--spacing-md); + position: relative; + top: unset; + left: unset; + width: auto; + + & > li { + background: none; + + & a { + width: var(--sizing-svg-base); + height: var(--sizing-svg-base); + } + + :is(.icon, .active) > svg { + display: block; + } + + :is(.icon, .active) > span { + display: none; + } + } + } + + #menu-toggle ~ .menu-primary li, + #menu-toggle:checked ~ .menu-primary li { + height: unset; + } + + .menu-button-container { + display: none; + } + } +} diff --git a/src/styles/components/modal.css b/src/styles/components/modal.css new file mode 100644 index 0000000..4d99079 --- /dev/null +++ b/src/styles/components/modal.css @@ -0,0 +1,63 @@ +.modal-wrapper, +.modal-body { + inset: 0; + width: 100%; + height: 100%; + position: fixed; +} + +.modal-wrapper { + background: var(--modal-overlay-background); + z-index: 3; + + .modal-body { + background: var(--background-color); + padding: var(--spacing-lg) var(--spacing-base); + overflow-y: auto; + border-radius: var(--border-radius-slight); + + h3 { + margin-top: 0; + } + + @media (min-width: 768px) { + max-width: 75%; + max-height: 75%; + inset: 12.5%; + border: var(--border-gray); + } + + .modal-close { + position: sticky; + top: 0; + left: 100%; + } + } +} + +.modal-input { + display: none; + + &:checked ~ .modal-wrapper { + display: block; + } + + &:not(:checked) ~ .modal-wrapper { + display: none; + } +} + +.modal-toggle, +.modal-close { + cursor: pointer; + display: inline-flex; + vertical-align: middle; + + svg { + stroke: var(--accent-color); + + &:is(:hover, :focus, :active) { + stroke: var(--accent-color-hover); + } + } +} \ No newline at end of file diff --git a/src/styles/components/music-chart.css b/src/styles/components/music-chart.css new file mode 100644 index 0000000..43e830e --- /dev/null +++ b/src/styles/components/music-chart.css @@ -0,0 +1,103 @@ +.music-chart { + margin: var(--margin-vertical-base-horizontal-zero); + + & ol { + padding-left: 0; + + @media screen and (min-width: 768px) { + list-style-position: outside; + } + } + + & .item { + display: flex; + flex-direction: column; + justify-content: start; + align-items: start; + + &:not(:last-of-type) { + margin-bottom: var(--spacing-lg); + } + + @media screen and (min-width: 768px) { + flex-direction: row; + align-items: center; + justify-content: space-between; + } + + & .progress-bar-wrapper { + max-width: 40%; + + @media screen and (max-width: 768px) { + margin-top: var(--spacing-sm); + } + } + + & img { + width: calc(var(--sizing-3xl) * 1.5); + height: calc(var(--sizing-3xl) * 1.5); + + @media screen and (min-width: 768px) { + width: calc(var(--sizing-3xl) * 2); + height: calc(var(--sizing-3xl) * 2); + } + } + + & .info { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + + @media screen and (min-width: 768px) { + max-width: calc(75% - var(--sizing-lg)); + } + } + + & .meta { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--spacing-md); + + @media screen and (min-width: 768px) { + width: calc(75% - var(--sizing-lg)); + } + } + + & .meta-text { + display: flex; + flex-direction: column; + justify-content: start; + gap: var(--spacing-xs); + + @media screen and (min-width: 768px) { + max-width: 85%; + } + } + + & .title { + font-weight: var(--font-weight-bold); + } + + & .title, + & .subtext, + & time { + line-height: var(--line-height-md); + word-break: break-word; + } + + & .subtext, + & time { + font-size: var(--font-size-sm); + } + + & time { + margin-top: var(--spacing-sm); + + @media screen and (min-width: 768px) { + text-align: right; + white-space: nowrap; + } + } + } +} diff --git a/src/styles/components/paginator.css b/src/styles/components/paginator.css new file mode 100644 index 0000000..fb2d77f --- /dev/null +++ b/src/styles/components/paginator.css @@ -0,0 +1,25 @@ +.pagination { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: var(--spacing-base); + + & button { + background: none; + padding: 0; + } + + & a { + display: flex; + + &.disabled svg[data-tablericon-name^="arrow-"] { + cursor: not-allowed; + stroke: var(--gray-medium); + stroke-width: var(--stroke-width-default); + } + } + + & p { + text-align: center; + } +} diff --git a/src/styles/components/progress-bar.css b/src/styles/components/progress-bar.css new file mode 100644 index 0000000..b2a7cab --- /dev/null +++ b/src/styles/components/progress-bar.css @@ -0,0 +1,13 @@ +.progress-bar-wrapper { + display: flex; + height: var(--sizing-lg); + width: 100%; + background-color: var(--gray-light); + border-radius: var(--border-radius-full); + overflow: hidden; + + & .progress-bar { + background-color: var(--accent-color); + border-radius: var(--border-radius-full); + } +} diff --git a/src/styles/components/tab-buttons.css b/src/styles/components/tab-buttons.css new file mode 100644 index 0000000..ce05980 --- /dev/null +++ b/src/styles/components/tab-buttons.css @@ -0,0 +1,38 @@ +#tracks-recent, +#tracks-chart, +.tracks-recent, +.tracks-chart { + display: none; +} + +#tracks-recent:checked ~ .tracks-recent, +#tracks-chart:checked ~ .tracks-chart { + display: block; +} + +input[id="tracks-recent"] ~ .tracks-recent, +input[id="tracks-chart"] ~ .tracks-chart { + margin-top: var(--spacing-base); +} + +[for="tracks-recent"] { + margin-right: var(--spacing-xs); +} + +#tracks-recent:checked ~ [for="tracks-recent"], +#tracks-chart:checked ~ [for="tracks-chart"] { + cursor: not-allowed; + border-color: var(--accent-color); + background-color: var(--accent-color); +} + +#tracks-recent:not(:checked) ~ [for="tracks-recent"], +#tracks-chart:not(:checked) ~ [for="tracks-chart"] { + color: var(--accent-color); + background: transparent; +} + +#tracks-recent:not(:checked) ~ [for="tracks-recent"]:is(:hover, :active), +#tracks-chart:not(:checked) ~ [for="tracks-chart"]:is(:hover, :active) { + color: var(--accent-color-hover); +} \ No newline at end of file diff --git a/src/styles/components/text-toggle.css b/src/styles/components/text-toggle.css new file mode 100644 index 0000000..68acaf8 --- /dev/null +++ b/src/styles/components/text-toggle.css @@ -0,0 +1,23 @@ +[data-toggle-content] { + &.text-toggle-hidden { + position: relative; + height: 500px; + overflow: hidden; + margin: var(--margin-vertical-base-horizontal-zero); + + & p:first-of-type { + margin-top: 0; + } + + &::after { + position: absolute; + z-index: 1; + content: ""; + box-shadow: var(--box-shadow-text-toggle); + width: 100%; + height: 20%; + bottom: 0; + left: 0; + } + } +} diff --git a/src/styles/components/youtube-player.css b/src/styles/components/youtube-player.css new file mode 100644 index 0000000..05e89c2 --- /dev/null +++ b/src/styles/components/youtube-player.css @@ -0,0 +1,15 @@ +youtube-video { + aspect-ratio: 16/9; + width: 100%; + display: flex; + overflow: hidden; + border: var(--border-default); + border-radius: var(--border-radius-slight); + margin: var(--margin-vertical-base-horizontal-zero); + + &:hover { + border: var(--border-default-hover); + transition: border var(--transition-duration-default) + var(--transition-ease-in-out); + } +} diff --git a/src/styles/feed.liquid b/src/styles/feed.liquid new file mode 100644 index 0000000..29e801d --- /dev/null +++ b/src/styles/feed.liquid @@ -0,0 +1,81 @@ +--- +permalink: /assets/styles/feed.xsl +--- + + + + + + + + <xsl:value-of select="/rss/channel/title" /> / {{ globals.site_name }} + + + + + + + + + + + + + +
    +
    + {% render "header.liquid", globals:globals, page:page, nav:nav %} +
    +

    + +

    + +
    + + + +
    +
    +
    + {% render "footer.liquid", + page:page, + nav:nav, + updated:updated, + pageUpdated:page.updated + %} +
    + + +
    +
    \ No newline at end of file diff --git a/src/styles/index.css b/src/styles/index.css new file mode 100644 index 0000000..38205f9 --- /dev/null +++ b/src/styles/index.css @@ -0,0 +1,39 @@ +@layer reset, defaults, base, page, components, plugins; + +/* style resets */ +@import url("./base/reset.css") layer(reset); + +/* core defaults */ +@import url("./base/fonts.css") layer(defaults); +@import url("./base/vars.css") layer(defaults); + +/* base styles */ +@import url("./base/index.css") layer(base); + +/* plugins */ +@import url("./plugins/prism.css") layer(plugins); + +/* page styles */ +@import url("./pages/about.css") layer(page); +@import url("./pages/books.css") layer(page); +@import url("./pages/contact.css") layer(page); +@import url("./pages/links.css") layer(page); +@import url("./pages/media.css") layer(page); +@import url("./pages/music.css") layer(page); +@import url("./pages/watching.css") layer(page); +@import url("./pages/webrings.css") layer(page); + +/* component styles */ +@import url("./components/addon-links.css") layer(components); +@import url("./components/badge-grid.css") layer(components); +@import url("./components/banners.css") layer(components); +@import url("./components/buttons.css") layer(components); +@import url("./components/forms.css") layer(components); +@import url("./components/mastodon-post.css") layer(components); +@import url("./components/media-grid.css") layer(components); +@import url("./components/menu.css") layer(components); +@import url("./components/modal.css") layer(components); +@import url("./components/music-chart.css") layer(components); +@import url("./components/paginator.css") layer(components); +@import url("./components/progress-bar.css") layer(components); +@import url("./components/youtube-player.css") layer(components); diff --git a/src/styles/pages/about.css b/src/styles/pages/about.css new file mode 100644 index 0000000..ec1394d --- /dev/null +++ b/src/styles/pages/about.css @@ -0,0 +1,24 @@ +:root { + --avatar-size: 16rem; + + @media screen and (min-width: 768px) { + --avatar-size: 24rem; + } +} + +.avatar-wrapper { + display: flex; + justify-content: center; + width: 100%; + + & img { + width: var(--avatar-size); + height: var(--avatar-size); + image-rendering: pixelated; + } +} + +.about-title { + margin: var(--margin-vertical-base-horizontal-zero); + text-align: center; +} diff --git a/src/styles/pages/books.css b/src/styles/pages/books.css new file mode 100644 index 0000000..39d5c69 --- /dev/null +++ b/src/styles/pages/books.css @@ -0,0 +1,87 @@ +:is(.book-entry, .book-focus) img { + height: auto; + aspect-ratio: var(--aspect-ratio-vertical); +} + +.book-entry { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-sm); + + &:not(:last-of-type) { + padding-bottom: var(--spacing-base); + border-bottom: var(--border-gray); + } + + @media screen and (min-width: 768px) { + flex-direction: row; + gap: var(--spacing-base); + align-items: start; + } + + & img { + max-width: calc(var(--sizing-3xl) * 4); + } + + & .media-meta { + margin-top: var(--sizing-base); + align-items: center; + + @media screen and (min-width: 768px) { + margin-top: 0; + align-items: start; + } + + & .description p:last-of-type { + margin-bottom: 0; + } + + & .progress-bar-wrapper { + max-width: 75%; + margin-bottom: 0; + + @media screen and (min-width: 768px) { + margin-top: 0; + max-width: 50%; + } + } + } +} + +.book-focus { + & .book-display { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-base); + margin-bottom: var(--spacing-base); + + @media screen and (min-width: 768px) { + flex-direction: row; + align-items: start; + } + + & img { + border: var(--border-default); + } + + & .media-meta { + width: 100%; + align-items: center; + + @media screen and (min-width: 768px) { + width: auto; + align-items: start; + } + + & .progress-bar-wrapper { + max-width: 50%; + + @media screen and (min-width: 768px) { + max-width: none; + } + } + } + } +} \ No newline at end of file diff --git a/src/styles/pages/contact.css b/src/styles/pages/contact.css new file mode 100644 index 0000000..01bd089 --- /dev/null +++ b/src/styles/pages/contact.css @@ -0,0 +1,36 @@ +.contact-wrapper { + display: grid; + grid-template-columns: var(--grid-columns-one); + gap: var(--spacing-base); + + @media screen and (min-width: 768px) { + grid-template-columns: var(--grid-columns-two); + } + + & .hp, + & label > span { + display: none; + } + + & textarea { + height: calc(var(--sizing-3xl) * 5); + } + + & .column.description { + & p:first-of-type { + margin-top: 0; + } + + ul { + margin-bottom: 0; + } + } +} + +.contact-success-wrapper { + text-align: center; + + & h2 { + margin: 0; + } +} diff --git a/src/styles/pages/links.css b/src/styles/pages/links.css new file mode 100644 index 0000000..ffdcbb2 --- /dev/null +++ b/src/styles/pages/links.css @@ -0,0 +1,15 @@ +.link-grid { + display: grid; + gap: var(--spacing-sm); + grid-template-columns: var(--grid-columns-one); + + @media screen and (min-width: 768px) { + grid-template-columns: var(--grid-columns-two); + } + + & .link-box { + border: var(--border-gray); + border-radius: var(--border-radius-slight); + padding: var(--spacing-sm) var(--spacing-md); + } +} diff --git a/src/styles/pages/media.css b/src/styles/pages/media.css new file mode 100644 index 0000000..e0172e0 --- /dev/null +++ b/src/styles/pages/media.css @@ -0,0 +1,42 @@ +.media-meta { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + + & .title { + font-size: var(--font-size-xl); + line-height: var(--line-height-md); + } + + & .sub-meta { + font-size: var(--font-size-sm); + + & svg { + width: var(--sizing-svg-sm); + height: var(--sizing-svg-sm); + } + } +} + +a:is(:hover, :active, :focus) .media-overlay::after { + border: var(--border-default-hover); + transition: border-color var(--transition-duration-default) + var(--transition-ease-in-out); +} + +.media-overlay::after { + position: absolute; + z-index: 1; + content: ""; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: var(--border-default); + box-shadow: var(--box-shadow-media); + border-radius: var(--border-radius-slight); +} + +.associated-media { + margin: var(--margin-vertical-base-horizontal-zero); +} \ No newline at end of file diff --git a/src/styles/pages/music.css b/src/styles/pages/music.css new file mode 100644 index 0000000..4c18783 --- /dev/null +++ b/src/styles/pages/music.css @@ -0,0 +1,37 @@ +.artist-focus { + & img { + border: var(--border-default); + aspect-ratio: var(--aspect-ratio-square); + width: 100%; + height: auto; + + @media screen and (min-width: 768px) { + max-width: calc(var(--sizing-3xl) * 6.75); + } + } + + & .artist-display { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + margin-bottom: var(--spacing-base); + + @media screen and (min-width: 768px) { + flex-direction: row; + gap: var(--spacing-md); + } + + & .media-meta { + margin-top: var(--spacing-base); + + @media screen and (min-width: 768px) { + margin-top: 0; + } + } + } + + & table + p { + font-size: var(--font-size-sm); + margin: var(--spacing-base) 0 0; + } +} diff --git a/src/styles/pages/watching.css b/src/styles/pages/watching.css new file mode 100644 index 0000000..0e91012 --- /dev/null +++ b/src/styles/pages/watching.css @@ -0,0 +1,29 @@ +.watching.hero { + position: relative; + + & img { + aspect-ratio: var(--aspect-ratio-banner); + } + + & .meta-text { + color: var(--color-lightest); + position: absolute; + z-index: 2; + left: var(--spacing-sm); + bottom: var(--spacing-sm); + + & .header { + font-weight: var(--font-weight-bold); + } + + & .subheader { + font-size: var(--font-size-sm); + } + + & .header, + & .subheader { + line-height: var(--line-height-md); + text-shadow: var(--text-shadow-default); + } + } +} diff --git a/src/styles/pages/webrings.css b/src/styles/pages/webrings.css new file mode 100644 index 0000000..ab01bba --- /dev/null +++ b/src/styles/pages/webrings.css @@ -0,0 +1,20 @@ +.webring-wrapper, +.webring-navigation { + display: flex; + align-items: center; +} + +.webring-wrapper { + flex-direction: column; + text-align: center; + margin: var(--margin-vertical-base-horizontal-zero); + + & p { + margin: 0; + } + + & .webring-navigation { + justify-content: center; + gap: var(--spacing-sm); + } +} \ No newline at end of file diff --git a/src/styles/plugins/prism.css b/src/styles/plugins/prism.css new file mode 100644 index 0000000..0ae33e2 --- /dev/null +++ b/src/styles/plugins/prism.css @@ -0,0 +1,110 @@ +code, +pre { + color: var(--blue-100); + background: none; + border-radius: var(--border-radius-slight); + font-family: var(--font-mono); + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: var(--line-height-md); + tab-size: 2; + hyphens: none; +} + +pre { + padding: var(--spacing-lg); + margin: var(--sizing-xl) 0; + overflow: auto; + + & > code { + padding: 0; + } +} + +:not(pre) > code { + padding: var(--spacing-xs); + white-space: normal; +} + +pre, +:not(pre) > code { + background: var(--color-darkest); + border: var(--border-gray); +} + +.namespace { + opacity: 0.7; +} + +.language-css .token.string, +.style .token.string { + color: #99ccff; +} + +.token { + color: var(--blue-200); + + &.comment, + &.prolog, + &.doctype, + &.cdata { + color: var(--gray-500); + } + + &.punctuation { + color: var(--gray-300); + } + + &.boolean, + &.number { + color: var(--blue-400); + } + + &.selector, + &.attr-name, + &.string, + &.char, + &.builtin, + &.inserted { + color: #6fff6f; + } + + &.operator, + &.entity, + &.url, + &.variable { + color: #99ccff; + } + + &.atrule, + &.attr-value, + &.function, + &.class-name { + color: #ff8f66; + } + + &.keyword { + color: #00ffff; + } + + &.regex, + &.important { + color: #ff7373; + } + + &.italic { + font-style: italic; + } + + &.entity { + cursor: help; + } + + &.important, + &.bold { + font-weight: var(--font-weight-bold); + } +} diff --git a/src/styles/styles.json b/src/styles/styles.json new file mode 100644 index 0000000..b822534 --- /dev/null +++ b/src/styles/styles.json @@ -0,0 +1,3 @@ +{ + "eleventyExcludeFromCollections": true +} diff --git a/src/utils/data/activity.js b/src/utils/data/activity.js new file mode 100644 index 0000000..b4d91e3 --- /dev/null +++ b/src/utils/data/activity.js @@ -0,0 +1,24 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchActivity() { + try { + const { data, error } = await supabase + .from('optimized_all_activity') + .select('feed'); + + if (error) { + console.error('Error fetching activity data:', error); + return []; + } + + const [{ feed } = {}] = data || []; + return feed?.filter((item) => item.feed !== null) || []; + } catch (error) { + console.error('Unexpected error fetching activity data:', error); + return []; + } +} \ No newline at end of file diff --git a/src/utils/data/albumReleases.js b/src/utils/data/albumReleases.js new file mode 100644 index 0000000..363988b --- /dev/null +++ b/src/utils/data/albumReleases.js @@ -0,0 +1,43 @@ +import { createClient } from '@supabase/supabase-js'; +import { DateTime } from 'luxon'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchAlbumReleases() { + try { + const today = DateTime.utc().startOf('day').toSeconds(); + + const { data, error } = await supabase + .from('optimized_album_releases') + .select('*'); + + if (error) { + console.error('Error fetching album releases:', error); + return { all: [], upcoming: [] }; + } + + const all = data + .map((album) => { + const releaseDate = DateTime.fromSeconds(album.release_timestamp) + .toUTC() + .startOf('day'); + + return { + ...album, + description: album.artist.description, + date: releaseDate.toLocaleString(DateTime.DATE_FULL), + timestamp: releaseDate.toSeconds(), + }; + }) + .sort((a, b) => a.timestamp - b.timestamp); + + const upcoming = all.filter((album) => album.release_timestamp > today); + + return { all, upcoming }; + } catch (error) { + console.error('Unexpected error processing album releases:', error); + return { all: [], upcoming: [] }; + } +} \ No newline at end of file diff --git a/src/utils/data/artists.js b/src/utils/data/artists.js new file mode 100644 index 0000000..bd1c940 --- /dev/null +++ b/src/utils/data/artists.js @@ -0,0 +1,38 @@ +import { createClient } from '@supabase/supabase-js'; +import { parseCountryField } from '@utils/helpers.js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchArtists(){ + let artists = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from('optimized_artists') + .select('*') + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching artists:', error); + break; + } + + // Process and concatenate artists data + artists = artists.concat( + data.map((artist) => ({ + ...artist, + country: parseCountryField(artist['country']), + })) + ); + + // Break if no more data + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + return artists; +}; \ No newline at end of file diff --git a/src/utils/data/blogroll.js b/src/utils/data/blogroll.js new file mode 100644 index 0000000..d8f5fc7 --- /dev/null +++ b/src/utils/data/blogroll.js @@ -0,0 +1,22 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchBlogroll() { + const { data, error } = await supabase + .from('authors') + .select('*') + .eq('blogroll', true) + .order('name', { ascending: true }); + + if (error) { + console.error('Error fetching authors for the blogroll:', error); + return []; + } + + return data.sort((a, b) => + a.name.toLowerCase().localeCompare(b.name.toLowerCase()) + ); +}; \ No newline at end of file diff --git a/src/utils/data/books.js b/src/utils/data/books.js new file mode 100644 index 0000000..cd3e7c5 --- /dev/null +++ b/src/utils/data/books.js @@ -0,0 +1,50 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchBooks() { + let books = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from('optimized_books') + .select('*') + .order('date_finished', { ascending: false }) + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching books:', error); + break; + } + + books = books.concat(data); + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + const years = {}; + books.forEach((book) => { + const year = book.year; + if (!years[year]) { + years[year] = { value: year, data: [book] }; + } else { + years[year].data.push(book); + } + }); + + const sortedByYear = Object.values(years).filter((year) => year.value > 2017); + const currentYear = new Date().getFullYear(); + const booksForCurrentYear = + sortedByYear.find((yearGroup) => yearGroup.value === currentYear)?.data || []; + + return { + all: books, + years: sortedByYear, + currentYear: booksForCurrentYear, + feed: books.filter((book) => book.feed), + }; +}; \ No newline at end of file diff --git a/src/utils/data/concerts.js b/src/utils/data/concerts.js new file mode 100644 index 0000000..8b67982 --- /dev/null +++ b/src/utils/data/concerts.js @@ -0,0 +1,32 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchConcertsData() { + let concerts = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from('optimized_concerts') + .select('*') + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching concerts:', error); + break; + } + + concerts = concerts.concat(data); + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + return concerts.map((concert) => ({ + ...concert, + artist: concert.artist || { name: concert.artist_name_string, url: null }, + })); +}; \ No newline at end of file diff --git a/src/utils/data/genres.js b/src/utils/data/genres.js new file mode 100644 index 0000000..fc1f1c5 --- /dev/null +++ b/src/utils/data/genres.js @@ -0,0 +1,18 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchGenres() { + const { data, error } = await supabase + .from('optimized_genres') + .select('*'); + + if (error) { + console.error('Error fetching genres with artists:', error); + return []; + } + + return data; +}; \ No newline at end of file diff --git a/src/utils/data/globals.js b/src/utils/data/globals.js new file mode 100644 index 0000000..80f1750 --- /dev/null +++ b/src/utils/data/globals.js @@ -0,0 +1,19 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchGlobals() { + const { data, error } = await supabase + .from('optimized_globals') + .select('*') + .single(); + + if (error) { + console.error('Error fetching globals:', error); + return {}; + } + + return data; +} diff --git a/src/utils/data/links.js b/src/utils/data/links.js new file mode 100644 index 0000000..e73cc15 --- /dev/null +++ b/src/utils/data/links.js @@ -0,0 +1,31 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchLinks() { + let links = []; + let page = 0; + let fetchMore = true; + + while (fetchMore) { + const { data, error } = await supabase + .from('optimized_links') + .select('*') + .range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching links:', error); + return links; + } + + if (data.length < PAGE_SIZE) fetchMore = false; + + links = links.concat(data); + page++; + } + + return links; +}; \ No newline at end of file diff --git a/src/utils/data/movies.js b/src/utils/data/movies.js new file mode 100644 index 0000000..10f0967 --- /dev/null +++ b/src/utils/data/movies.js @@ -0,0 +1,42 @@ +import { createClient } from '@supabase/supabase-js'; +import { DateTime } from 'luxon'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchMovies() { + let movies = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from('optimized_movies') + .select('*') + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching movies:', error); + break; + } + + movies = movies.concat(data); + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + const year = DateTime.now().year; + const favoriteMovies = movies.filter(movie => movie.favorite); + const recentlyWatchedMovies = movies.filter( + movie => movie.last_watched && year - DateTime.fromISO(movie.last_watched).year <= 3 + ); + + return { + movies, + watchHistory: movies.filter(movie => movie.last_watched), + recentlyWatched: recentlyWatchedMovies, + favorites: favoriteMovies.sort((a, b) => a.title.localeCompare(b.title)), + feed: movies.filter(movie => movie.feed), + }; +}; \ No newline at end of file diff --git a/src/utils/data/music.js b/src/utils/data/music.js new file mode 100644 index 0000000..3f00c95 --- /dev/null +++ b/src/utils/data/music.js @@ -0,0 +1,79 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export async function fetchMusicData() { + const fetchDataFromView = async (viewName) => { + let rows = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from(viewName) + .select('*') + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error(`Error fetching data from view ${viewName}:`, error); + break; + } + + if (data.length === 0) break; + + rows = [...rows, ...data]; + + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + return rows; + }; + + try { + const [ + recentTracks, + weekTracks, + weekArtists, + weekAlbums, + weekGenres, + monthTracks, + monthArtists, + monthAlbums, + monthGenres, + ] = await Promise.all([ + fetchDataFromView('recent_tracks'), + fetchDataFromView('week_tracks'), + fetchDataFromView('week_artists'), + fetchDataFromView('week_albums'), + fetchDataFromView('week_genres'), + fetchDataFromView('month_tracks'), + fetchDataFromView('month_artists'), + fetchDataFromView('month_albums'), + fetchDataFromView('month_genres'), + ]); + + return { + recent: recentTracks, + week: { + tracks: weekTracks, + artists: weekArtists, + albums: weekAlbums, + genres: weekGenres, + totalTracks: weekTracks.reduce((acc, track) => acc + track.plays, 0).toLocaleString('en-US'), + }, + month: { + tracks: monthTracks, + artists: monthArtists, + albums: monthAlbums, + genres: monthGenres, + totalTracks: monthTracks.reduce((acc, track) => acc + track.plays, 0).toLocaleString('en-US'), + }, + }; + } catch (error) { + console.error('Error fetching and processing music data:', error); + return {}; + } +}; \ No newline at end of file diff --git a/src/utils/data/nav.js b/src/utils/data/nav.js new file mode 100644 index 0000000..5a678e6 --- /dev/null +++ b/src/utils/data/nav.js @@ -0,0 +1,39 @@ +import { createClient } from '@supabase/supabase-js' + +const SUPABASE_URL = import.meta.env.SUPABASE_URL +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY) + +export async function fetchNavigation() { + const { data, error } = await supabase + .from('optimized_navigation') + .select('*') + + if (error) { + console.error('Error fetching navigation data:', error) + return {} + } + + const menu = data.reduce((acc, item) => { + const menuItem = { + title: item['title'] || item['page_title'], + permalink: item['permalink'] || item ['page_permalink'], + icon: item['icon'], + sort: item['sort'] + } + + if (!acc[item['menu_location']]) { + acc[item['menu_location']] = [menuItem] + } else { + acc[item['menu_location']].push(menuItem) + } + + return acc + }, {}) + + Object.keys(menu).forEach(location => { + menu[location].sort((a, b) => a['sort'] - b['sort']) + }) + + return menu +} \ No newline at end of file diff --git a/src/utils/data/nowPlaying.js b/src/utils/data/nowPlaying.js new file mode 100644 index 0000000..f2fbca2 --- /dev/null +++ b/src/utils/data/nowPlaying.js @@ -0,0 +1,24 @@ +import { createClient } from '@supabase/supabase-js' + +const SUPABASE_URL = import.meta.env.SUPABASE_URL +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY) + +export async function fetchNowPlaying() { + const { data, error } = await supabase + .from('optimized_latest_listen') + .select('*') + .single() + + if (error) { + console.error('Error fetching the latest track:', error) + return {} + } + + const genreEmoji = data.genre_emoji + const emoji = data.artist_emoji || genreEmoji + + return { + content: `${emoji || '🎧'} ${data.track_name} by ${data.artist_name}`, + } +} \ No newline at end of file diff --git a/src/utils/data/pages.js b/src/utils/data/pages.js new file mode 100644 index 0000000..795e619 --- /dev/null +++ b/src/utils/data/pages.js @@ -0,0 +1,16 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export async function fetchPages() { + const { data, error } = await supabase.from('optimized_pages').select('*'); + + if (error) { + console.error('Error fetching pages:', error); + return []; + } + + return data; +} \ No newline at end of file diff --git a/src/utils/data/posts.js b/src/utils/data/posts.js new file mode 100644 index 0000000..770137f --- /dev/null +++ b/src/utils/data/posts.js @@ -0,0 +1,32 @@ +import { createClient } from '@supabase/supabase-js' + +const SUPABASE_URL = import.meta.env['SUPABASE_URL'] +const SUPABASE_KEY = import.meta.env['SUPABASE_KEY'] +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY) +const PAGE_SIZE = 1000 + +export async function fetchAllPosts() { + let posts = [] + let page = 0 + let fetchMore = true + + while (fetchMore) { + const { data, error } = await supabase + .from('optimized_posts') + .select('*') + .order('date', { ascending: false }) + .range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1) + + if (error) { + console.error('Error fetching posts:', error) + return posts + } + + if (data.length < PAGE_SIZE) fetchMore = false + + posts = posts.concat(data) + page++ + } + + return posts +} \ No newline at end of file diff --git a/src/utils/data/robots.js b/src/utils/data/robots.js new file mode 100644 index 0000000..a64ebac --- /dev/null +++ b/src/utils/data/robots.js @@ -0,0 +1,29 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 500; + +export async function fetchAllRobots() { + let robots = []; + let from = 0; + + while (true) { + const { data, error } = await supabase + .from('robots') + .select('user_agent') + .range(from, from + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching robot data:', error); + return []; + } + + robots = robots.concat(data); + if (data.length < PAGE_SIZE) break; + from += PAGE_SIZE; + } + + return robots.map((robot) => robot['user_agent']).sort(); +}; \ No newline at end of file diff --git a/src/utils/data/search.js b/src/utils/data/search.js new file mode 100644 index 0000000..c779e91 --- /dev/null +++ b/src/utils/data/search.js @@ -0,0 +1,19 @@ +import { createClient } from '@supabase/supabase-js' + +const SUPABASE_URL = import.meta.env.SUPABASE_URL +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY) + +export async function fetchSearchIndex() { + const { data, error } = await supabase + .from('optimized_search_index') + .select('search_index') + + if (error) { + console.error('Error fetching search index data:', error) + return [] + } + + const [{ search_index } = {}] = data + return search_index || [] +} \ No newline at end of file diff --git a/src/utils/data/syndication.js b/src/utils/data/syndication.js new file mode 100644 index 0000000..291f262 --- /dev/null +++ b/src/utils/data/syndication.js @@ -0,0 +1,20 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export default async function fetchSyndication() { + const { data, error } = await supabase + .from('optimized_syndication') + .select('syndication'); + + if (error) { + console.error('Error fetching syndication data:', error); + return []; + } + + const [{ syndication } = {}] = data; + + return syndication?.filter((item) => item.syndication !== null) || []; +} \ No newline at end of file diff --git a/src/utils/data/tv.js b/src/utils/data/tv.js new file mode 100644 index 0000000..109612d --- /dev/null +++ b/src/utils/data/tv.js @@ -0,0 +1,46 @@ +import { createClient } from '@supabase/supabase-js'; + +const SUPABASE_URL = import.meta.env.SUPABASE_URL; +const SUPABASE_KEY = import.meta.env.SUPABASE_KEY; +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); +const PAGE_SIZE = 1000; + +export const fetchShows = async () => { + let shows = []; + let rangeStart = 0; + + while (true) { + const { data, error } = await supabase + .from('optimized_shows') + .select('*') + .range(rangeStart, rangeStart + PAGE_SIZE - 1); + + if (error) { + console.error('Error fetching shows:', error); + break; + } + + shows = shows.concat(data); + if (data.length < PAGE_SIZE) break; + rangeStart += PAGE_SIZE; + } + + const watchedShows = shows.filter(show => show['last_watched_at'] !== null); + const episodes = watchedShows.map(show => ({ + title: show['episode']['title'], + year: show['year'], + formatted_episode: show['episode']['formatted_episode'], + url: show['episode']['url'], + image: show['episode']['image'], + backdrop: show['episode']['backdrop'], + last_watched_at: show['episode']['last_watched_at'], + grid: show['grid'], + type: 'tv' + })); + + return { + shows, + recentlyWatched: episodes.slice(0, 225), + favorites: shows.filter(show => show.favorite).sort((a, b) => a.title.localeCompare(b.title)), + }; +}; \ No newline at end of file diff --git a/src/utils/helpers.js b/src/utils/helpers.js new file mode 100644 index 0000000..38636fd --- /dev/null +++ b/src/utils/helpers.js @@ -0,0 +1,45 @@ +import markdownIt from "markdown-it"; +import markdownItAnchor from "markdown-it-anchor"; +import markdownItFootnote from "markdown-it-footnote"; +import markdownItPrism from "markdown-it-prism"; + +const markdown = markdownIt({ html: true, linkify: true }); +markdown.use(markdownItAnchor, { + level: [1, 2], + permalink: markdownItAnchor.permalink.headerLink({ + safariReaderFix: true, + }), +}); +markdown.use(markdownItFootnote); +markdown.use(markdownItPrism); + +export const shuffleArray = (array) => { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + let j = Math.floor(Math.random() * (i + 1)); + let temp = shuffled[i]; + shuffled[i] = shuffled[j]; + shuffled[j] = temp; + } + return shuffled; +}; + +export const regionNames = new Intl.DisplayNames(["en"], { type: "region" }); + +export const getCountryName = (countryCode) => + regionNames.of(countryCode.trim()) || countryCode.trim(); + +export const parseCountryField = (countryField) => { + if (!countryField) return null; + + const delimiters = [",", "/", "&", "and"]; + let countries = [countryField]; + + delimiters.forEach((delimiter) => { + countries = countries.flatMap((country) => country.split(delimiter)); + }); + + return countries.map(getCountryName).join(", "); +}; + +export const md = (string) => markdown.render(string); diff --git a/workers/analytics/index.js b/workers/analytics/index.js new file mode 100644 index 0000000..1d0cb7a --- /dev/null +++ b/workers/analytics/index.js @@ -0,0 +1,40 @@ +const scriptName = "/js/script.js"; +const endpoint = "/api/event"; + +addEventListener("fetch", (event) => { + event.passThroughOnException(); + event.respondWith(handleRequest(event)); +}); + +async function handleRequest(event) { + const url = new URL(event.request.url); + const pathname = url.pathname; + + if (pathname === scriptName) { + return getScript(event); + } else if (pathname === endpoint) { + return postData(event); + } + return new Response(null, { status: 404 }); +} + +async function getScript(event) { + const cache = caches.default; + let response = await cache.match(event.request); + + if (!response) { + const scriptUrl = + "https://plausible.io/js/plausible.outbound-links.tagged-events.js"; + response = await fetch(scriptUrl); + if (response.ok) + event.waitUntil(cache.put(event.request, response.clone())); + } + + return response; +} + +async function postData(event) { + const request = new Request(event.request); + request.headers.delete("cookie"); + return await fetch("https://plausible.io/api/event", request); +} diff --git a/workers/analytics/wrangler.template.toml b/workers/analytics/wrangler.template.toml new file mode 100644 index 0000000..5b39504 --- /dev/null +++ b/workers/analytics/wrangler.template.toml @@ -0,0 +1,13 @@ +name = "analytics-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "analytics-worker-production" +routes = [ + { pattern = "coryd.dev/js/*", zone_id = "${CF_ZONE_ID}" }, + { pattern = "coryd.dev/api/event", zone_id = "${CF_ZONE_ID}" } +] \ No newline at end of file diff --git a/workers/artist-import/index.js b/workers/artist-import/index.js new file mode 100644 index 0000000..3f0585a --- /dev/null +++ b/workers/artist-import/index.js @@ -0,0 +1,184 @@ +import slugify from "slugify"; +import countries from "i18n-iso-countries"; + +countries.registerLocale(require("i18n-iso-countries/langs/en.json")); + +function sanitizeMediaString(str) { + const sanitizedString = str + .normalize("NFD") + .replace(/[\u0300-\u036f\u2010\-\.\?\(\)\[\]\{\}]/g, "") + .replace(/\.{3}/g, ""); + return slugify(sanitizedString, { + replacement: "-", + remove: /[#,&,+()$~%.'\":*?<>{}]/g, + lower: true, + }); +} + +export default { + async fetch(request, env) { + const directusUrl = env.DIRECTUS_URL; + const directusToken = env.DIRECTUS_API_TOKEN; + const artistImportToken = env.ARTIST_IMPORT_TOKEN; + const artistFlowID = env.ARTIST_FLOW_ID; + const albumFlowID = env.ALBUM_FLOW_ID; + const placeholderImageId = "4cef75db-831f-4f5d-9333-79eaa5bb55ee"; + const requestUrl = new URL(request["url"]); + const providedToken = requestUrl.searchParams.get("token"); + + if (!providedToken || providedToken !== artistImportToken) return new Response("Unauthorized", { status: 401 }); + + async function saveToDirectus(endpoint, payload) { + const response = await fetch(`${directusUrl}/items/${endpoint}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${directusToken}`, + }, + body: JSON.stringify(payload), + }); + const data = await response.json(); + if (!response.ok) { + throw new Error( + data["errors"] + ? data["errors"][0]["message"] + : "Failed to save to Directus" + ); + } + return data["data"]; + } + + async function findGenreIdByName(genreName) { + try { + const response = await fetch( + `${directusUrl}/items/genres?filter[name][_eq]=${encodeURIComponent( + genreName.toLowerCase() + )}`, + { headers: { Authorization: `Bearer ${directusToken}` } } + ); + const data = await response.json(); + return data["data"].length > 0 ? data["data"][0]["id"] : null; + } catch (error) { + console.error("Error fetching genre ID:", error["message"]); + return null; + } + } + + const artistId = requestUrl.searchParams.get("artist_id"); + if (!artistId) + return new Response("artist_id parameter is required", { status: 400 }); + + let artistData; + try { + const artistResponse = await fetch( + `${directusUrl}/flows/trigger/${artistFlowID}?artist_id=${artistId}&import_token=${artistImportToken}`, + { headers: { Authorization: `Bearer ${directusToken}` } } + ); + artistData = await artistResponse.json(); + artistData = + artistData["get_artist_data"]["data"]["MediaContainer"]["Metadata"][0]; + } catch (error) { + console.error( + "Error fetching artist data from Directus flow:", + error["message"] + ); + return new Response("Error fetching artist data", { status: 500 }); + } + + const artistName = artistData["title"] || ""; + const artistKey = sanitizeMediaString(artistName); + const countryName = artistData["Country"] + ? artistData["Country"][0]?.["tag"] + : ""; + const countryIsoCode = countries.getAlpha2Code(countryName, "en") || ""; + const slug = `/music/artists/${artistKey}-${countryName.toLowerCase()}`; + const description = artistData["summary"] || ""; + const mbid = artistData["Guid"]?.[0]?.["id"]?.replace("mbid://", "") || ""; + + const genreNames = artistData["Genre"] + ? artistData["Genre"].map((g) => g["tag"].toLowerCase()) + : []; + let genreId = null; + for (const genreName of genreNames) { + genreId = await findGenreIdByName(genreName); + if (genreId) break; + } + + const artistPayload = { + name: artistName, + name_string: artistName, + slug: slug, + description: description, + mbid: mbid, + tentative: true, + genres: genreId, + country: countryIsoCode, + art: placeholderImageId, + }; + + let insertedArtist; + try { + insertedArtist = await saveToDirectus("artists", artistPayload); + } catch (error) { + console.error("Error saving artist:", error["message"]); + return new Response("Error saving artist", { status: 500 }); + } + + let albumData; + try { + const albumResponse = await fetch( + `${directusUrl}/flows/trigger/${albumFlowID}?artist_id=${artistId}&import_token=${artistImportToken}`, + { headers: { Authorization: `Bearer ${directusToken}` } } + ); + albumData = await albumResponse.json(); + albumData = + albumData["get_album_data"]["data"]["MediaContainer"]["Metadata"]; + } catch (error) { + console.error( + "Error fetching album data from Directus flow:", + error["message"] + ); + return new Response("Error fetching album data", { status: 500 }); + } + + for (const album of albumData) { + const albumName = album["title"] || ""; + const albumKey = `${artistKey}-${sanitizeMediaString(albumName)}`; + const albumSlug = `/music/albums/${albumKey}`; + const albumDescription = album["summary"] || ""; + const albumReleaseDate = album["originallyAvailableAt"] || ""; + const albumReleaseYear = albumReleaseDate + ? new Date(albumReleaseDate).getFullYear() + : null; + const albumGenres = album["Genre"] + ? album["Genre"].map((g) => g["tag"]) + : []; + const albumMbid = + album["Guid"]?.[0]?.["id"]?.replace("mbid://", "") || null; + + const albumPayload = { + name: albumName, + key: albumKey, + slug: albumSlug, + mbid: albumMbid, + description: albumDescription, + release_year: albumReleaseYear, + artist: insertedArtist["id"], + artist_name: artistName, + genres: albumGenres, + art: placeholderImageId, + tentative: true, + }; + + try { + await saveToDirectus("albums", albumPayload); + } catch (error) { + console.error("Error saving album:", error["message"]); + } + } + + return new Response("Artist and albums synced successfully", { + status: 200, + }); + }, +}; diff --git a/workers/artist-import/wrangler.template.toml b/workers/artist-import/wrangler.template.toml new file mode 100644 index 0000000..f6115b8 --- /dev/null +++ b/workers/artist-import/wrangler.template.toml @@ -0,0 +1,15 @@ +name = "import-artist-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[observability] +enabled = true + +[env.production] +name = "import-artist-worker-production" +routes = [ + { pattern = "coryd.dev/api/import-artist*", zone_id = "${CF_ZONE_ID}" } +] diff --git a/workers/contact/index.js b/workers/contact/index.js new file mode 100644 index 0000000..761c4ea --- /dev/null +++ b/workers/contact/index.js @@ -0,0 +1,101 @@ +import { createClient } from "@supabase/supabase-js"; + +const RATE_LIMIT = 5; +const TIME_FRAME = 60 * 60 * 1000; +const ipSubmissions = new Map(); + +export default { + async fetch(request, env) { + if (request.method === "POST") { + const ip = + request.headers.get("CF-Connecting-IP") || + request.headers.get("X-Forwarded-For") || + request.headers.get("Remote-Addr"); + const currentTime = Date.now(); + + if (!ipSubmissions.has(ip)) ipSubmissions.set(ip, []); + + const submissions = ipSubmissions + .get(ip) + .filter((time) => currentTime - time < TIME_FRAME); + + if (submissions.length >= RATE_LIMIT) + return Response.redirect("https://coryd.dev/rate-limit", 301); + + submissions.push(currentTime); + ipSubmissions.set(ip, submissions); + + try { + const formData = await request.formData(); + const name = formData.get("name"); + const email = formData.get("email"); + const message = formData.get("message"); + const hpName = formData.get("hp_name"); + if (hpName) return new Response("Spam detected", { status: 400 }); + if (!name || !email || !message) + return new Response("Invalid input", { status: 400 }); + + const emailDomain = email.split("@")[1].toLowerCase(); + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); + const { data: blockedDomains, error: domainError } = await supabase + .from("blocked_domains") + .select("domain_name"); + + if (domainError) + throw new Error( + `Failed to fetch blocked domains: ${domainError.message}` + ); + + const domainList = blockedDomains.map((item) => + item["domain_name"].toLowerCase() + ); + + if (domainList.includes(emailDomain)) + return new Response("Email domain is blocked.", { status: 400 }); + + const { error } = await supabase + .from("contacts") + .insert([{ name, email, message, replied: false }]); + + if (error) throw error; + + const forwardEmailApiKey = env.FORWARDEMAIL_API_KEY; + const authHeader = "Basic " + btoa(`${forwardEmailApiKey}:`); + const emailData = new URLSearchParams({ + from: `${name} `, + to: "hi@coryd.dev", + subject: `${message}`, + text: `Name: ${name}\nEmail: ${email}\nMessage: ${message}`, + replyTo: email, + }).toString(); + const response = await fetch("https://api.forwardemail.net/v1/emails", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: authHeader, + }, + body: emailData, + }); + + if (!response.ok) { + const errorText = await response.text(); + console.error( + "Email API response error:", + response.status, + errorText + ); + throw new Error(`Failed to send email: ${errorText}`); + } + + return Response.redirect("https://coryd.dev/contact/success", 301); + } catch (error) { + console.error("Error:", error.message); + return Response.redirect("https://coryd.dev/broken", 301); + } + } else { + return Response.redirect("https://coryd.dev/not-allowed", 301); + } + }, +}; diff --git a/workers/contact/wrangler.template.toml b/workers/contact/wrangler.template.toml new file mode 100644 index 0000000..2e30b7c --- /dev/null +++ b/workers/contact/wrangler.template.toml @@ -0,0 +1,12 @@ +name = "contact-form-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "contact-form-worker-production" +routes = [ + { pattern = "coryd.dev/api/contact", zone_id = "${CF_ZONE_ID}" } +] \ No newline at end of file diff --git a/workers/mastodon/index.js b/workers/mastodon/index.js new file mode 100644 index 0000000..d19b983 --- /dev/null +++ b/workers/mastodon/index.js @@ -0,0 +1,149 @@ +import { XMLParser } from "fast-xml-parser"; +import { convert } from "html-to-text"; +import { createClient } from "@supabase/supabase-js"; + +const BASE_URL = "https://coryd.dev"; + +export default { + async scheduled(event, env) { + await handleMastodonPost(env); + }, +}; + +async function handleMastodonPost(env) { + const mastodonApiUrl = "https://follow.coryd.dev/api/v1/statuses"; + const accessToken = env.MASTODON_ACCESS_TOKEN; + const rssFeedUrl = "https://coryd.dev/feeds/syndication"; + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); + + try { + const latestItems = await fetchRSSFeed(rssFeedUrl); + + for (let i = latestItems.length - 1; i >= 0; i--) { + const item = latestItems[i]; + const existingPost = await env.RSS_TO_MASTODON_NAMESPACE.get(item.link); + + if (existingPost) continue; + + const title = item.title; + const link = item.link; + const maxLength = 500; + const plainTextDescription = convert(item.description, { + wordwrap: false, + selectors: [ + { selector: "a", options: { ignoreHref: true } }, + { selector: "h1", options: { uppercase: false } }, + { selector: "h2", options: { uppercase: false } }, + { selector: "h3", options: { uppercase: false } }, + { selector: "*", format: "block" }, + ], + }); + + const cleanedDescription = plainTextDescription + .replace(/\s+/g, " ") + .trim(); + const content = truncateContent( + title, + cleanedDescription, + link, + maxLength + ); + + const mastodonPostUrl = await postToMastodon( + mastodonApiUrl, + accessToken, + content + ); + const timestamp = new Date().toISOString(); + + await env.RSS_TO_MASTODON_NAMESPACE.put(link, timestamp); + + if (link.includes("coryd.dev/posts")) { + const slug = link.replace(BASE_URL, ""); + await addMastodonUrlToPost(supabase, slug, mastodonPostUrl); + } + + console.log(`Posted stored URL: ${link}`); + } + + console.log("RSS processed successfully"); + } catch (error) { + console.error("Error in scheduled event:", error); + } +} + +async function addMastodonUrlToPost(supabase, slug, mastodonPostUrl) { + const { data, error } = await supabase + .from("posts") + .update({ mastodon_url: mastodonPostUrl }) + .eq("slug", slug); + + if (error) { + console.error("Error updating post:", error); + } else { + console.log(`Updated post with Mastodon URL: ${mastodonPostUrl}`); + } +} + +function truncateContent(title, description, link, maxLength) { + const baseLength = `${title}\n\n${link}`.length; + const availableSpace = maxLength - baseLength - 4; + let truncatedDescription = description; + + if (description.length > availableSpace) + truncatedDescription = + description + .substring(0, availableSpace) + .split(" ") + .slice(0, -1) + .join(" ") + "..."; + + truncatedDescription = truncatedDescription.replace(/\s+([.,!?;:])/g, "$1"); + + return `${title}\n\n${truncatedDescription}\n\n${link}`; +} + +async function fetchRSSFeed(rssFeedUrl) { + const response = await fetch(rssFeedUrl); + const rssText = await response.text(); + const parser = new XMLParser(); + const rssData = parser.parse(rssText); + const items = rssData.rss.channel.item; + + let latestItems = []; + + items.forEach((item) => { + const title = item.title; + const link = item.link; + const description = item.description; + latestItems.push({ title, link, description }); + }); + + return latestItems; +} + +async function postToMastodon(apiUrl, accessToken, content) { + const response = await fetch(apiUrl, { + method: "POST", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ status: content }), + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `Error posting to Mastodon: ${response.statusText} - ${errorText}` + ); + } + + const responseData = await response.json(); + + console.log("Posted to Mastodon successfully."); + + return responseData.url; +} diff --git a/workers/mastodon/wrangler.template.toml b/workers/mastodon/wrangler.template.toml new file mode 100644 index 0000000..3ffce7f --- /dev/null +++ b/workers/mastodon/wrangler.template.toml @@ -0,0 +1,21 @@ +name = "rss-to-mastodon-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[observability] +enabled = true + +[[kv_namespaces]] +binding = "RSS_TO_MASTODON_NAMESPACE" +id = "${RSS_TO_MASTODON_KV_NAMESPACE_ID}" + +[env.production] +name = "rss-to-mastodon-worker-production" +triggers = { crons = ["*/15 * * * *"] } + +[[env.production.kv_namespaces]] +binding = "RSS_TO_MASTODON_NAMESPACE" +id = "${RSS_TO_MASTODON_KV_NAMESPACE_ID}" \ No newline at end of file diff --git a/workers/playing/index.js b/workers/playing/index.js new file mode 100644 index 0000000..15b2240 --- /dev/null +++ b/workers/playing/index.js @@ -0,0 +1,45 @@ +import { createClient } from "@supabase/supabase-js"; + +export default { + async fetch(request, env) { + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); + + const { data, error } = await supabase + .from("optimized_latest_listen") + .select("*") + .single(); + + const headers = { + "Content-Type": "application/json", + "Cache-Control": "public, s-maxage=360, stale-while-revalidate=1080", + }; + + if (error) { + console.error("Error fetching data:", error); + return new Response( + JSON.stringify({ error: "Failed to fetch the latest track" }), + { headers } + ); + } + + if (!data) + return new Response( + JSON.stringify({ message: "No recent tracks found" }), + { headers } + ); + + const genreEmoji = data.genre_emoji; + const emoji = data.artist_emoji || genreEmoji; + + return new Response( + JSON.stringify({ + content: `${emoji || "🎧"} ${ + data.track_name + } by ${data.artist_name}`, + }), + { headers } + ); + }, +}; diff --git a/workers/playing/wrangler.template.toml b/workers/playing/wrangler.template.toml new file mode 100644 index 0000000..8b33c30 --- /dev/null +++ b/workers/playing/wrangler.template.toml @@ -0,0 +1,12 @@ +name = "now-playing-worker" +main = "./index.js" # Specify the entry point +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "now-playing-worker-production" +routes = [ + { pattern = "coryd.dev/api/now-playing", zone_id = "${CF_ZONE_ID}" } +] \ No newline at end of file diff --git a/workers/rebuild/index.js b/workers/rebuild/index.js new file mode 100644 index 0000000..0846001 --- /dev/null +++ b/workers/rebuild/index.js @@ -0,0 +1,20 @@ +export default { + async scheduled(event, env, ctx) { + const deployHookUrl = env.DEPLOY_HOOK_URL; + + const response = await fetch(deployHookUrl, { + method: "POST", + }); + + if (!response.ok) { + const errorText = await response.text(); + console.error( + `Error triggering deploy: ${response.statusText}`, + errorText + ); + return; + } + + console.log("Deploy triggered successfully"); + }, +}; diff --git a/workers/rebuild/wrangler.template.toml b/workers/rebuild/wrangler.template.toml new file mode 100644 index 0000000..5c1ae2d --- /dev/null +++ b/workers/rebuild/wrangler.template.toml @@ -0,0 +1,10 @@ +name = "scheduled-rebuild-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "scheduled-rebuild-worker-production" +triggers = {crons = ["0 * * * *"]} \ No newline at end of file diff --git a/workers/scrobble/index.js b/workers/scrobble/index.js new file mode 100644 index 0000000..951a8c6 --- /dev/null +++ b/workers/scrobble/index.js @@ -0,0 +1,250 @@ +import { createClient } from "@supabase/supabase-js"; +import { DateTime } from "luxon"; +import slugify from "slugify"; + +const sanitizeMediaString = (str) => { + const sanitizedString = str + .normalize("NFD") + .replace(/[\u0300-\u036f\u2010\-\.\?\(\)\[\]\{\}]/g, "") + .replace(/\.{3}/g, ""); + return slugify(sanitizedString, { + replacement: "-", + remove: /[#,&,+()$~%.'":*?<>{}]/g, + lower: true, + }); +}; + +const sendEmail = async (subject, text, authHeader, maxRetries = 3) => { + const emailData = new URLSearchParams({ + from: "coryd.dev ", + to: "hi@coryd.dev", + subject: subject, + text: text, + }).toString(); + + let attempt = 0; + let success = false; + + while (attempt < maxRetries && !success) { + attempt++; + try { + const response = await fetch("https://api.forwardemail.net/v1/emails", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: authHeader, + }, + body: emailData, + }); + + if (!response.ok) { + const responseText = await response.text(); + console.error( + `Attempt ${attempt}: Email API response error:`, + response.status, + responseText + ); + throw new Error(`Failed to send email: ${responseText}`); + } + + console.log("Email sent successfully on attempt", attempt); + success = true; + } catch (error) { + console.error(`Attempt ${attempt}: Error sending email:`, error.message); + + if (attempt < maxRetries) { + console.log( + `Retrying email send (attempt ${attempt + 1}/${maxRetries})...` + ); + } else { + console.error("All attempts to send email failed."); + } + } + } + + return success; +}; + +export default { + async fetch(request, env) { + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const FORWARDEMAIL_API_KEY = env.FORWARDEMAIL_API_KEY; + const ACCOUNT_ID_PLEX = env.ACCOUNT_ID_PLEX; + const supabase = createClient(supabaseUrl, supabaseKey); + const authHeader = "Basic " + btoa(`${FORWARDEMAIL_API_KEY}:`); + const url = new URL(request.url); + const params = url.searchParams; + const id = params.get("id"); + + if (!id) + return new Response(JSON.stringify({ status: "Bad request" }), { + headers: { "Content-Type": "application/json" }, + }); + + if (id !== ACCOUNT_ID_PLEX) + return new Response(JSON.stringify({ status: "Forbidden" }), { + headers: { "Content-Type": "application/json" }, + }); + + const contentType = request.headers.get("Content-Type") || ""; + if (!contentType.includes("multipart/form-data")) + return new Response( + JSON.stringify({ + status: "Bad request", + message: "Invalid Content-Type. Expected multipart/form-data.", + }), + { headers: { "Content-Type": "application/json" } } + ); + + try { + const data = await request.formData(); + const payload = JSON.parse(data.get("payload")); + + if (payload?.event === "media.scrobble") { + const artistName = payload["Metadata"]["grandparentTitle"]; + const albumName = payload["Metadata"]["parentTitle"]; + const trackName = payload["Metadata"]["title"]; + const listenedAt = Math.floor(DateTime.now().toSeconds()); + const artistKey = sanitizeMediaString(artistName); + const albumKey = `${artistKey}-${sanitizeMediaString(albumName)}`; + + let { data: artistData, error: artistError } = await supabase + .from("artists") + .select("*") + .ilike("name_string", artistName) + .single(); + + if (artistError && artistError.code === "PGRST116") { + const { error: insertArtistError } = await supabase + .from("artists") + .insert([ + { + mbid: null, + art: "4cef75db-831f-4f5d-9333-79eaa5bb55ee", + name: artistName, + slug: "/music", + tentative: true, + total_plays: 0, + }, + ]); + + if (insertArtistError) { + console.error( + "Error inserting artist: ", + insertArtistError.message + ); + return new Response( + JSON.stringify({ + status: "error", + message: insertArtistError.message, + }), + { headers: { "Content-Type": "application/json" } } + ); + } + + await sendEmail( + "New tentative artist record", + `A new tentative artist record was inserted:\n\nArtist: ${artistName}\nKey: ${artistKey}`, + authHeader + ); + ({ data: artistData, error: artistError } = await supabase + .from("artists") + .select("*") + .ilike("name_string", artistName) + .single()); + } + + if (artistError) { + console.error("Error fetching artist:", artistError.message); + return new Response( + JSON.stringify({ status: "error", message: artistError.message }), + { headers: { "Content-Type": "application/json" } } + ); + } + + let { data: albumData, error: albumError } = await supabase + .from("albums") + .select("*") + .ilike("key", albumKey) + .single(); + + if (albumError && albumError.code === "PGRST116") { + const { error: insertAlbumError } = await supabase + .from("albums") + .insert([ + { + mbid: null, + art: "4cef75db-831f-4f5d-9333-79eaa5bb55ee", + key: albumKey, + name: albumName, + tentative: true, + total_plays: 0, + artist: artistData.id, + }, + ]); + + if (insertAlbumError) { + console.error("Error inserting album:", insertAlbumError.message); + return new Response( + JSON.stringify({ + status: "error", + message: insertAlbumError.message, + }), + { headers: { "Content-Type": "application/json" } } + ); + } + + await sendEmail( + "New tentative album record", + `A new tentative album record was inserted:\n\nAlbum: ${albumName}\nKey: ${albumKey}\nArtist: ${artistName}`, + authHeader + ); + ({ data: albumData, error: albumError } = await supabase + .from("albums") + .select("*") + .ilike("key", albumKey) + .single()); + } + + if (albumError) { + console.error("Error fetching album:", albumError.message); + return new Response( + JSON.stringify({ status: "error", message: albumError.message }), + { headers: { "Content-Type": "application/json" } } + ); + } + + const { error: listenError } = await supabase.from("listens").insert([ + { + artist_name: artistData["name_string"] || artistName, + album_name: albumData["name"] || albumName, + track_name: trackName, + listened_at: listenedAt, + album_key: albumKey, + }, + ]); + + if (listenError) { + console.error("Error inserting listen:", listenError.message); + return new Response( + JSON.stringify({ status: "error", message: listenError.message }), + { headers: { "Content-Type": "application/json" } } + ); + } + + console.log("Listen record inserted successfully"); + } + + return new Response(JSON.stringify({ status: "success" }), { + headers: { "Content-Type": "application/json" }, + }); + } catch (e) { + console.error("Error processing request:", e.message); + return new Response( + JSON.stringify({ status: "error", message: e.message }), + { headers: { "Content-Type": "application/json" } } + ); + } + }, +}; diff --git a/workers/scrobble/wrangler.template.toml b/workers/scrobble/wrangler.template.toml new file mode 100644 index 0000000..2b5f490 --- /dev/null +++ b/workers/scrobble/wrangler.template.toml @@ -0,0 +1,15 @@ +name = "scrobble-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[observability] +enabled = true + +[env.production] +name = "scrobble-worker-production" +routes = [ + { pattern = "coryd.dev/api/scrobble*", zone_id = "${CF_ZONE_ID}" } +] diff --git a/workers/search/index.js b/workers/search/index.js new file mode 100644 index 0000000..061b788 --- /dev/null +++ b/workers/search/index.js @@ -0,0 +1,44 @@ +import { createClient } from "@supabase/supabase-js"; + +export default { + async fetch(request, env) { + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); + + const { searchParams } = new URL(request.url); + const query = searchParams.get("q") || ""; + const rawTypes = searchParams.getAll("type") || []; + const types = rawTypes.length > 0 ? rawTypes[0].split(",") : null; + + const page = parseInt(searchParams.get("page") || "1", 10); + const pageSize = parseInt(searchParams.get("pageSize") || "10", 10); + const offset = (page - 1) * pageSize; + + try { + const { data, error } = await supabase.rpc("search_optimized_index", { + search_query: query, + page_size: pageSize, + page_offset: offset, + types: types.length ? types : null, + }); + + if (error) { + console.error("Error fetching search data:", error); + return new Response(JSON.stringify({ results: [], total: 0 }), { + status: 500, + }); + } + + const total = data.length > 0 ? data[0].total_count : 0; + const results = data.map(({ total_count, ...item }) => item); + + return new Response(JSON.stringify({ results, total, page, pageSize }), { + headers: { "Content-Type": "application/json" }, + }); + } catch (error) { + console.error("Unexpected error:", error); + return new Response("Internal Server Error", { status: 500 }); + } + }, +}; \ No newline at end of file diff --git a/workers/search/wrangler.template.toml b/workers/search/wrangler.template.toml new file mode 100644 index 0000000..a59b41f --- /dev/null +++ b/workers/search/wrangler.template.toml @@ -0,0 +1,12 @@ +name = "search-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "search-worker-production" +routes = [ + { pattern = "coryd.dev/api/search*", zone_id = "${CF_ZONE_ID}" }, +] \ No newline at end of file diff --git a/workers/sitemap/index.js b/workers/sitemap/index.js new file mode 100644 index 0000000..b362d76 --- /dev/null +++ b/workers/sitemap/index.js @@ -0,0 +1,51 @@ +import { createClient } from "@supabase/supabase-js"; + +export default { + async fetch(request, env) { + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); + + try { + const { data, error } = await supabase + .from("optimized_sitemap") + .select("url, lastmod, changefreq, priority"); + + if (error) { + console.error("Error fetching sitemap data:", error); + return new Response("Error fetching sitemap data", { status: 500 }); + } + + const sitemapXml = generateSitemapXml(data); + return new Response(sitemapXml, { + headers: { + "Content-Type": "application/xml", + "Access-Control-Allow-Origin": "*", + }, + }); + } catch (error) { + console.error("Unexpected error:", error); + return new Response("Internal Server Error", { status: 500 }); + } + }, +}; + +function generateSitemapXml(data) { + const urls = data + .map( + ({ url, lastmod, changefreq, priority }) => ` + + ${url} + ${lastmod ? `${new Date(lastmod).toISOString()}` : ""} + ${changefreq} + ${priority} + + ` + ) + .join(""); + + return ` + + ${urls} + `; +} diff --git a/workers/sitemap/wrangler.template.toml b/workers/sitemap/wrangler.template.toml new file mode 100644 index 0000000..aa682af --- /dev/null +++ b/workers/sitemap/wrangler.template.toml @@ -0,0 +1,12 @@ +name = "sitemap-worker" +main = "./index.js" +compatibility_date = "2023-01-01" + +account_id = "${CF_ACCOUNT_ID}" +workers_dev = true + +[env.production] +name = "sitemap-worker-production" +routes = [ + { pattern = "coryd.dev/sitemap.xml", zone_id = "${CF_ZONE_ID}" }, +] \ No newline at end of file