my website at ewancroft.uk
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial Svelte set up

+2303 -2174
+18 -46
.gitignore
··· 1 - /public/ 2 - /resources/_gen/ 3 - /assets/jsconfig.json 4 - /hugo.log 5 - /hugo_stats.json 6 - /.hugo_build.lock 7 - /hugo.exe 8 - /hugo.darwin 9 - /hugo.linux 10 - 11 - # Why the hell does this exist? It's just a bloodstain on a perfectly white shirt! 12 - .DS_Store 1 + node_modules 13 2 14 - # Node.js dependencies 15 - /node_modules/ 16 - /package-lock.json 17 - /yarn.lock 3 + # Output 4 + .output 5 + .vercel 6 + .netlify 7 + .wrangler 8 + /.svelte-kit 9 + /build 18 10 19 - # Logs 20 - npm-debug.log* 21 - yarn-debug.log* 22 - yarn-error.log* 11 + # OS 12 + .DS_Store 13 + Thumbs.db 23 14 24 - # Environment variables 15 + # Env 25 16 .env 26 - .env.local 27 - .env.development.local 28 - .env.test.local 29 - .env.production.local 30 - 31 - # Build output 32 - /dist/ 33 - /build/ 34 - 35 - # IDE specific files 36 - /.vscode/ 37 - .idea/ 38 - *.sublime-project 39 - *.sublime-workspace 40 - 41 - # Temporary files 42 - *.tmp 43 - *.temp 17 + .env.* 18 + !.env.example 19 + !.env.test 44 20 45 - # Server-specific files 46 - /nginx.conf 47 - /nginx/ 48 - /apache2.conf 49 - /httpd.conf 50 - /uwsgi.ini 51 - /gunicorn.conf.py 21 + # Vite 22 + vite.config.js.timestamp-* 23 + vite.config.ts.timestamp-*
+1
.npmrc
··· 1 + engine-strict=true
+4
.prettierignore
··· 1 + # Package Managers 2 + package-lock.json 3 + pnpm-lock.yaml 4 + yarn.lock
+15
.prettierrc
··· 1 + { 2 + "useTabs": true, 3 + "singleQuote": true, 4 + "trailingComma": "none", 5 + "printWidth": 100, 6 + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], 7 + "overrides": [ 8 + { 9 + "files": "*.svelte", 10 + "options": { 11 + "parser": "svelte" 12 + } 13 + } 14 + ] 15 + }
-8
.vscode/settings.json
··· 1 - { 2 - "markdownlint.config": { 3 - "MD033": { 4 - "allowed_elements": ["iframe"] 5 - } 6 - } 7 - } 8 -
-30
LICENCE
··· 1 - # MIT and CC BY 4.0 Licence 2 - 3 - The code files in this repository, including HTML, CSS, and JS files, are under the MIT Licence, whereas the text and imagery featured on this website are under the CC BY 4.0 Licence. 4 - 5 - ## MIT Licence 6 - 7 - Copyright © 2025 Ewan Croft 8 - 9 - 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, sublicence, 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: 10 - 11 - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 - 13 - 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. 14 - 15 - ## CC BY 4.0 Licence 16 - 17 - Copyright © 2025 Ewan Croft 18 - 19 - This work (including text and imagery) is licenced under a Creative Commons Attribution 4.0 International Licence. 20 - 21 - You are free to: 22 - 23 - - Share — copy and redistribute the material in any medium or format 24 - - Adapt — remix, transform, and build upon the material for any purpose, even commercially. 25 - 26 - Under the following terms: 27 - 28 - - Attribution — You must give appropriate credit, provide a link to the licence, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 29 - 30 - Full Licence details: [CC BY 4.0](https://creativecommons.org/Licences/by/4.0/).
+24 -91
README.md
··· 1 - # Ewan's Web Corner 1 + # sv 2 2 3 - Welcome to the repository for **Ewan's Web Corner**, my personal website. This site is where I share my thoughts on coding, technology, and various aspects of my life. 3 + Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli). 4 4 5 - ## Site Overview 5 + ## Creating a project 6 6 7 - The site is built using **atproto** technology, and the structure is optimised to display posts, profile information, and various content in a user-friendly way. It's also designed to be easy to navigate, with pages like **About** and **Verification** accessible directly from the sidebar. 7 + If you're seeing this, you've probably already done this step. Congrats! 8 8 9 - It is based on the fantastic work by [fei.chicory.blue](https://codeberg.org/fei-chicory-blue/atproto-site), just with my own tweaks. 9 + ```bash 10 + # create a new project in the current directory 11 + npx sv create 10 12 11 - ### Features 12 - 13 - - **Customisable Layout:** The page layout features a left sidebar with profile info, navigation links, and pagination. The right column is dedicated to displaying posts. 14 - - **Posts:** The site supports multiple post types, including text posts, image posts, and embedded content. Posts can be customised with rich media, such as images and embedded cards. 15 - - **Profile Information:** The left sidebar includes a space for a profile picture, username, description, and external links. 16 - - **Mobile Optimisation:** The site is optimised for mobile browsing, with a responsive design that adjusts to different screen sizes. 17 - 18 - For more details on customisation, refer to the documentation on WhiteWind [here](https://whtwnd.com/did:plc:xz3euvkhf44iadavovbsmqoo/3laxrz4dl4s2f). 19 - 20 - ### Powered by atproto 21 - 22 - The site is powered by the [atproto platform](https://atproto.com), which enables decentralised content hosting. This allows you to integrate various platforms and manage your content seamlessly. 23 - 24 - ## Running the Site with Docker 25 - 26 - To run the site using Docker Compose, follow these steps: 13 + # create a new project in my-app 14 + npx sv create my-app 15 + ``` 27 16 28 - 1. Build and start the Docker container: 17 + ## Developing 29 18 30 - ```sh 31 - docker compose up --build -d 32 - ``` 19 + Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 33 20 34 - This will build your Docker image and start the website inside a Docker container, making it accessible on port `3002`. 21 + ```bash 22 + npm run dev 35 23 36 - ## Deploying with Cloudflare Tunnel 24 + # or start the server and open the app in a new browser tab 25 + npm run dev -- --open 26 + ``` 37 27 38 - To deploy the site through a Cloudflare Tunnel, follow these steps: 28 + ## Building 39 29 40 - ### On macOS 30 + To create a production version of your app: 41 31 42 - 1. Install the Cloudflare Tunnel client (`cloudflared`): 32 + ```bash 33 + npm run build 34 + ``` 43 35 44 - ```sh 45 - brew install cloudflare/cloudflare/cloudflared 46 - ``` 36 + You can preview the production build with `npm run preview`. 47 37 48 - 2. Authenticate `cloudflared` with your Cloudflare account: 49 - 50 - ```sh 51 - cloudflared login 52 - ``` 53 - 54 - 3. Create a tunnel and give it a name: 55 - 56 - ```sh 57 - cloudflared tunnel create my-tunnel 58 - ``` 59 - 60 - 4. Configure the tunnel to route traffic to your Docker container: 61 - 62 - ```sh 63 - cloudflared tunnel route dns my-tunnel mywebsite.example.com 64 - ``` 65 - 66 - 5. Start the tunnel and route traffic to your local Docker container running on port `3002`: 67 - 68 - ```sh 69 - cloudflared tunnel --url http://localhost:3002 run my-tunnel 70 - ``` 71 - 72 - ### On Ubuntu Server 73 - 74 - 1. Install the Cloudflare Tunnel client (`cloudflared`): 75 - 76 - ```sh 77 - sudo apt-get update 78 - sudo apt-get install -y wget 79 - wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb 80 - sudo dpkg -i cloudflared-linux-amd64.deb 81 - ``` 82 - 83 - 2. Authenticate `cloudflared` with your Cloudflare account: 84 - 85 - ```sh 86 - cloudflared login 87 - ``` 88 - 89 - 3. Create a tunnel and give it a name: 90 - 91 - ```sh 92 - cloudflared tunnel create my-tunnel 93 - ``` 94 - 95 - 4. Configure the tunnel to route traffic to your Docker container: 96 - 97 - ```sh 98 - cloudflared tunnel route dns my-tunnel mywebsite.example.com 99 - ``` 100 - 101 - 5. Start the tunnel and route traffic to your local Docker container running on port `3002`: 102 - 103 - ```sh 104 - cloudflared tunnel --url http://localhost:3002 run my-tunnel 105 - ``` 38 + > To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
-48
assets/css/base.css
··· 1 - body { 2 - margin: 0; 3 - background: var(--background-color); 4 - color: var(--text-color); 5 - line-height: 1.5; 6 - font-family: "madecarvingsoft", "Trebuchet MS", sans-serif; 7 - overflow: hidden; 8 - } 9 - 10 - a { 11 - color: var(--link-color); 12 - text-decoration: none; 13 - } 14 - 15 - a:hover { 16 - text-decoration: none; 17 - color: var(--text-color); 18 - } 19 - 20 - code { 21 - background: var(--header-footer-bg); 22 - white-space: pre-wrap; 23 - } 24 - 25 - pre code { 26 - display: block; 27 - white-space: pre; 28 - overflow-x: auto; 29 - } 30 - 31 - blockquote { 32 - padding-left: 16px; 33 - margin: 0; 34 - border-left: 4px solid var(--header-footer-bg); 35 - } 36 - 37 - table { 38 - display: block; 39 - word-break: normal; 40 - border-collapse: collapse; 41 - overflow-x: auto; 42 - } 43 - 44 - th, 45 - td { 46 - padding: 8px; 47 - border: 1px solid var(--header-footer-bg); 48 - }
-248
assets/css/components.css
··· 1 - profile-picture img { 2 - display: block; 3 - height: 128px; 4 - margin: 0 auto; 5 - border-radius: 50%; 6 - object-fit: cover; 7 - box-shadow: 0 0 10px 3px var(--link-color); 8 - } 9 - 10 - profile-username { 11 - display: block; 12 - margin-top: 16px; 13 - font-size: 2rem; 14 - } 15 - 16 - profile-description { 17 - margin-top: 8px; 18 - font-size: 1rem; 19 - } 20 - 21 - nav { 22 - margin-top: 24px; 23 - } 24 - 25 - .links { 26 - max-width: 200px; 27 - margin: 0 auto; 28 - display: flex; 29 - flex-direction: column; 30 - gap: 10px; 31 - } 32 - 33 - .links a { 34 - display: flex; 35 - height: 48px; 36 - background: var(--button-bg); 37 - color: var(--link-color); 38 - border-radius: 8px; 39 - justify-content: center; 40 - align-items: center; 41 - transition: background 0.25s; 42 - text-decoration: none; 43 - } 44 - 45 - .links a:hover { 46 - text-decoration: none; 47 - color: var(--link-hover-color); 48 - } 49 - 50 - nav .links a { 51 - color: var(--text-color); 52 - transition: color 0.3s ease, background 0.3s ease, transform 0.3s ease; 53 - } 54 - 55 - nav .links a:hover { 56 - color: var(--link-hover-color);; 57 - background: var(--button-hover-bg); 58 - transform: scale(1.1) 59 - } 60 - 61 - #theme-toggle { 62 - display: block; 63 - margin: 0 auto; 64 - padding: 10px 20px; 65 - background: var(--button-bg); 66 - color: var(--text-color); 67 - border: none; 68 - border-radius: 8px; 69 - cursor: pointer; 70 - transition: background 0.25s, color 0.25s; 71 - text-align: center; 72 - } 73 - 74 - #theme-toggle:hover { 75 - background: var(--button-hover-bg); 76 - color: var(--text-color); 77 - } 78 - 79 - if-pagination { 80 - display: block; 81 - margin-top: 20px; 82 - } 83 - 84 - .pagination { 85 - margin-bottom: 48px; 86 - text-align: center; 87 - } 88 - 89 - .credit { 90 - font-size: 11px; 91 - opacity: 0.7; 92 - color: var(--text-color); 93 - text-align: center; 94 - margin-top: 16px; 95 - } 96 - 97 - .credit a { 98 - color: var(--link-color); 99 - text-decoration: none; 100 - } 101 - 102 - .credit a:hover { 103 - color: var(--link-hover-color); 104 - } 105 - 106 - .post { 107 - display: block; 108 - max-width: 500px; 109 - padding: 20px; 110 - margin: 10px auto; 111 - background: var(--header-footer-bg); 112 - word-break: break-word; 113 - border-radius: 8px; 114 - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); 115 - } 116 - 117 - .post img { 118 - display: block; 119 - width: 100%; 120 - cursor: pointer; 121 - } 122 - 123 - .reply-indicator, 124 - .author { 125 - margin-bottom: 12px; 126 - } 127 - 128 - .author { 129 - display: flex; 130 - align-items: center; 131 - gap: 8px; 132 - } 133 - 134 - author-pfp { 135 - display: inline-block; 136 - vertical-align: middle; 137 - width: 30px; 138 - } 139 - 140 - author-pfp img { 141 - height: 30px; 142 - width: 30px; 143 - aspect-ratio: 1 / 1; 144 - object-fit: cover; 145 - border-radius: 50%; 146 - } 147 - 148 - author-username, 149 - title-content { 150 - font-weight: bold; 151 - } 152 - 153 - author-username { 154 - font-weight: bold; 155 - } 156 - 157 - author-handle { 158 - opacity: 0.5; 159 - } 160 - 161 - image-post image-content { 162 - display: block; 163 - margin: 12px 0; 164 - } 165 - 166 - imageset-post image-content { 167 - margin: 12px 0; 168 - display: grid; 169 - grid-template-columns: 1fr 1fr; 170 - gap: 6px; 171 - } 172 - 173 - imageset-post image-content img { 174 - height: 100%; 175 - object-fit: cover; 176 - } 177 - 178 - .footer { 179 - margin-top: 12px; 180 - display: flex; 181 - justify-content: space-between; 182 - align-items: center; 183 - font-size: 14px; 184 - color: var(--text-color); 185 - } 186 - 187 - .created-at { 188 - color: var(--button-bg); 189 - } 190 - 191 - .remote-link { 192 - font-size: 14px; 193 - } 194 - 195 - .post .embed-container { 196 - display: block; 197 - margin-top: 24px; 198 - background: var(--embed-bg); 199 - border-radius: var(--embed-border-radius); 200 - padding: 16px; 201 - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15); 202 - } 203 - 204 - .frontpage-post .embed-container { 205 - display: none; 206 - } 207 - 208 - .post .embed-card { 209 - display: block; 210 - margin-top: 12px; 211 - background: var(--embed-bg); 212 - border-radius: 8px; 213 - padding: 12px; 214 - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); 215 - overflow: hidden; 216 - } 217 - 218 - .post .embed-card img { 219 - max-height: 256px; 220 - object-fit: cover; 221 - border-radius: 8px; 222 - } 223 - 224 - .post .embed-card .embed-content { 225 - padding: 16px; 226 - } 227 - 228 - .post .embed-card .embed-title { 229 - font-weight: bold; 230 - } 231 - 232 - .post image-content img { 233 - border-radius: 8px; 234 - } 235 - 236 - noscript { 237 - display: block; 238 - text-align: center; 239 - font-size: 1.2rem; 240 - color: var(--text-color); 241 - background-color: var(--header-footer-bg); 242 - padding: 10px; 243 - border-radius: 8px; 244 - margin: 20px auto; 245 - width: 70%; 246 - max-width: 600px; 247 - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); 248 - }
-12
assets/css/fonts.css
··· 1 - @font-face { 2 - font-family: 'madecarvingsoft'; 3 - src: url('/assets/fonts/madecarvingsoft.woff2') format('woff2'), 4 - url('/assets/fonts/madecarvingsoft.woff') format('woff'); 5 - } 6 - 7 - @font-face { 8 - font-family: 'madecarvingsoft'; 9 - src: url('/assets/fonts/madecarvingsoftsemibold.woff2') format('woff2'), 10 - url('/assets/fonts/madecarvingsoftsemibold.woff') format('woff'); 11 - font-weight: bold; 12 - }
-39
assets/css/layout.css
··· 1 - #page { 2 - height: 100vh; 3 - display: flex; 4 - } 5 - 6 - #column-left { 7 - flex: 1; 8 - background: var(--header-footer-bg); 9 - display: flex; 10 - justify-content: center; 11 - align-items: center; 12 - flex-direction: column; 13 - padding: 0; 14 - } 15 - 16 - #sidebar { 17 - display: flex; 18 - flex-direction: column; 19 - align-items: center; 20 - justify-content: center; 21 - width: 100%; 22 - } 23 - 24 - #profile-area { 25 - max-height: 100%; 26 - padding: 32px; 27 - text-align: center; 28 - overflow-y: auto; 29 - } 30 - 31 - #column-right { 32 - flex: 2; 33 - padding: 0; 34 - } 35 - 36 - main { 37 - max-height: 100%; 38 - overflow-y: auto; 39 - }
-72
assets/css/media-queries.css
··· 1 - @media screen and (max-width: 800px) { 2 - body { 3 - overflow: auto; 4 - } 5 - 6 - #page { 7 - display: block; 8 - } 9 - 10 - #column-left { 11 - justify-content: center; 12 - padding: 24px 16px; 13 - } 14 - 15 - #column-right { 16 - padding: 24px 16px; 17 - } 18 - 19 - .footer { 20 - flex-direction: row; 21 - align-items: center; 22 - gap: 16px; 23 - } 24 - 25 - .author { 26 - gap: 8px; 27 - } 28 - 29 - .created-at, 30 - .remote-link { 31 - font-size: 12px; 32 - } 33 - 34 - .links { 35 - flex-direction: column; 36 - gap: 8px; 37 - } 38 - 39 - .links a { 40 - flex: 1; 41 - height: 40px; 42 - border-radius: 20px; 43 - margin: 4px 0; 44 - } 45 - 46 - .author-pfp img { 47 - width: 30px; 48 - height: 30px; 49 - } 50 - 51 - .post { 52 - margin: 12px 8px; 53 - padding: 16px; 54 - } 55 - 56 - .embed-container, 57 - .embed-card { 58 - margin: 12px 0; 59 - padding: 12px; 60 - } 61 - 62 - nav a { 63 - margin-top: 30px; 64 - padding: 5px; 65 - } 66 - 67 - noscript { 68 - font-size: 1rem; 69 - padding: 15px; 70 - width: 90%; 71 - } 72 - }
-33
assets/css/post-transitions.css
··· 1 - /* Post transition styles */ 2 - .post-transition { 3 - opacity: 1; 4 - transform: translateY(0); 5 - transition: opacity 0.4s ease, transform 0.4s ease; 6 - } 7 - 8 - /* Initial state controlled by JavaScript */ 9 - .post { 10 - will-change: opacity, transform; 11 - } 12 - 13 - /* Post container transitions */ 14 - post-container { 15 - display: block; 16 - min-height: 100px; /* Provide space for loading state */ 17 - } 18 - 19 - /* Optional loading indicator between page changes */ 20 - post-container:empty::after { 21 - content: "Loading..."; 22 - display: block; 23 - text-align: center; 24 - padding: 20px; 25 - color: var(--text-color); 26 - font-style: italic; 27 - opacity: 0.7; 28 - } 29 - 30 - /* Smoothly handle tag pages */ 31 - if-tag-page .post { 32 - transition: opacity 0.4s ease, transform 0.4s ease; 33 - }
-182
assets/css/variables.css
··· 1 - @media (prefers-color-scheme: dark) { 2 - :root { 3 - /* Default (green) */ 4 - --background-color: #2b3728; 5 - --text-color: #fff; 6 - --header-footer-bg: #0a1607; 7 - --button-bg: #2b3728; 8 - --button-hover-bg: #204d22; 9 - --embed-bg: #304028; 10 - --embed-border-radius: 8px; 11 - --link-color: #29a12d; 12 - --link-hover-color: #8ced91; 13 - } 14 - 15 - :root.red { 16 - --background-color: #4a0e0e; 17 - --text-color: #fff; 18 - --header-footer-bg: #300707; 19 - --button-bg: #4a0e0e; 20 - --button-hover-bg: #650a0a; 21 - --embed-bg: #530e0e; 22 - --link-color: #ff4d4d; 23 - --link-hover-color: #ff9999; 24 - } 25 - 26 - :root.blue { 27 - --background-color: #1a2a4a; 28 - --text-color: #fff; 29 - --header-footer-bg: #0d1530; 30 - --button-bg: #1a2a4a; 31 - --button-hover-bg: #20346d; 32 - --embed-bg: #253a67; 33 - --link-color: #4da6ff; 34 - --link-hover-color: #99ccff; 35 - } 36 - 37 - :root.yellow { 38 - --background-color: #665a0e; 39 - --text-color: #fff; 40 - --header-footer-bg: #4c470a; 41 - --button-bg: #665a0e; 42 - --button-hover-bg: #7a6f0c; 43 - --embed-bg: #806710; 44 - --link-color: #ffd633; 45 - --link-hover-color: #ffea80; 46 - } 47 - 48 - :root.monochrome { 49 - --background-color: #333; 50 - --text-color: #fff; 51 - --header-footer-bg: #1a1a1a; 52 - --button-bg: #333; 53 - --button-hover-bg: #4d4d4d; 54 - --embed-bg: #404040; 55 - --link-color: #ccc; 56 - --link-hover-color: #eee; 57 - } 58 - 59 - :root.orange { 60 - --background-color: #5a3f0a; 61 - --text-color: #fff; 62 - --header-footer-bg: #3b2a07; 63 - --button-bg: #5a3f0a; 64 - --button-hover-bg: #6f4b0a; 65 - --embed-bg: #64410a; 66 - --link-color: #ff8c00; 67 - --link-hover-color: #ffb347; 68 - } 69 - 70 - :root.indigo { 71 - --background-color: #2e1a4a; 72 - --text-color: #fff; 73 - --header-footer-bg: #1f1130; 74 - --button-bg: #2e1a4a; 75 - --button-hover-bg: #36265d; 76 - --embed-bg: #392a66; 77 - --link-color: #7a5cff; 78 - --link-hover-color: #b3a0ff; 79 - } 80 - 81 - :root.violet { 82 - --background-color: #4a0e4a; 83 - --text-color: #fff; 84 - --header-footer-bg: #300730; 85 - --button-bg: #4a0e4a; 86 - --button-hover-bg: #650a65; 87 - --embed-bg: #530e53; 88 - --link-color: #d966ff; 89 - --link-hover-color: #e699ff; 90 - } 91 - } 92 - 93 - @media (prefers-color-scheme: light) { 94 - :root { 95 - /* Default (green) */ 96 - --background-color: #91c991; 97 - --header-footer-bg: #e2f4e2; 98 - --text-color: #333; 99 - --button-bg: #6fbf6f; 100 - --button-hover-bg: #91c991; 101 - --embed-bg: #b1ddb1; 102 - --link-color: #2d6a2f; 103 - --link-hover-color: #222222; 104 - } 105 - 106 - :root.red { 107 - --background-color: #f8c2c2; 108 - --header-footer-bg: #ffe5e5; 109 - --text-color: #300707; 110 - --button-bg: #e89a9a; 111 - --button-hover-bg: #f8c2c2; 112 - --embed-bg: #ffcccc; 113 - --link-color: #a11414; 114 - --link-hover-color: #222222; 115 - } 116 - 117 - :root.blue { 118 - --background-color: #c2d9f8; 119 - --header-footer-bg: #e5f0ff; 120 - --text-color: #0d1530; 121 - --button-bg: #9bbce8; 122 - --button-hover-bg: #c2d9f8; 123 - --embed-bg: #d4e5ff; 124 - --link-color: #104b8a; 125 - --link-hover-color: #222222; 126 - } 127 - 128 - :root.yellow { 129 - --background-color: #fff6c2; 130 - --header-footer-bg: #fffbe5; 131 - --text-color: #4c470a; 132 - --button-bg: #ebdf9f; 133 - --button-hover-bg: #fff6c2; 134 - --embed-bg: #fff2ad; 135 - --link-color: #8a7a10; 136 - --link-hover-color: #222222; 137 - } 138 - 139 - :root.monochrome { 140 - --background-color: #f0f0f0; 141 - --header-footer-bg: #ffffff; 142 - --text-color: #222; 143 - --button-bg: #bfbfbf; 144 - --button-hover-bg: #d9d9d9; 145 - --embed-bg: #e6e6e6; 146 - --link-color: #666; 147 - --link-hover-color: #222222; 148 - } 149 - 150 - :root.orange { 151 - --background-color: #f8e4d1; 152 - --header-footer-bg: #fff0e0; 153 - --text-color: #5a3f0a; 154 - --button-bg: #f5d4b0; 155 - --button-hover-bg: #f8e4d1; 156 - --embed-bg: #fae7cf; 157 - --link-color: #d2691e; 158 - --link-hover-color: #222222; 159 - } 160 - 161 - :root.indigo { 162 - --background-color: #d1d0f8; 163 - --header-footer-bg: #e0e0ff; 164 - --text-color: #1a0e4a; 165 - --button-bg: #b0b3f5; 166 - --button-hover-bg: #d1d0f8; 167 - --embed-bg: #c2c5fa; 168 - --link-color: #4a3aff; 169 - --link-hover-color: #222222; 170 - } 171 - 172 - :root.violet { 173 - --background-color: #f0d1f8; 174 - --header-footer-bg: #ffe0ff; 175 - --text-color: #4a0e4a; 176 - --button-bg: #e0b3f5; 177 - --button-hover-bg: #f0d1f8; 178 - --embed-bg: #e0c2fa; 179 - --link-color: #a64ca6; 180 - --link-hover-color: #222222; 181 - } 182 - }
assets/fonts/madecarvingsoft.woff2 static/fonts/madecarvingsoft.woff2
assets/fonts/madecarvingsoftsemibold.woff2 static/fonts/madecarvingsoftsemibold.woff2
assets/images/embed-preview.png static/images/embed-preview.png
assets/images/favicon/about.txt static/images/favicon/about.txt
assets/images/favicon/android-chrome-192x192.png static/images/favicon/android-chrome-192x192.png
assets/images/favicon/android-chrome-512x512.png static/images/favicon/android-chrome-512x512.png
assets/images/favicon/apple-touch-icon.png static/images/favicon/apple-touch-icon.png
assets/images/favicon/favicon-16x16.png static/images/favicon/favicon-16x16.png
assets/images/favicon/favicon-32x32.png static/images/favicon/favicon-32x32.png
assets/images/favicon/site.webmanifest static/images/favicon/site.webmanifest
-1004
assets/scripts/atproto.js
··· 1 - 'use strict'; 2 - async function atprotoSite(options) { 3 - 4 - // globalvar 5 - 6 - let md; 7 - if (window.markdownit) { 8 - md = window.markdownit(); 9 - } else { 10 - // if the markdown parser isn't loaded, just make it text with linebreaks 11 - md = { 12 - render: (markdown) => { 13 - const p = document.createElement('p'); 14 - p.innerText = markdown; 15 - return p.outerHTML; 16 - } 17 - } 18 - } 19 - 20 - // html elements 21 - const refs = { 22 - scrollers: document.querySelectorAll('.atproto-site-scroll'), 23 - postContainer: document.querySelector('post-container'), 24 - pagination: document.querySelector('if-pagination'), 25 - ifPreviousPage: document.querySelector('if-previous-page'), 26 - ifNextPage: document.querySelector('if-next-page'), 27 - currentPageNumber:document.querySelector('current-page-number'), 28 - previousPageLink: wrapLink(document, '', 'previous-page-link'), 29 - nextPageLink: wrapLink(document, '', 'next-page-link') 30 - } 31 - // places to store loaded info 32 - const cache = { 33 - users: {}, 34 - records: {}, 35 - page: 1 36 - } 37 - const stream = { 38 - records: [], 39 - queues: [] 40 - } 41 - function addQueue(user, collection, filter) { 42 - stream.queues.push({ 43 - user: user, 44 - collection: collection, 45 - records: [], 46 - cursor: '', 47 - reachedEnd: false, 48 - filter: filter 49 - }); 50 - } 51 - 52 - // Modal 53 - 54 - const modal = document.createElement('div'); 55 - modal.style.position = 'fixed'; 56 - modal.style.inset = '0'; 57 - modal.style.display = 'flex'; 58 - modal.style.flexDirection = 'column'; 59 - modal.style.justifyContent = 'center'; 60 - modal.style.alignItems = 'center'; 61 - modal.style.pointerEvents = 'none'; 62 - 63 - const modalImage = document.createElement('img'); 64 - modalImage.style.display = 'block'; 65 - modalImage.style.width = 'auto'; 66 - modalImage.style.height = 'auto'; 67 - modalImage.style.maxHeight = '90%'; 68 - modalImage.style.maxWidth = '90%'; 69 - modalImage.style.pointerEvents = 'auto'; 70 - modal.appendChild(modalImage); 71 - 72 - const modalBackground = document.createElement('div'); 73 - modalBackground.style.position = 'fixed'; 74 - modalBackground.style.inset = '0'; 75 - modalBackground.style.background = '#000000bb'; 76 - modalBackground.onclick = function () { 77 - modal.remove(); 78 - this.remove(); 79 - } 80 - 81 - const modalAlt = document.createElement('div'); 82 - modalAlt.style.maxWidth = '90%'; 83 - modalAlt.style.padding = '.5em'; 84 - modalAlt.style.marginTop = '12px'; 85 - modalAlt.style.background = '#222222'; 86 - modalAlt.style.color = '#ffffff'; 87 - modalAlt.style.border = '1px solid #555555'; 88 - modalAlt.style.borderRadius = '6px'; 89 - modalAlt.style.overflowY = 'auto'; 90 - modalAlt.style.pointerEvents = 'auto'; 91 - modalAlt.ariaHidden = 'true'; 92 - modal.appendChild(modalAlt); 93 - 94 - function openModal(src, alt) { 95 - modalImage.src = src; 96 - modalImage.alt = alt; 97 - modalAlt.textContent = alt; 98 - document.body.appendChild(modalBackground); 99 - document.body.appendChild(modal); 100 - } 101 - 102 - // Sources 103 - 104 - const sources = [ 105 - { 106 - name: 'Bluesky', 107 - createQueue(user) { 108 - let filter = function (record) { 109 - if (!options.showReplies && record.value.reply) { 110 - return false; 111 - } 112 - if (options.hideNSFW) { 113 - // filters out all current self labels 114 - if (record.value.labels && record.value.labels.values) { 115 - for (let label of record.value.labels.values) { 116 - if (label.val === "porn" || label.val === "graphic-media" || label.val === "sexual" || label.val === "nudity") { 117 - return false; 118 - } 119 - } 120 - } 121 - } 122 - return true; 123 - } 124 - addQueue(user, 'app.bsky.feed.post', filter); 125 - }, 126 - createPost(record, info) { 127 - if (info.collection === 'app.bsky.feed.post') { 128 - const url = `https://bsky.app/profile/${info.DID}/post/${info.rkey}`; 129 - let images = []; 130 - 131 - // construct embed based on embed type 132 - let externalEmbed; 133 - let embed = record.value.embed; 134 - if (embed) { 135 - if (embed.$type === 'app.bsky.embed.images') { 136 - images = embed.images; 137 - } else if (embed.$type === 'app.bsky.embed.recordWithMedia') { 138 - if (embed.media.images) { 139 - images = embed.media.images; 140 - } else if (embed.media.video) { 141 - externalEmbed = { title: embed.alt, text: 'Open video on Bluesky', url: url }; 142 - } 143 - } else if (embed.$type === 'app.bsky.embed.external') { 144 - externalEmbed = { 145 - title: embed.external.title, 146 - text: embed.external.description, 147 - url: embed.external.uri, 148 - user: record.author, 149 - blob: embed.external.thumb 150 - } 151 - } else if (embed.$type === 'app.bsky.embed.video') { 152 - externalEmbed = { title: embed.alt, text: 'Open video on Bluesky', url: url }; 153 - } else { 154 - externalEmbed = { text: 'Open embedded content on Bluesky', url: url }; 155 - } 156 - } 157 - 158 - // pick type of post to create 159 - let post; 160 - if (images.length === 1) { 161 - post = createCustomElement('image-post'); 162 - } else if (images.length > 1) { 163 - post = createCustomElement('imageset-post'); 164 - } else { 165 - post = createCustomElement('text-post'); 166 - } 167 - 168 - // replies 169 - if (record.value.reply) { 170 - removeCustomElements(post, 'if-not-reply'); 171 - const replyInfo = parseURI(record.value.reply.parent.uri); 172 - wrapLink(post, `https://bsky.app/profile/${replyInfo.DID}/post/${replyInfo.rkey}`, 'reply-link-wrapper'); 173 - } else { 174 - removeCustomElements(post, 'if-reply'); 175 - } 176 - 177 - removeCustomElements(post, 'if-title'); 178 - addText(post, record.value.text); 179 - for (let image of images) { 180 - addImage(post, record.author, image.image, image.alt); 181 - } 182 - if (externalEmbed) { 183 - addEmbed(post, externalEmbed); 184 - } 185 - addRemoteLink(post, url, 'Bluesky'); 186 - addCreatedAt(post, record.value.createdAt); 187 - return post; 188 - } 189 - }, 190 - }, 191 - { 192 - name: 'WhiteWind', 193 - createQueue(user) { 194 - let filter; 195 - if (!options.showDrafts) { 196 - filter = (record) => record.value.visibility === 'public'; 197 - } 198 - addQueue(user, 'com.whtwnd.blog.entry', filter); 199 - }, 200 - createPost(record, info, threshold) { 201 - if (info.collection === 'com.whtwnd.blog.entry') { 202 - const post = createCustomElement('text-post'); 203 - removeCustomElements(post, 'if-reply'); 204 - addText(post, record.value.title, 'title-content'); 205 - addMarkdown(post, record.value.content, threshold); 206 - addRemoteLink(post, `https://whtwnd.com/${info.DID}/${info.rkey}`, 'WhiteWind'); 207 - addCreatedAt(post, record.value.createdAt); 208 - return post; 209 - } 210 - } 211 - }, 212 - { 213 - name: 'Frontpage', 214 - createQueue(user) { 215 - addQueue(user, 'fyi.unravel.frontpage.post'); 216 - }, 217 - createPost(record, info) { 218 - if (info.collection === 'fyi.unravel.frontpage.post') { 219 - const post = createCustomElement('link-post'); 220 - removeCustomElements(post, 'if-reply'); 221 - addText(post, record.value.title, 'title-content'); 222 - addText(post, record.value.url, 'link-content'); 223 - wrapLink(post, record.value.url); 224 - addRemoteLink(post, `https://frontpage.fyi/post/${info.DID}/${info.rkey}`,'Frontpage'); 225 - addCreatedAt(post, record.value.createdAt); 226 - return post; 227 - } 228 - } 229 - }, 230 - { 231 - name: 'PinkSea', 232 - createQueue(user) { 233 - let filter = function (record) { 234 - if (!options.showReplies && record.value.inResponseTo) { 235 - return false; 236 - } 237 - if (options.hideNSFW && record.value.nsfw) { 238 - return false; 239 - } 240 - return true; 241 - } 242 - addQueue(user, 'com.shinolabs.pinksea.oekaki', filter); 243 - }, 244 - createPost(record, info) { 245 - if (info.collection === 'com.shinolabs.pinksea.oekaki') { 246 - let post = createCustomElement('image-post'); 247 - 248 - // replies 249 - if (record.value.inResponseTo) { 250 - removeCustomElements(post, 'if-not-reply'); 251 - const replyInfo = parseURI(record.value.inResponseTo.uri); 252 - wrapLink(post, `https://pinksea.art/${replyInfo.DID}/oekaki/${replyInfo.rkey}`, 'reply-link-wrapper'); 253 - } else { 254 - removeCustomElements(post, 'if-reply'); 255 - } 256 - 257 - removeCustomElements(post, 'if-title'); 258 - addImage(post, record.author, record.value.image.blob, record.value.image.imageLink.alt); 259 - addTags(post, record.value.tags); 260 - addRemoteLink(post, `https://pinksea.art/${info.DID}/oekaki/${info.rkey}`, 'PinkSea'); 261 - addCreatedAt(post, record.value.createdAt); 262 - return post; 263 - } 264 - } 265 - }, 266 - { 267 - name: 'pastesphere', 268 - createQueue(user) { 269 - addQueue(user, 'link.pastesphere.snippet'); 270 - }, 271 - createPost(record, info, threshold) { 272 - if (info.collection === 'link.pastesphere.snippet') { 273 - const post = createCustomElement('text-post'); 274 - removeCustomElements(post, 'if-reply'); 275 - addText(post, record.value.title, 'title-content'); 276 - // put together description and body, wrap code types in backticks 277 - if (record.value.type === 'Plain Text') { 278 - addText(post, `${record.value.description}\n\n${record.value.body}`); 279 - } else if (record.value.type === 'Markdown') { 280 - addMarkdown(post, `${record.value.description}\n\n${record.value.body}`, threshold); 281 - } else { 282 - addMarkdown(post, `${record.value.description}\n\n\`\`\`${record.value.type}\n${record.value.body}\`\`\``, threshold); 283 - } 284 - addRemoteLink(post, `https://pastesphere.link/user/${info.DID}/snippet/${info.rkey}`, 'pastesphere'); 285 - addCreatedAt(post, record.value.createdAt); 286 - return post; 287 - } 288 - } 289 - } 290 - ] 291 - 292 - // Things that deal with at:// 293 - 294 - // breaks down URI into DID, collection, and rkey 295 - function parseURI(uri) { 296 - const components = uri.split('/'); 297 - return { 298 - DID: components[2], 299 - collection: components[3], 300 - rkey: components[4] 301 - } 302 - } 303 - 304 - // returns a cursor and list of records or undefined 305 - async function fetchRecords(DID, collection, limit=20, cursor=undefined) { 306 - let url = `https://${options.PDS}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=${collection}&limit=${limit}`; 307 - if (cursor) { 308 - url += `&cursor=${cursor}`; 309 - } 310 - const httpsResponse = await fetch(url, { method: 'GET' }); 311 - if (!httpsResponse.ok) { 312 - return undefined; // handled differently depending on caller 313 - } 314 - const converted = await httpsResponse.json(); 315 - return converted; 316 - } 317 - 318 - // returns a single record or undefined 319 - async function fetchRecordByURI(uri) { 320 - const info = parseURI(uri); 321 - const url = `https://${options.PDS}/xrpc/com.atproto.repo.getRecord?repo=${info.DID}&collection=${info.collection}&rkey=${info.rkey}`; 322 - const httpsResponse = await fetch(url, { method: 'GET' }); 323 - if (!httpsResponse.ok) { 324 - return undefined; 325 - } 326 - const converted = await httpsResponse.json(); 327 - converted.author = cache.users[info.DID]; 328 - return converted; 329 - } 330 - 331 - // Loading 332 - 333 - // adds up to a certain number of records to a queue 334 - async function queueRecords(queue, amount) { 335 - let records = []; 336 - let limit = amount; 337 - while (!records.length) { 338 - if (queue.reachedEnd) { 339 - break; 340 - } 341 - 342 - const response = await fetchRecords(queue.user.DID, queue.collection, limit, queue.cursor); 343 - queue.cursor = response.cursor; 344 - if (queue.filter) { 345 - records = response.records.filter(queue.filter); 346 - } else { 347 - records = response.records; 348 - } 349 - 350 - if (!response.cursor || response.records.length < amount) { 351 - queue.reachedEnd = true; 352 - } 353 - } 354 - queue.records = queue.records.concat(records); 355 - } 356 - 357 - // loads one page worth of records from queues into stream 358 - async function loadRecords() { 359 - let records = []; 360 - const postsPerPage = options.postsPerPage; 361 - while (records.length < postsPerPage) { 362 - // remove any empty queues 363 - stream.queues = stream.queues.filter((queue) => { 364 - return queue.records.length; 365 - }); 366 - 367 - // stop loading if there are no queues 368 - if (!stream.queues.length) { 369 - break; 370 - } 371 - 372 - // find the queue with the smallest first post date 373 - let queue; 374 - let latest = stream.queues[0]; 375 - for (let i = 1; i < stream.queues.length; i++) { 376 - queue = stream.queues[i]; 377 - if (queue.records[0].value.createdAt > latest.records[0].value.createdAt) { 378 - latest = queue; 379 - } 380 - } 381 - // unshift it into the new page of records 382 - const latestRecord = latest.records.shift(); 383 - latestRecord.author = latest.user; 384 - records.push(latestRecord); 385 - // if that queue is empty, queue up a bit more than the page size 386 - if (!latest.records.length) { 387 - await queueRecords(latest, postsPerPage + options.overshoot); 388 - } 389 - } 390 - stream.records = stream.records.concat(records); 391 - } 392 - 393 - // returns posts on a given page 394 - async function getPostsByPage(page) { 395 - const postsPerPage = options.postsPerPage; 396 - const pageStart = (page - 1) * postsPerPage; 397 - const pageEnd = pageStart + postsPerPage; 398 - 399 - // load pages until we reach this page + 1 entry 400 - while (stream.records.length <= pageEnd) { 401 - await loadRecords(); 402 - // if there is nothing more to load from, return whatever did load 403 - if (!stream.queues.length) { 404 - return stream.records.slice(pageStart, pageEnd); 405 - } 406 - } 407 - return stream.records.slice(pageStart, pageEnd); 408 - } 409 - 410 - // loads up the page limit and returns all posts with the tag 411 - async function getPostsByTag(tag) { 412 - await getPostsByPage(options.pageLimit); 413 - const filteredPosts = stream.records.filter((post) => { 414 - if (post.value.tags) { 415 - for (let postTag of post.value.tags) { 416 - if (tag === postTag.toLowerCase()) { 417 - return true; 418 - } 419 - } 420 - } 421 - return false; 422 - }); 423 - return filteredPosts; 424 - } 425 - 426 - // returns a record given its URI 427 - async function getRecord(uri) { 428 - if (uri in cache.records) { 429 - return cache.records[uri]; 430 - } 431 - // if not yet loaded, fetch it and add it 432 - const record = await fetchRecordByURI(uri); 433 - cache.records[uri] = record; 434 - return record; 435 - } 436 - 437 - // Custom HTML Elements 438 - 439 - function createCustomType(name) { 440 - customElements.define(name, class extends HTMLElement {}); 441 - } 442 - const customTypes = [ 443 - 'text-post', 444 - 'image-post', 445 - 'imageset-post', 446 - 'link-post', 447 - 'profile-username', 448 - 'profile-picture', 449 - 'profile-description', 450 - 'link-board', 451 - 'page-nav-container', 452 - 'page-nav', 453 - 'if-previous-page', 454 - 'previous-page-link', 455 - 'if-next-page', 456 - 'next-page-link', 457 - 'current-page', 458 - 'if-index-page', 459 - 'if-tag-page', 460 - 'tag-name', 461 - 'if-author', 462 - 'author-pfp', 463 - 'author-username', 464 - 'author-handle', 465 - 'if-title', 466 - 'title-content', 467 - 'text-content', 468 - 'image-content', 469 - 'link-wrapper', 470 - 'reply-link-wrapper', 471 - 'embed-container', 472 - 'embed-card', 473 - 'remote-link', 474 - 'created-at', 475 - 'tag-container', 476 - 'tag-chip', 477 - 'if-reply', 478 - 'if-not-reply' 479 - ] 480 - for (let customType of customTypes) { 481 - createCustomType(customType); 482 - } 483 - 484 - function createCustomElement(type, fallback=true) { 485 - const element = document.createElement(type); 486 - 487 - let template = document.getElementById(`template-${type}`); 488 - 489 - // for post types, fall back to generic-post 490 - if (!template && fallback) { 491 - template = document.getElementById('template-generic-post'); 492 - } 493 - 494 - // clone template or print an error and skip 495 - try { 496 - element.appendChild(template.content.cloneNode(true)); 497 - } catch { 498 - console.error(`Could not find a valid template ${type}.`) 499 - } 500 - 501 - return element; 502 - } 503 - 504 - function showCustomElements(container, type) { 505 - const elements = container.querySelectorAll(type); 506 - for (let element of elements) { 507 - element.style.display = ''; 508 - } 509 - } 510 - 511 - function hideCustomElements(container, type) { 512 - const elements = container.querySelectorAll(type); 513 - for (let element of elements) { 514 - element.style.display = 'none'; 515 - } 516 - } 517 - 518 - function removeCustomElements(container, type) { 519 - const elements = container.querySelectorAll(type); 520 - for (let element of elements) { 521 - element.remove(); 522 - } 523 - } 524 - 525 - function clearContainer(container) { 526 - container.innerHTML = ''; 527 - } 528 - 529 - // General element creation 530 - 531 - function createPost(record, showAuthor=true, threshold) { 532 - let post; // will be created depending on the type of post 533 - const info = parseURI(record.uri); 534 - for (let source of sources) { 535 - post = source.createPost(record, info, threshold); 536 - if (post) break; 537 - } 538 - 539 - // Add author information 540 - if (showAuthor) { 541 - addAuthor(post, record.author); 542 - } else { 543 - removeCustomElements(post, 'if-author'); 544 - } 545 - 546 - // Tags as Classes 547 - if (options.tagsAsClasses) { 548 - if (record.value.tags) { 549 - for (let tag of record.value.tags) { 550 - post.classList.add(tag.toLowerCase()); 551 - } 552 - } 553 - } 554 - 555 - return post; 556 - } 557 - 558 - // make an img element from blob or image link 559 - function createImage(user, blob, alt) { 560 - const imageElement = document.createElement('img'); 561 - imageElement.alt = alt; 562 - // check if it's a blob or not 563 - if (blob && blob.ref) { 564 - if (options.blobURL) { 565 - imageElement.src = `${options.blobURL}/${user.DID}/${blob.ref.$link}`; 566 - } else { 567 - imageElement.src = `https://${options.PDS}/xrpc/com.atproto.sync.getBlob?did=${user.DID}&cid=${blob.ref.$link}`; 568 - } 569 - } else { 570 - imageElement.src = blob; 571 - } 572 - return imageElement; 573 - } 574 - 575 - // container: HTML element 576 - // url: string 577 - // elementTag: string 578 - // returns the link element the content has been wrapped in 579 - function wrapLink(container, url, elementTag='link-wrapper') { 580 - const content = container.querySelector(elementTag); 581 - if (content) { 582 - const link = document.createElement('a'); 583 - link.href = url; 584 - content.parentElement.replaceChild(link, content); 585 - link.appendChild(content); 586 - return link; 587 - } 588 - } 589 - 590 - // Functions that add things to elements 591 - 592 - // container: HTML element 593 - // records: array of records 594 - function addPosts(container, records) { 595 - for (let record of records) { 596 - let element = createPost(record, true, options.readMore); 597 - container.appendChild(element); 598 - } 599 - } 600 - 601 - // container: HTML element 602 - // uri: AT URI 603 - // showAuthor: boolean 604 - async function addPostByURI(container, uri, showAuthor) { 605 - const record = await getRecord(uri); 606 - if (record) { 607 - const element = createPost(record, showAuthor); 608 - container.appendChild(element); 609 - } else { 610 - addNotice(container, `The record ${uri} could not be found on the PDS.`); 611 - } 612 - } 613 - 614 - // container: HTML element 615 - // text: string 616 - function addNotice(container, text) { 617 - const post = createCustomElement('text-post'); 618 - addText(post, text); 619 - removeCustomElements(post, 'if-title'); 620 - removeCustomElements(post, 'if-reply'); 621 - removeCustomElements(post, 'if-author'); 622 - container.appendChild(post); 623 - } 624 - 625 - // post: HTML element 626 - // elementTag: custom element tag 627 - // text: string 628 - function addText(post, text, elementTag='text-content') { 629 - const textElement = post.querySelector(elementTag); 630 - if (textElement) { 631 - textElement.innerText = text; 632 - } 633 - } 634 - 635 - // post: HTML element 636 - // markdown: string 637 - // threshold: how many elements to add Read more line after 638 - // elementTag: custom element tag 639 - function addMarkdown(post, markdown, threshold, elementTag='text-content') { 640 - const markdownElement = post.querySelector(elementTag); 641 - if (markdownElement) { 642 - markdownElement.innerHTML = md.render(markdown); 643 - if (threshold) { 644 - const children = markdownElement.children; 645 - // move all children past the readmore threshold to Details 646 - if (children.length > threshold) { 647 - const details = document.createElement('details'); 648 - const summary = document.createElement('summary'); 649 - summary.textContent = 'Read more'; 650 - details.appendChild(summary); 651 - while (children.length > threshold) { 652 - details.appendChild(children[threshold]); 653 - } 654 - markdownElement.appendChild(details); 655 - } 656 - } 657 - } 658 - } 659 - 660 - // post: HTML element 661 - // user: options.users._ 662 - // blob: blob 663 - // alt: string 664 - function addImage(post, user, blob, alt, clickToOpen=true) { 665 - const imageContent = post.querySelector('image-content'); 666 - if (imageContent) { 667 - const image = createImage(user, blob, alt); 668 - imageContent.appendChild(image); 669 - // add onclick event that opens modal with this image 670 - if (clickToOpen) { 671 - if (options.blobURL) { 672 - image.onclick = () => { 673 - openModal(`${options.blobURL}/${user.DID}/${blob.ref.$link}`, alt); 674 - }; 675 - } else { 676 - image.onclick = () => { 677 - openModal(`https://${options.PDS}/xrpc/com.atproto.sync.getBlob?did=${user.DID}&cid=${blob.ref.$link}`, alt); 678 - }; 679 - } 680 - } 681 - } 682 - } 683 - 684 - // post: HTML element 685 - // title, text, url: string 686 - // user: options.users._ 687 - // blob: blob 688 - function addEmbed(post, {title, text, url, user, blob}) { 689 - const embedContainer = post.querySelector('embed-container'); 690 - if (embedContainer) { 691 - const embedLink = document.createElement('a'); 692 - const embedCard = createCustomElement('embed-card', false); 693 - if (title) { 694 - addText(embedCard, title, 'title-content'); 695 - } else { 696 - removeCustomElements(embedCard, 'if-title'); 697 - } 698 - addText(embedCard, text, 'text-content'); 699 - if (blob) { 700 - addImage(embedCard, user, blob, title || text, false); 701 - } 702 - embedLink.href = url; 703 - embedLink.appendChild(embedCard); 704 - embedContainer.appendChild(embedLink); 705 - } 706 - } 707 - 708 - // post: HTML element 709 - // tags: array of strings 710 - function addTags(post, tags) { 711 - const tagContainer = post.querySelector('tag-container'); 712 - if (tagContainer) { 713 - for (let tag of tags) { 714 - const tagChip = createCustomElement('tag-chip', false); 715 - wrapLink(tagChip, `#tagged/${tag.toLowerCase()}`); 716 - addText(tagChip, tag, 'link-content'); 717 - tagContainer.appendChild(tagChip); 718 - } 719 - } 720 - } 721 - 722 - // post: HTML element 723 - // createdAt: string, https://en.wikipedia.org/wiki/ISO_8601 724 - function addCreatedAt(post, createdAt) { 725 - const dateElement = post.querySelector('created-at'); 726 - if (dateElement) { 727 - const datetime = Date.parse(createdAt); 728 - dateElement.textContent = options.dateFormat.format(datetime); 729 - } 730 - } 731 - 732 - // post: HTML element 733 - // user: options.users._ 734 - // adds author username, handle, and pfp, linking to handle domain if requested 735 - function addAuthor(post, user) { 736 - const usernameElement = post.querySelector('author-username'); 737 - const handleElement = post.querySelector('author-handle'); 738 - const pfpElement = post.querySelector('author-pfp'); 739 - if (usernameElement) { 740 - usernameElement.textContent = user.profile.username; 741 - } 742 - if (handleElement) { 743 - handleElement.textContent = user.handle; 744 - } 745 - if (pfpElement) { 746 - const pfpImage = createImage(user, user.profile.pfp, `${user.profile.username}'s pfp`); 747 - pfpElement.appendChild(pfpImage); 748 - } 749 - if (options.linkToUserHandles) { 750 - wrapLink(post, `https://${user.handle}`, 'author-username'); 751 - wrapLink(post, `https://${user.handle}`, 'author-handle'); 752 - wrapLink(post, `https://${user.handle}`, 'author-pfp'); 753 - } 754 - } 755 - 756 - // post: HTML element 757 - // url: string 758 - // service: string 759 - function addRemoteLink(post, url, service) { 760 - const remoteElement = post.querySelector('remote-link'); 761 - if (remoteElement) { 762 - const remoteLink = document.createElement('a'); 763 - remoteLink.href = url; 764 - remoteLink.target = '_blank'; // open in new tab 765 - remoteLink.textContent = `Open on ${service}`; 766 - remoteElement.appendChild(remoteLink); 767 - } 768 - } 769 - 770 - // Pagination 771 - 772 - function updatePagination() { 773 - if (refs.pagination) { 774 - const hasPreviousPage = cache.page !== 1; // previous page if not on page 1 775 - const hasNextPage = (cache.page * options.postsPerPage < stream.records.length) && (cache.page + 1 <= options.pageLimit); // next page if there are records after this page and next page would be within page limit 776 - 777 - // update page number and page number links 778 - if (refs.currentPageNumber) { 779 - refs.currentPageNumber.textContent = cache.page; 780 - } 781 - if (refs.previousPageLink) { 782 - if (hasPreviousPage) { 783 - refs.previousPageLink.href = `#page/${cache.page - 1}`; 784 - } else { 785 - refs.previousPageLink.removeAttribute('href'); 786 - } 787 - } 788 - if (refs.nextPageLink) { 789 - if (hasNextPage) { 790 - refs.nextPageLink.href = `#page/${cache.page + 1}`; 791 - } else { 792 - refs.nextPageLink.removeAttribute('href'); 793 - } 794 - } 795 - 796 - // only display things in <if-previous/next-page> blocks if the page exists 797 - if (refs.ifPreviousPage) { 798 - refs.ifPreviousPage.style.display = hasPreviousPage ? '' : 'none'; 799 - } 800 - if (refs.ifNextPage) { 801 - refs.ifNextPage.style.display = hasNextPage ? '' : 'none'; 802 - } 803 - refs.pagination.style.display = ''; 804 - } 805 - } 806 - 807 - function hidePagination() { 808 - if (refs.pagination) { 809 - refs.pagination.style.display = 'none'; 810 - } 811 - } 812 - 813 - // Routing 814 - 815 - // numbered page: one page of the timeline 816 - async function goToPage(page) { 817 - cache.page = page; 818 - hideCustomElements(document.body, 'if-tag-page'); 819 - showCustomElements(document.body, 'if-index-page'); 820 - clearContainer(refs.postContainer); 821 - const records = await getPostsByPage(page); 822 - addPosts(refs.postContainer, records); 823 - updatePagination(); 824 - } 825 - 826 - // tag page: all posts up to limit, filtered by tag 827 - async function goToTagPage(tag) { 828 - document.title += ` | #${tag}`; 829 - hideCustomElements(document.body, 'if-index-page'); 830 - // add tag text to all if-tag-page tag-name elements 831 - const tagPageElements = document.body.querySelectorAll('if-tag-page'); 832 - for (let element of tagPageElements) { 833 - element.style = ''; 834 - addText(element, tag, 'tag-name'); 835 - } 836 - hidePagination(); 837 - clearContainer(refs.postContainer); 838 - const records = await getPostsByTag(tag); 839 - addPosts(refs.postContainer, records); 840 - } 841 - 842 - // custom page: the specified post 843 - async function goToCustomPage(url) { 844 - hideCustomElements(document.body, 'if-tag-page'); 845 - hideCustomElements(document.body, 'if-index-page'); 846 - const page = options.pages[url]; 847 - document.title += ` | ${page.title}`; 848 - hidePagination(); 849 - 850 - // add the new page as a post 851 - clearContainer(refs.postContainer); 852 - await addPostByURI(refs.postContainer, page.post, false); 853 - } 854 - 855 - async function handleURL(url) { 856 - document.title = options.title; 857 - 858 - const parts = url.split('/'); 859 - 860 - // figure out type of page and run the function for that type 861 - if (parts.length > 1 && parts[0] === 'page') { 862 - // #page/${number} 863 - const page = parseInt(parts[1]) || 1; // if no page number go to 1 864 - if (page <= options.pageLimit) { 865 - await goToPage(page); 866 - } 867 - } else if (parts.length > 1 && parts[0] === 'tagged') { 868 - // #tagged/${tag} 869 - await goToTagPage(parts[1]); 870 - } else if (url in options.pages) { 871 - // #${name} that matches a page in options.pages 872 - await goToCustomPage(url); 873 - } else if (url) { 874 - // error: page not found 875 - clearContainer(refs.postContainer); 876 - addNotice(refs.postContainer, `The page ${url} could not be found.`); 877 - hidePagination(); 878 - } else { 879 - // default: timeline page 1 880 - await goToPage(1); 881 - } 882 - 883 - for (let scroller of refs.scrollers) { 884 - scroller.scroll(0, 0); 885 - } 886 - } 887 - 888 - window.onhashchange = () => { 889 - const url = window.location.hash.slice(1).toLowerCase(); 890 - 891 - // if we navigated to the home page, reload 892 - if (!url) { 893 - window.location.reload(); 894 - } else { 895 - handleURL(url); 896 - } 897 - } 898 - 899 - // page setup for first time load 900 - async function firstLoadSetup() { 901 - // defaults if not provided 902 - if (!options.pageLimit) options.pageLimit = 5; 903 - if (!options.postsPerPage) options.postsPerPage = 10; 904 - if (!options.overshoot) options.overshoot = options.postsPerPage; 905 - if (!options.users) options.users = []; 906 - if (!options.pages) options.pages = {}; 907 - if (!options.dateFormat) options.dateFormat = new Intl.DateTimeFormat(); 908 - 909 - for (let user of options.users) { 910 - // set up queues 911 - for (let source of sources) { 912 - if (user.sources[source.name]) { 913 - source.createQueue(user); 914 - } 915 - } 916 - if (!user.profile) { 917 - // bluesky profile default 918 - const response = await fetchRecordByURI(`at://${user.DID}/app.bsky.actor.profile/self`); 919 - if (response) { 920 - user.profile = { 921 - username: response.value.displayName, 922 - description: response.value.description, 923 - pfp: response.value.avatar 924 - }; 925 - } else { 926 - user.profile = { 927 - username: `Could not load profile for DID ${user.DID}`, 928 - description: `Could not load profile for DID ${user.DID}`, 929 - pfp: '' 930 - } 931 - } 932 - } 933 - // add user to cache 934 - cache.users[user.DID] = user; 935 - } 936 - 937 - // Populate profile elements 938 - const usernameElement = document.querySelector('profile-username'); 939 - const pfpElement = document.querySelector('profile-picture'); 940 - const descriptionElement = document.querySelector('profile-description'); 941 - const firstUser = options.users[0]; 942 - let profile; 943 - if (usernameElement || pfpElement || descriptionElement) { 944 - profile = options.profile || firstUser.profile; 945 - } 946 - if (usernameElement) { 947 - usernameElement.textContent = profile.username; 948 - } 949 - if (descriptionElement) { 950 - descriptionElement.innerText = profile.description; 951 - } 952 - if (pfpElement) { 953 - const profilePicture = createImage(firstUser, profile.pfp, 'Site profile picture'); 954 - pfpElement.appendChild(profilePicture); 955 - } 956 - 957 - // Populate links 958 - if (firstUser && firstUser.sources.Linkat) { 959 - const linkBoard = document.querySelector('link-board'); 960 - const response = await fetchRecordByURI(`at://${firstUser.DID}/blue.linkat.board/self`); 961 - if (response) { 962 - const cards = response.value.cards; 963 - for (let card of cards) { 964 - const linkCard = document.createElement('a'); 965 - linkCard.href = card.url; 966 - const linkEmoji = document.createElement('span'); 967 - linkEmoji.textContent = card.emoji; 968 - const linkText = document.createElement('span'); 969 - linkText.textContent = card.text; 970 - linkCard.appendChild(linkEmoji); 971 - linkCard.appendChild(linkText); 972 - linkBoard.appendChild(linkCard); 973 - } 974 - } else { 975 - linkBoard.textContent = 'Could not find Linkat board.'; 976 - } 977 - } 978 - 979 - // Populate user-added posts on page 980 - const userAddedPosts = document.querySelectorAll('site-post'); 981 - for (let sitePost of userAddedPosts) { 982 - const uri = sitePost.dataset.uri; 983 - if (uri) { 984 - const showAuthor = sitePost.dataset.showAuthor !== undefined; 985 - await addPostByURI(sitePost, sitePost.dataset.uri, showAuthor); 986 - } else { 987 - addNotice(sitePost, 'Please specify an AT URI.'); 988 - } 989 - } 990 - 991 - // go to page 992 - const url = window.location.hash.slice(1).toLowerCase(); 993 - if (!(url in options.pages)) { 994 - // initial queue population for tl pages 995 - for (let queue of stream.queues) { 996 - await queueRecords(queue, options.postsPerPage + options.overshoot); 997 - } 998 - } 999 - await handleURL(url); 1000 - } 1001 - 1002 - await firstLoadSetup(); 1003 - 1004 - }
-19
assets/scripts/copyright.js
··· 1 - document.addEventListener("DOMContentLoaded", function () { 2 - console.debug("Initialising copyright year update..."); 3 - 4 - function updateCopyrightYear() { 5 - const currentYear = new Date().getFullYear(); 6 - const displayYear = currentYear < 2023 ? 2023 : currentYear; 7 - const copyrightElement = document.getElementById("copyright-year"); 8 - 9 - if (copyrightElement) { 10 - copyrightElement.textContent = currentYear; 11 - console.debug(`Copyright year updated to ${currentYear}`); 12 - } else { 13 - console.warn("Copyright year element not found."); 14 - } 15 - } 16 - 17 - // Update the copyright year on page load 18 - updateCopyrightYear(); 19 - });
-67
assets/scripts/post-transitions.js
··· 1 - document.addEventListener("DOMContentLoaded", function() { 2 - // Set up an observer to watch for new posts being added to the DOM 3 - const postContainer = document.querySelector('post-container'); 4 - 5 - if (!postContainer) { 6 - console.warn("Post container not found"); 7 - return; 8 - } 9 - 10 - // Function to add transition classes to posts 11 - function setupPostTransitions() { 12 - // Get all posts that don't have the transition class yet 13 - const posts = document.querySelectorAll('.post:not(.has-transition)'); 14 - 15 - posts.forEach((post, index) => { 16 - // Mark this post as having transitions 17 - post.classList.add('has-transition', 'post-transition'); 18 - 19 - // Set initial state (invisible) 20 - post.style.opacity = '0'; 21 - post.style.transform = 'translateY(20px)'; 22 - 23 - // Stagger the appearance of posts 24 - setTimeout(() => { 25 - post.style.opacity = '1'; 26 - post.style.transform = 'translateY(0)'; 27 - }, 100 * index); // Stagger each post by 100ms 28 - }); 29 - } 30 - 31 - // Initial setup for any posts that are already in the DOM 32 - setupPostTransitions(); 33 - 34 - // Watch for changes in the post container (new posts being added) 35 - const observer = new MutationObserver((mutations) => { 36 - mutations.forEach((mutation) => { 37 - if (mutation.addedNodes.length > 0) { 38 - setupPostTransitions(); 39 - } 40 - }); 41 - }); 42 - 43 - // Start observing the post container for added posts 44 - observer.observe(postContainer, { childList: true, subtree: true }); 45 - 46 - // Handle page navigation (when the user navigates between pages) 47 - window.addEventListener('hashchange', function() { 48 - // Fade out all existing posts 49 - const posts = document.querySelectorAll('.post'); 50 - posts.forEach((post, index) => { 51 - post.style.opacity = '0'; 52 - post.style.transform = 'translateY(20px)'; 53 - }); 54 - 55 - // After posts fade out, new ones will be loaded and fade in due to the observer 56 - setTimeout(setupPostTransitions, 400); // Wait for fade out to complete 57 - }); 58 - 59 - // Handle theme changes to reapply transitions 60 - const themeToggle = document.getElementById('theme-toggle'); 61 - if (themeToggle) { 62 - themeToggle.addEventListener('click', function() { 63 - // Brief delay to allow theme change to process 64 - setTimeout(setupPostTransitions, 100); 65 - }); 66 - } 67 - });
-38
assets/scripts/settings.js
··· 1 - // docs: https://whtwnd.com/did:plc:xz3euvkhf44iadavovbsmqoo/3laxrz4dl4s2f 2 - atprotoSite({ 3 - PDS: 'pds.ewancroft.uk', 4 - title: "Ewan's Web Corner", 5 - postsPerPage: 10, 6 - pageLimit: 5, 7 - linkToUserHandles: false, 8 - showDrafts: false, 9 - showReplies: true, 10 - readMore: 5, 11 - tagsAsClasses: true, 12 - blobURL: undefined, 13 - dateFormat: new Intl.DateTimeFormat(undefined, { dateStyle: 'short', timeStyle: 'short' }), 14 - pages: { 15 - 'about': { 16 - title: 'About Me', 17 - post: 'at://did:plc:ofrbh253gwicbkc5nktqepol/com.whtwnd.blog.entry/3lgvyq43doi2e' 18 - }, 19 - 'verification': { 20 - title: 'Verification', 21 - post: 'at://did:plc:ofrbh253gwicbkc5nktqepol/com.whtwnd.blog.entry/3lhcavd3wyc2g' 22 - } 23 - }, 24 - users: [ 25 - { 26 - DID: 'did:plc:ofrbh253gwicbkc5nktqepol', 27 - handle: 'ewancroft.uk', 28 - sources: { 29 - Bluesky: true, 30 - WhiteWind: true, 31 - Frontpage: true, 32 - PinkSea: false, 33 - pastesphere: false, 34 - Linkat: false 35 - }, 36 - } 37 - ], 38 - });
-24
assets/scripts/theme.js
··· 1 - document.addEventListener("DOMContentLoaded", function () { 2 - const themeToggleButton = document.getElementById("theme-toggle"); 3 - // Reordered themes list by colour spectrum – "default" is green. 4 - const themes = ["red", "orange", "yellow", "default", "blue", "indigo", "violet", "monochrome"]; 5 - let currentTheme = localStorage.getItem("theme") || "default"; 6 - 7 - // Apply saved theme and update button text 8 - document.documentElement.className = currentTheme; 9 - themeToggleButton.textContent = `Theme: ${currentTheme}`; 10 - themeToggleButton.setAttribute("aria-label", `Switch theme (Current: ${currentTheme})`); 11 - 12 - themeToggleButton.addEventListener("click", function () { 13 - const nextTheme = themes[(themes.indexOf(currentTheme) + 1) % themes.length]; 14 - 15 - // Apply the new theme 16 - document.documentElement.className = nextTheme; 17 - localStorage.setItem("theme", nextTheme); 18 - currentTheme = nextTheme; 19 - 20 - // Update button text and accessibility label 21 - themeToggleButton.textContent = `Theme: ${nextTheme}`; 22 - themeToggleButton.setAttribute("aria-label", `Switch theme (Current: ${nextTheme})`); 23 - }); 24 - });
-213
index.html
··· 1 - <!DOCTYPE html> 2 - <html lang="en"> 3 - 4 - <head> 5 - <meta charset="utf-8"> 6 - <meta name="viewport" content="width=device-width, initial-scale=1"> 7 - 8 - <!-- Meta Tags for SEO and Personal Branding --> 9 - <meta name="description" 10 - content="Welcome to Ewan's Web Corner - A personal blog where I share my thoughts on coding, technology, and life."> 11 - <meta name="keywords" content="Ewan, personal blog, coding, technology, programming, tech blog, Ewan's Web Corner"> 12 - <meta name="author" content="Ewan Croft"> 13 - <meta name="robots" content="index, follow"> 14 - 15 - <!-- Open Graph Meta Tags for Social Media --> 16 - <meta property="og:title" content="Ewan's Web Corner"> 17 - <meta property="og:description" content="Explore my personal website where I share my ramblings."> 18 - <meta property="og:image" content="/assets/images/embed-preview.png"> 19 - <meta property="og:image:width" content="1200"> 20 - <meta property="og:image:height" content="630"> 21 - <meta property="og:url" content="https://ewancroft.uk"> 22 - <meta property="og:type" content="website"> 23 - <meta property="og:site_name" content="Ewan's Web Corner"> 24 - 25 - <!-- Styles --> 26 - <link rel="stylesheet" href="/assets/css/fonts.css"> 27 - <link rel="stylesheet" href="/assets/css/variables.css"> 28 - <link rel="stylesheet" href="/assets/css/base.css"> 29 - <link rel="stylesheet" href="/assets/css/layout.css"> 30 - <link rel="stylesheet" href="/assets/css/components.css"> 31 - <link rel="stylesheet" href="/assets/css/media-queries.css"> 32 - <link rel="stylesheet" href="/assets/css/post-transitions.css"> 33 - 34 - <!-- Favicon and Icons (Static Fallbacks) --> 35 - <link id="icon-32" rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon/favicon-32x32.png"> 36 - <link id="icon-16" rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon/favicon-16x16.png"> 37 - <link id="apple-touch-icon" rel="apple-touch-icon" sizes="180x180" href="/assets/images/favicon/apple-touch-icon.png"> 38 - <link id="android-chrome-192x192" rel="icon" type="image/png" sizes="192x192" href="/assets/images/favicon/android-chrome-192x192.png"> 39 - <link id="android-chrome-512x512" rel="icon" type="image/png" sizes="512x512" href="/assets/images/favicon/android-chrome-512x512.png"> 40 - <link rel="manifest" href="/assets/images/favicon/site.webmanifest"> 41 - 42 - <!-- Mobile Optimisation --> 43 - <meta name="mobile-web-app-capable" content="yes"> 44 - <meta name="apple-mobile-web-app-capable" content="yes"> 45 - 46 - <!-- Title --> 47 - <title>Ewan's Web Corner</title> 48 - 49 - <!-- Other Meta Tags for Compatibility --> 50 - <meta http-equiv="X-UA-Compatible" content="IE=edge"> 51 - <meta name="format-detection" content="telephone=no"> 52 - <meta name="msapplication-TileColor" content="#0a1607"> 53 - <meta name="msapplication-TileImage" content="/assets/images/favicon/ms-icon-144x144.png"> 54 - 55 - <title>Loading...</title> 56 - </head> 57 - 58 - <body class="atproto-site-scroll"> 59 - 60 - <div id="page"> 61 - <div id="column-left"> 62 - <div id="sidebar"> 63 - <div id="profile-area"> 64 - <!-- Profile Information --> 65 - <profile-picture></profile-picture> 66 - <profile-username></profile-username> 67 - <profile-description></profile-description> 68 - 69 - <!-- Navigation Links --> 70 - <nav aria-label="Main Navigation"> 71 - <div class="links"> 72 - <a href="/">Home</a> 73 - <a href="/#about">About</a> 74 - <a href="/#verification">Verification</a> 75 - <a href="https://whtwnd.com/did:plc:ofrbh253gwicbkc5nktqepol">My Blog</a> 76 - <a href="https://lastfmstats.com/user/greenwolf745/charts">Music Habits</a> 77 - </div> 78 - 79 - <!-- Pagination --> 80 - <if-pagination role="navigation" aria-label="Pagination Navigation"> 81 - <if-previous-page style="display: none;"> 82 - <a aria-label="Previous Page"><previous-page-link>&lt;</previous-page-link></a> 83 - </if-previous-page> 84 - <current-page-number>1</current-page-number> 85 - <if-next-page> 86 - <a href="#page/2" aria-label="Next Page"><next-page-link>&gt;</next-page-link></a> 87 - </if-next-page> 88 - </if-pagination> 89 - </nav> 90 - </div> 91 - 92 - <p class="credit"> 93 - powered by <a href="https://atproto.com">atproto</a> 94 - <br /> 95 - &copy; 2023-<span id="copyright-year"></span> ewan croft 96 - <br /> 97 - <a href="https://opensource.org/licenses/MIT">code licensed under the mit licence</a> 98 - <br /> 99 - <a href="https://creativecommons.org/licenses/by/4.0/">text and imagery licenced under cc by 4.0</a> 100 - <br /> 101 - this website is based on <a href="https://codeberg.org/fei-chicory-blue/atproto-site">this template</a> 102 - 103 - <script src="https://recentfm.rknight.me/now.js?u=greenwolf745"></script> 104 - </p> 105 - 106 - <button id="theme-toggle" aria-label="Toggle Theme">Toggle Theme</button> 107 - </div> 108 - 109 - </div> 110 - <div id="column-right"> 111 - <noscript> 112 - <p>It seems you have JavaScript disabled. Please enable it to view this site properly.</p> 113 - </noscript> 114 - <if-tag-page style="display: none;"> 115 - <div class="post"> 116 - Posts tagged #<tag-name></tag-name> 117 - </div> 118 - </if-tag-page> 119 - <main class="atproto-site-scroll"> 120 - <!--you can add a "pinned" post here:--> 121 - <!--<site-post data-uri="at:..." data-show-author></site-post>--> 122 - <post-container></post-container> 123 - </main> 124 - </div> 125 - </div> 126 - 127 - <!--generic/fallback post template--> 128 - <template id="template-generic-post"> 129 - <article class="post" role="article"> 130 - <div class="author"> 131 - <author-pfp></author-pfp> 132 - <div> 133 - <author-username></author-username> 134 - <author-handle></author-handle> 135 - </div> 136 - </div> 137 - <if-reply> 138 - <div class="reply-indicator" aria-label="Reply Indicator">&#8617; Reply 139 - <reply-link-wrapper>(see context)</reply-link-wrapper> 140 - </div> 141 - </if-reply> 142 - <image-content></image-content> 143 - <if-title> 144 - <h2><title-content></title-content></h2> 145 - </if-title> 146 - <text-content></text-content> 147 - <embed-container></embed-container> 148 - <tag-container></tag-container> 149 - <div class="footer"> 150 - <created-at></created-at> 151 - <remote-link></remote-link> 152 - </div> 153 - </article> 154 - </template> 155 - 156 - <template id="template-link-post"> 157 - <article class="post" role="article"> 158 - <div class="author"> 159 - <author-pfp></author-pfp> 160 - <div> 161 - <author-username></author-username> 162 - <author-handle></author-handle> 163 - </div> 164 - </div> 165 - <if-reply> 166 - <div class="reply-indicator" aria-label="Reply Indicator">&#8617; Reply 167 - <reply-link-wrapper>(see context)</reply-link-wrapper> 168 - </div> 169 - </if-reply> 170 - <link-wrapper> 171 - <link-content></link-content> 172 - </link-wrapper> 173 - <if-title> 174 - <h3><title-content></title-content></h3> 175 - </if-title> 176 - <embed-container></embed-container> 177 - <tag-container></tag-container> 178 - <div class="footer"> 179 - <created-at></created-at> 180 - <remote-link></remote-link> 181 - </div> 182 - </article> 183 - </template> 184 - 185 - <template id="template-embed-card"> 186 - <div class="embed-card"> 187 - <image-content></image-content> 188 - <div class="embed-content"> 189 - <if-title> 190 - <div> 191 - <title-content></title-content> 192 - </div> 193 - </if-title> 194 - <text-content></text-content> 195 - </div> 196 - </div> 197 - </template> 198 - 199 - <template id="template-tag-chip"> 200 - <link-wrapper > 201 - #<link-content></link-content> 202 - </link-wrapper> 203 - </template> 204 - 205 - <script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script> 206 - <script src="/assets/scripts/atproto.js"></script> 207 - <script src="/assets/scripts/settings.js"></script> 208 - <script src="/assets/scripts/copyright.js"></script> 209 - <script src="/assets/scripts/theme.js"></script> 210 - <script src="/assets/scripts/post-transitions.js"></script> 211 - </body> 212 - 213 - </html>
+2132
package-lock.json
··· 1 + { 2 + "name": "website", 3 + "version": "0.0.1", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "website", 9 + "version": "0.0.1", 10 + "devDependencies": { 11 + "@sveltejs/adapter-auto": "^4.0.0", 12 + "@sveltejs/kit": "^2.16.0", 13 + "@sveltejs/vite-plugin-svelte": "^5.0.0", 14 + "@tailwindcss/vite": "^4.0.0", 15 + "prettier": "^3.4.2", 16 + "prettier-plugin-svelte": "^3.3.3", 17 + "prettier-plugin-tailwindcss": "^0.6.11", 18 + "svelte": "^5.0.0", 19 + "svelte-check": "^4.0.0", 20 + "tailwindcss": "^4.0.0", 21 + "typescript": "^5.0.0", 22 + "vite": "^6.0.0" 23 + } 24 + }, 25 + "node_modules/@ampproject/remapping": { 26 + "version": "2.3.0", 27 + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 28 + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 29 + "dev": true, 30 + "license": "Apache-2.0", 31 + "dependencies": { 32 + "@jridgewell/gen-mapping": "^0.3.5", 33 + "@jridgewell/trace-mapping": "^0.3.24" 34 + }, 35 + "engines": { 36 + "node": ">=6.0.0" 37 + } 38 + }, 39 + "node_modules/@esbuild/aix-ppc64": { 40 + "version": "0.25.1", 41 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", 42 + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", 43 + "cpu": [ 44 + "ppc64" 45 + ], 46 + "dev": true, 47 + "license": "MIT", 48 + "optional": true, 49 + "os": [ 50 + "aix" 51 + ], 52 + "engines": { 53 + "node": ">=18" 54 + } 55 + }, 56 + "node_modules/@esbuild/android-arm": { 57 + "version": "0.25.1", 58 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", 59 + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", 60 + "cpu": [ 61 + "arm" 62 + ], 63 + "dev": true, 64 + "license": "MIT", 65 + "optional": true, 66 + "os": [ 67 + "android" 68 + ], 69 + "engines": { 70 + "node": ">=18" 71 + } 72 + }, 73 + "node_modules/@esbuild/android-arm64": { 74 + "version": "0.25.1", 75 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", 76 + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", 77 + "cpu": [ 78 + "arm64" 79 + ], 80 + "dev": true, 81 + "license": "MIT", 82 + "optional": true, 83 + "os": [ 84 + "android" 85 + ], 86 + "engines": { 87 + "node": ">=18" 88 + } 89 + }, 90 + "node_modules/@esbuild/android-x64": { 91 + "version": "0.25.1", 92 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", 93 + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", 94 + "cpu": [ 95 + "x64" 96 + ], 97 + "dev": true, 98 + "license": "MIT", 99 + "optional": true, 100 + "os": [ 101 + "android" 102 + ], 103 + "engines": { 104 + "node": ">=18" 105 + } 106 + }, 107 + "node_modules/@esbuild/darwin-arm64": { 108 + "version": "0.25.1", 109 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", 110 + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", 111 + "cpu": [ 112 + "arm64" 113 + ], 114 + "dev": true, 115 + "license": "MIT", 116 + "optional": true, 117 + "os": [ 118 + "darwin" 119 + ], 120 + "engines": { 121 + "node": ">=18" 122 + } 123 + }, 124 + "node_modules/@esbuild/darwin-x64": { 125 + "version": "0.25.1", 126 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", 127 + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", 128 + "cpu": [ 129 + "x64" 130 + ], 131 + "dev": true, 132 + "license": "MIT", 133 + "optional": true, 134 + "os": [ 135 + "darwin" 136 + ], 137 + "engines": { 138 + "node": ">=18" 139 + } 140 + }, 141 + "node_modules/@esbuild/freebsd-arm64": { 142 + "version": "0.25.1", 143 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", 144 + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", 145 + "cpu": [ 146 + "arm64" 147 + ], 148 + "dev": true, 149 + "license": "MIT", 150 + "optional": true, 151 + "os": [ 152 + "freebsd" 153 + ], 154 + "engines": { 155 + "node": ">=18" 156 + } 157 + }, 158 + "node_modules/@esbuild/freebsd-x64": { 159 + "version": "0.25.1", 160 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", 161 + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", 162 + "cpu": [ 163 + "x64" 164 + ], 165 + "dev": true, 166 + "license": "MIT", 167 + "optional": true, 168 + "os": [ 169 + "freebsd" 170 + ], 171 + "engines": { 172 + "node": ">=18" 173 + } 174 + }, 175 + "node_modules/@esbuild/linux-arm": { 176 + "version": "0.25.1", 177 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", 178 + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", 179 + "cpu": [ 180 + "arm" 181 + ], 182 + "dev": true, 183 + "license": "MIT", 184 + "optional": true, 185 + "os": [ 186 + "linux" 187 + ], 188 + "engines": { 189 + "node": ">=18" 190 + } 191 + }, 192 + "node_modules/@esbuild/linux-arm64": { 193 + "version": "0.25.1", 194 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", 195 + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", 196 + "cpu": [ 197 + "arm64" 198 + ], 199 + "dev": true, 200 + "license": "MIT", 201 + "optional": true, 202 + "os": [ 203 + "linux" 204 + ], 205 + "engines": { 206 + "node": ">=18" 207 + } 208 + }, 209 + "node_modules/@esbuild/linux-ia32": { 210 + "version": "0.25.1", 211 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", 212 + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", 213 + "cpu": [ 214 + "ia32" 215 + ], 216 + "dev": true, 217 + "license": "MIT", 218 + "optional": true, 219 + "os": [ 220 + "linux" 221 + ], 222 + "engines": { 223 + "node": ">=18" 224 + } 225 + }, 226 + "node_modules/@esbuild/linux-loong64": { 227 + "version": "0.25.1", 228 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", 229 + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", 230 + "cpu": [ 231 + "loong64" 232 + ], 233 + "dev": true, 234 + "license": "MIT", 235 + "optional": true, 236 + "os": [ 237 + "linux" 238 + ], 239 + "engines": { 240 + "node": ">=18" 241 + } 242 + }, 243 + "node_modules/@esbuild/linux-mips64el": { 244 + "version": "0.25.1", 245 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", 246 + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", 247 + "cpu": [ 248 + "mips64el" 249 + ], 250 + "dev": true, 251 + "license": "MIT", 252 + "optional": true, 253 + "os": [ 254 + "linux" 255 + ], 256 + "engines": { 257 + "node": ">=18" 258 + } 259 + }, 260 + "node_modules/@esbuild/linux-ppc64": { 261 + "version": "0.25.1", 262 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", 263 + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", 264 + "cpu": [ 265 + "ppc64" 266 + ], 267 + "dev": true, 268 + "license": "MIT", 269 + "optional": true, 270 + "os": [ 271 + "linux" 272 + ], 273 + "engines": { 274 + "node": ">=18" 275 + } 276 + }, 277 + "node_modules/@esbuild/linux-riscv64": { 278 + "version": "0.25.1", 279 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", 280 + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", 281 + "cpu": [ 282 + "riscv64" 283 + ], 284 + "dev": true, 285 + "license": "MIT", 286 + "optional": true, 287 + "os": [ 288 + "linux" 289 + ], 290 + "engines": { 291 + "node": ">=18" 292 + } 293 + }, 294 + "node_modules/@esbuild/linux-s390x": { 295 + "version": "0.25.1", 296 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", 297 + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", 298 + "cpu": [ 299 + "s390x" 300 + ], 301 + "dev": true, 302 + "license": "MIT", 303 + "optional": true, 304 + "os": [ 305 + "linux" 306 + ], 307 + "engines": { 308 + "node": ">=18" 309 + } 310 + }, 311 + "node_modules/@esbuild/linux-x64": { 312 + "version": "0.25.1", 313 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", 314 + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", 315 + "cpu": [ 316 + "x64" 317 + ], 318 + "dev": true, 319 + "license": "MIT", 320 + "optional": true, 321 + "os": [ 322 + "linux" 323 + ], 324 + "engines": { 325 + "node": ">=18" 326 + } 327 + }, 328 + "node_modules/@esbuild/netbsd-arm64": { 329 + "version": "0.25.1", 330 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", 331 + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", 332 + "cpu": [ 333 + "arm64" 334 + ], 335 + "dev": true, 336 + "license": "MIT", 337 + "optional": true, 338 + "os": [ 339 + "netbsd" 340 + ], 341 + "engines": { 342 + "node": ">=18" 343 + } 344 + }, 345 + "node_modules/@esbuild/netbsd-x64": { 346 + "version": "0.25.1", 347 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", 348 + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", 349 + "cpu": [ 350 + "x64" 351 + ], 352 + "dev": true, 353 + "license": "MIT", 354 + "optional": true, 355 + "os": [ 356 + "netbsd" 357 + ], 358 + "engines": { 359 + "node": ">=18" 360 + } 361 + }, 362 + "node_modules/@esbuild/openbsd-arm64": { 363 + "version": "0.25.1", 364 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", 365 + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", 366 + "cpu": [ 367 + "arm64" 368 + ], 369 + "dev": true, 370 + "license": "MIT", 371 + "optional": true, 372 + "os": [ 373 + "openbsd" 374 + ], 375 + "engines": { 376 + "node": ">=18" 377 + } 378 + }, 379 + "node_modules/@esbuild/openbsd-x64": { 380 + "version": "0.25.1", 381 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", 382 + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", 383 + "cpu": [ 384 + "x64" 385 + ], 386 + "dev": true, 387 + "license": "MIT", 388 + "optional": true, 389 + "os": [ 390 + "openbsd" 391 + ], 392 + "engines": { 393 + "node": ">=18" 394 + } 395 + }, 396 + "node_modules/@esbuild/sunos-x64": { 397 + "version": "0.25.1", 398 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", 399 + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", 400 + "cpu": [ 401 + "x64" 402 + ], 403 + "dev": true, 404 + "license": "MIT", 405 + "optional": true, 406 + "os": [ 407 + "sunos" 408 + ], 409 + "engines": { 410 + "node": ">=18" 411 + } 412 + }, 413 + "node_modules/@esbuild/win32-arm64": { 414 + "version": "0.25.1", 415 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", 416 + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", 417 + "cpu": [ 418 + "arm64" 419 + ], 420 + "dev": true, 421 + "license": "MIT", 422 + "optional": true, 423 + "os": [ 424 + "win32" 425 + ], 426 + "engines": { 427 + "node": ">=18" 428 + } 429 + }, 430 + "node_modules/@esbuild/win32-ia32": { 431 + "version": "0.25.1", 432 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", 433 + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", 434 + "cpu": [ 435 + "ia32" 436 + ], 437 + "dev": true, 438 + "license": "MIT", 439 + "optional": true, 440 + "os": [ 441 + "win32" 442 + ], 443 + "engines": { 444 + "node": ">=18" 445 + } 446 + }, 447 + "node_modules/@esbuild/win32-x64": { 448 + "version": "0.25.1", 449 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", 450 + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", 451 + "cpu": [ 452 + "x64" 453 + ], 454 + "dev": true, 455 + "license": "MIT", 456 + "optional": true, 457 + "os": [ 458 + "win32" 459 + ], 460 + "engines": { 461 + "node": ">=18" 462 + } 463 + }, 464 + "node_modules/@jridgewell/gen-mapping": { 465 + "version": "0.3.8", 466 + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", 467 + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", 468 + "dev": true, 469 + "license": "MIT", 470 + "dependencies": { 471 + "@jridgewell/set-array": "^1.2.1", 472 + "@jridgewell/sourcemap-codec": "^1.4.10", 473 + "@jridgewell/trace-mapping": "^0.3.24" 474 + }, 475 + "engines": { 476 + "node": ">=6.0.0" 477 + } 478 + }, 479 + "node_modules/@jridgewell/resolve-uri": { 480 + "version": "3.1.2", 481 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 482 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 483 + "dev": true, 484 + "license": "MIT", 485 + "engines": { 486 + "node": ">=6.0.0" 487 + } 488 + }, 489 + "node_modules/@jridgewell/set-array": { 490 + "version": "1.2.1", 491 + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 492 + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 493 + "dev": true, 494 + "license": "MIT", 495 + "engines": { 496 + "node": ">=6.0.0" 497 + } 498 + }, 499 + "node_modules/@jridgewell/sourcemap-codec": { 500 + "version": "1.5.0", 501 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 502 + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 503 + "dev": true, 504 + "license": "MIT" 505 + }, 506 + "node_modules/@jridgewell/trace-mapping": { 507 + "version": "0.3.25", 508 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 509 + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 510 + "dev": true, 511 + "license": "MIT", 512 + "dependencies": { 513 + "@jridgewell/resolve-uri": "^3.1.0", 514 + "@jridgewell/sourcemap-codec": "^1.4.14" 515 + } 516 + }, 517 + "node_modules/@polka/url": { 518 + "version": "1.0.0-next.28", 519 + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", 520 + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", 521 + "dev": true, 522 + "license": "MIT" 523 + }, 524 + "node_modules/@rollup/rollup-android-arm-eabi": { 525 + "version": "4.36.0", 526 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.36.0.tgz", 527 + "integrity": "sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==", 528 + "cpu": [ 529 + "arm" 530 + ], 531 + "dev": true, 532 + "license": "MIT", 533 + "optional": true, 534 + "os": [ 535 + "android" 536 + ] 537 + }, 538 + "node_modules/@rollup/rollup-android-arm64": { 539 + "version": "4.36.0", 540 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.36.0.tgz", 541 + "integrity": "sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==", 542 + "cpu": [ 543 + "arm64" 544 + ], 545 + "dev": true, 546 + "license": "MIT", 547 + "optional": true, 548 + "os": [ 549 + "android" 550 + ] 551 + }, 552 + "node_modules/@rollup/rollup-darwin-arm64": { 553 + "version": "4.36.0", 554 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.36.0.tgz", 555 + "integrity": "sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==", 556 + "cpu": [ 557 + "arm64" 558 + ], 559 + "dev": true, 560 + "license": "MIT", 561 + "optional": true, 562 + "os": [ 563 + "darwin" 564 + ] 565 + }, 566 + "node_modules/@rollup/rollup-darwin-x64": { 567 + "version": "4.36.0", 568 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.36.0.tgz", 569 + "integrity": "sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==", 570 + "cpu": [ 571 + "x64" 572 + ], 573 + "dev": true, 574 + "license": "MIT", 575 + "optional": true, 576 + "os": [ 577 + "darwin" 578 + ] 579 + }, 580 + "node_modules/@rollup/rollup-freebsd-arm64": { 581 + "version": "4.36.0", 582 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.36.0.tgz", 583 + "integrity": "sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==", 584 + "cpu": [ 585 + "arm64" 586 + ], 587 + "dev": true, 588 + "license": "MIT", 589 + "optional": true, 590 + "os": [ 591 + "freebsd" 592 + ] 593 + }, 594 + "node_modules/@rollup/rollup-freebsd-x64": { 595 + "version": "4.36.0", 596 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.36.0.tgz", 597 + "integrity": "sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==", 598 + "cpu": [ 599 + "x64" 600 + ], 601 + "dev": true, 602 + "license": "MIT", 603 + "optional": true, 604 + "os": [ 605 + "freebsd" 606 + ] 607 + }, 608 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 609 + "version": "4.36.0", 610 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.36.0.tgz", 611 + "integrity": "sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==", 612 + "cpu": [ 613 + "arm" 614 + ], 615 + "dev": true, 616 + "license": "MIT", 617 + "optional": true, 618 + "os": [ 619 + "linux" 620 + ] 621 + }, 622 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 623 + "version": "4.36.0", 624 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.36.0.tgz", 625 + "integrity": "sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==", 626 + "cpu": [ 627 + "arm" 628 + ], 629 + "dev": true, 630 + "license": "MIT", 631 + "optional": true, 632 + "os": [ 633 + "linux" 634 + ] 635 + }, 636 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 637 + "version": "4.36.0", 638 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.36.0.tgz", 639 + "integrity": "sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==", 640 + "cpu": [ 641 + "arm64" 642 + ], 643 + "dev": true, 644 + "license": "MIT", 645 + "optional": true, 646 + "os": [ 647 + "linux" 648 + ] 649 + }, 650 + "node_modules/@rollup/rollup-linux-arm64-musl": { 651 + "version": "4.36.0", 652 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.36.0.tgz", 653 + "integrity": "sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==", 654 + "cpu": [ 655 + "arm64" 656 + ], 657 + "dev": true, 658 + "license": "MIT", 659 + "optional": true, 660 + "os": [ 661 + "linux" 662 + ] 663 + }, 664 + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 665 + "version": "4.36.0", 666 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.36.0.tgz", 667 + "integrity": "sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==", 668 + "cpu": [ 669 + "loong64" 670 + ], 671 + "dev": true, 672 + "license": "MIT", 673 + "optional": true, 674 + "os": [ 675 + "linux" 676 + ] 677 + }, 678 + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 679 + "version": "4.36.0", 680 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.36.0.tgz", 681 + "integrity": "sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==", 682 + "cpu": [ 683 + "ppc64" 684 + ], 685 + "dev": true, 686 + "license": "MIT", 687 + "optional": true, 688 + "os": [ 689 + "linux" 690 + ] 691 + }, 692 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 693 + "version": "4.36.0", 694 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.36.0.tgz", 695 + "integrity": "sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==", 696 + "cpu": [ 697 + "riscv64" 698 + ], 699 + "dev": true, 700 + "license": "MIT", 701 + "optional": true, 702 + "os": [ 703 + "linux" 704 + ] 705 + }, 706 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 707 + "version": "4.36.0", 708 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.36.0.tgz", 709 + "integrity": "sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==", 710 + "cpu": [ 711 + "s390x" 712 + ], 713 + "dev": true, 714 + "license": "MIT", 715 + "optional": true, 716 + "os": [ 717 + "linux" 718 + ] 719 + }, 720 + "node_modules/@rollup/rollup-linux-x64-gnu": { 721 + "version": "4.36.0", 722 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.36.0.tgz", 723 + "integrity": "sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==", 724 + "cpu": [ 725 + "x64" 726 + ], 727 + "dev": true, 728 + "license": "MIT", 729 + "optional": true, 730 + "os": [ 731 + "linux" 732 + ] 733 + }, 734 + "node_modules/@rollup/rollup-linux-x64-musl": { 735 + "version": "4.36.0", 736 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.36.0.tgz", 737 + "integrity": "sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==", 738 + "cpu": [ 739 + "x64" 740 + ], 741 + "dev": true, 742 + "license": "MIT", 743 + "optional": true, 744 + "os": [ 745 + "linux" 746 + ] 747 + }, 748 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 749 + "version": "4.36.0", 750 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.36.0.tgz", 751 + "integrity": "sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==", 752 + "cpu": [ 753 + "arm64" 754 + ], 755 + "dev": true, 756 + "license": "MIT", 757 + "optional": true, 758 + "os": [ 759 + "win32" 760 + ] 761 + }, 762 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 763 + "version": "4.36.0", 764 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.36.0.tgz", 765 + "integrity": "sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==", 766 + "cpu": [ 767 + "ia32" 768 + ], 769 + "dev": true, 770 + "license": "MIT", 771 + "optional": true, 772 + "os": [ 773 + "win32" 774 + ] 775 + }, 776 + "node_modules/@rollup/rollup-win32-x64-msvc": { 777 + "version": "4.36.0", 778 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.36.0.tgz", 779 + "integrity": "sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==", 780 + "cpu": [ 781 + "x64" 782 + ], 783 + "dev": true, 784 + "license": "MIT", 785 + "optional": true, 786 + "os": [ 787 + "win32" 788 + ] 789 + }, 790 + "node_modules/@sveltejs/acorn-typescript": { 791 + "version": "1.0.5", 792 + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", 793 + "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", 794 + "dev": true, 795 + "license": "MIT", 796 + "peerDependencies": { 797 + "acorn": "^8.9.0" 798 + } 799 + }, 800 + "node_modules/@sveltejs/adapter-auto": { 801 + "version": "4.0.0", 802 + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-4.0.0.tgz", 803 + "integrity": "sha512-kmuYSQdD2AwThymQF0haQhM8rE5rhutQXG4LNbnbShwhMO4qQGnKaaTy+88DuNSuoQDi58+thpq8XpHc1+oEKQ==", 804 + "dev": true, 805 + "license": "MIT", 806 + "dependencies": { 807 + "import-meta-resolve": "^4.1.0" 808 + }, 809 + "peerDependencies": { 810 + "@sveltejs/kit": "^2.0.0" 811 + } 812 + }, 813 + "node_modules/@sveltejs/kit": { 814 + "version": "2.20.0", 815 + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.0.tgz", 816 + "integrity": "sha512-xCUGevE2GFhpDAxZiVOsk6HKaBicwU7uWYcMOcpHCDcjoN6mKBIeMEzuddRMqSA4zjbeA+RcillCv1ppkWRwSQ==", 817 + "dev": true, 818 + "license": "MIT", 819 + "dependencies": { 820 + "@types/cookie": "^0.6.0", 821 + "cookie": "^0.6.0", 822 + "devalue": "^5.1.0", 823 + "esm-env": "^1.2.2", 824 + "import-meta-resolve": "^4.1.0", 825 + "kleur": "^4.1.5", 826 + "magic-string": "^0.30.5", 827 + "mrmime": "^2.0.0", 828 + "sade": "^1.8.1", 829 + "set-cookie-parser": "^2.6.0", 830 + "sirv": "^3.0.0" 831 + }, 832 + "bin": { 833 + "svelte-kit": "svelte-kit.js" 834 + }, 835 + "engines": { 836 + "node": ">=18.13" 837 + }, 838 + "peerDependencies": { 839 + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", 840 + "svelte": "^4.0.0 || ^5.0.0-next.0", 841 + "vite": "^5.0.3 || ^6.0.0" 842 + } 843 + }, 844 + "node_modules/@sveltejs/vite-plugin-svelte": { 845 + "version": "5.0.3", 846 + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.0.3.tgz", 847 + "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", 848 + "dev": true, 849 + "license": "MIT", 850 + "dependencies": { 851 + "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", 852 + "debug": "^4.4.0", 853 + "deepmerge": "^4.3.1", 854 + "kleur": "^4.1.5", 855 + "magic-string": "^0.30.15", 856 + "vitefu": "^1.0.4" 857 + }, 858 + "engines": { 859 + "node": "^18.0.0 || ^20.0.0 || >=22" 860 + }, 861 + "peerDependencies": { 862 + "svelte": "^5.0.0", 863 + "vite": "^6.0.0" 864 + } 865 + }, 866 + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { 867 + "version": "4.0.1", 868 + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", 869 + "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", 870 + "dev": true, 871 + "license": "MIT", 872 + "dependencies": { 873 + "debug": "^4.3.7" 874 + }, 875 + "engines": { 876 + "node": "^18.0.0 || ^20.0.0 || >=22" 877 + }, 878 + "peerDependencies": { 879 + "@sveltejs/vite-plugin-svelte": "^5.0.0", 880 + "svelte": "^5.0.0", 881 + "vite": "^6.0.0" 882 + } 883 + }, 884 + "node_modules/@tailwindcss/node": { 885 + "version": "4.0.14", 886 + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.14.tgz", 887 + "integrity": "sha512-Ux9NbFkKWYE4rfUFz6M5JFLs/GEYP6ysxT8uSyPn6aTbh2K3xDE1zz++eVK4Vwx799fzMF8CID9sdHn4j/Ab8w==", 888 + "dev": true, 889 + "license": "MIT", 890 + "dependencies": { 891 + "enhanced-resolve": "^5.18.1", 892 + "jiti": "^2.4.2", 893 + "tailwindcss": "4.0.14" 894 + } 895 + }, 896 + "node_modules/@tailwindcss/oxide": { 897 + "version": "4.0.14", 898 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.0.14.tgz", 899 + "integrity": "sha512-M8VCNyO/NBi5vJ2cRcI9u8w7Si+i76a7o1vveoGtbbjpEYJZYiyc7f2VGps/DqawO56l3tImIbq2OT/533jcrA==", 900 + "dev": true, 901 + "license": "MIT", 902 + "engines": { 903 + "node": ">= 10" 904 + }, 905 + "optionalDependencies": { 906 + "@tailwindcss/oxide-android-arm64": "4.0.14", 907 + "@tailwindcss/oxide-darwin-arm64": "4.0.14", 908 + "@tailwindcss/oxide-darwin-x64": "4.0.14", 909 + "@tailwindcss/oxide-freebsd-x64": "4.0.14", 910 + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.14", 911 + "@tailwindcss/oxide-linux-arm64-gnu": "4.0.14", 912 + "@tailwindcss/oxide-linux-arm64-musl": "4.0.14", 913 + "@tailwindcss/oxide-linux-x64-gnu": "4.0.14", 914 + "@tailwindcss/oxide-linux-x64-musl": "4.0.14", 915 + "@tailwindcss/oxide-win32-arm64-msvc": "4.0.14", 916 + "@tailwindcss/oxide-win32-x64-msvc": "4.0.14" 917 + } 918 + }, 919 + "node_modules/@tailwindcss/oxide-android-arm64": { 920 + "version": "4.0.14", 921 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.14.tgz", 922 + "integrity": "sha512-VBFKC2rFyfJ5J8lRwjy6ub3rgpY186kAcYgiUr8ArR8BAZzMruyeKJ6mlsD22Zp5ZLcPW/FXMasJiJBx0WsdQg==", 923 + "cpu": [ 924 + "arm64" 925 + ], 926 + "dev": true, 927 + "license": "MIT", 928 + "optional": true, 929 + "os": [ 930 + "android" 931 + ], 932 + "engines": { 933 + "node": ">= 10" 934 + } 935 + }, 936 + "node_modules/@tailwindcss/oxide-darwin-arm64": { 937 + "version": "4.0.14", 938 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.14.tgz", 939 + "integrity": "sha512-U3XOwLrefGr2YQZ9DXasDSNWGPZBCh8F62+AExBEDMLDfvLLgI/HDzY8Oq8p/JtqkAY38sWPOaNnRwEGKU5Zmg==", 940 + "cpu": [ 941 + "arm64" 942 + ], 943 + "dev": true, 944 + "license": "MIT", 945 + "optional": true, 946 + "os": [ 947 + "darwin" 948 + ], 949 + "engines": { 950 + "node": ">= 10" 951 + } 952 + }, 953 + "node_modules/@tailwindcss/oxide-darwin-x64": { 954 + "version": "4.0.14", 955 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.14.tgz", 956 + "integrity": "sha512-V5AjFuc3ndWGnOi1d379UsODb0TzAS2DYIP/lwEbfvafUaD2aNZIcbwJtYu2DQqO2+s/XBvDVA+w4yUyaewRwg==", 957 + "cpu": [ 958 + "x64" 959 + ], 960 + "dev": true, 961 + "license": "MIT", 962 + "optional": true, 963 + "os": [ 964 + "darwin" 965 + ], 966 + "engines": { 967 + "node": ">= 10" 968 + } 969 + }, 970 + "node_modules/@tailwindcss/oxide-freebsd-x64": { 971 + "version": "4.0.14", 972 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.14.tgz", 973 + "integrity": "sha512-tXvtxbaZfcPfqBwW3f53lTcyH6EDT+1eT7yabwcfcxTs+8yTPqxsDUhrqe9MrnEzpNkd+R/QAjJapfd4tjWdLg==", 974 + "cpu": [ 975 + "x64" 976 + ], 977 + "dev": true, 978 + "license": "MIT", 979 + "optional": true, 980 + "os": [ 981 + "freebsd" 982 + ], 983 + "engines": { 984 + "node": ">= 10" 985 + } 986 + }, 987 + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { 988 + "version": "4.0.14", 989 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.14.tgz", 990 + "integrity": "sha512-cSeLNWWqIWeSTmBntQvyY2/2gcLX8rkPFfDDTQVF8qbRcRMVPLxBvFVJyfSAYRNch6ZyVH2GI6dtgALOBDpdNA==", 991 + "cpu": [ 992 + "arm" 993 + ], 994 + "dev": true, 995 + "license": "MIT", 996 + "optional": true, 997 + "os": [ 998 + "linux" 999 + ], 1000 + "engines": { 1001 + "node": ">= 10" 1002 + } 1003 + }, 1004 + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { 1005 + "version": "4.0.14", 1006 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.14.tgz", 1007 + "integrity": "sha512-bwDWLBalXFMDItcSXzFk6y7QKvj6oFlaY9vM+agTlwFL1n1OhDHYLZkSjaYsh6KCeG0VB0r7H8PUJVOM1LRZyg==", 1008 + "cpu": [ 1009 + "arm64" 1010 + ], 1011 + "dev": true, 1012 + "license": "MIT", 1013 + "optional": true, 1014 + "os": [ 1015 + "linux" 1016 + ], 1017 + "engines": { 1018 + "node": ">= 10" 1019 + } 1020 + }, 1021 + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { 1022 + "version": "4.0.14", 1023 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.14.tgz", 1024 + "integrity": "sha512-gVkJdnR/L6iIcGYXx64HGJRmlme2FGr/aZH0W6u4A3RgPMAb+6ELRLi+UBiH83RXBm9vwCfkIC/q8T51h8vUJQ==", 1025 + "cpu": [ 1026 + "arm64" 1027 + ], 1028 + "dev": true, 1029 + "license": "MIT", 1030 + "optional": true, 1031 + "os": [ 1032 + "linux" 1033 + ], 1034 + "engines": { 1035 + "node": ">= 10" 1036 + } 1037 + }, 1038 + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { 1039 + "version": "4.0.14", 1040 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.14.tgz", 1041 + "integrity": "sha512-EE+EQ+c6tTpzsg+LGO1uuusjXxYx0Q00JE5ubcIGfsogSKth8n8i2BcS2wYTQe4jXGs+BQs35l78BIPzgwLddw==", 1042 + "cpu": [ 1043 + "x64" 1044 + ], 1045 + "dev": true, 1046 + "license": "MIT", 1047 + "optional": true, 1048 + "os": [ 1049 + "linux" 1050 + ], 1051 + "engines": { 1052 + "node": ">= 10" 1053 + } 1054 + }, 1055 + "node_modules/@tailwindcss/oxide-linux-x64-musl": { 1056 + "version": "4.0.14", 1057 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.14.tgz", 1058 + "integrity": "sha512-KCCOzo+L6XPT0oUp2Jwh233ETRQ/F6cwUnMnR0FvMUCbkDAzHbcyOgpfuAtRa5HD0WbTbH4pVD+S0pn1EhNfbw==", 1059 + "cpu": [ 1060 + "x64" 1061 + ], 1062 + "dev": true, 1063 + "license": "MIT", 1064 + "optional": true, 1065 + "os": [ 1066 + "linux" 1067 + ], 1068 + "engines": { 1069 + "node": ">= 10" 1070 + } 1071 + }, 1072 + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { 1073 + "version": "4.0.14", 1074 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.14.tgz", 1075 + "integrity": "sha512-AHObFiFL9lNYcm3tZSPqa/cHGpM5wOrNmM2uOMoKppp+0Hom5uuyRh0QkOp7jftsHZdrZUpmoz0Mp6vhh2XtUg==", 1076 + "cpu": [ 1077 + "arm64" 1078 + ], 1079 + "dev": true, 1080 + "license": "MIT", 1081 + "optional": true, 1082 + "os": [ 1083 + "win32" 1084 + ], 1085 + "engines": { 1086 + "node": ">= 10" 1087 + } 1088 + }, 1089 + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { 1090 + "version": "4.0.14", 1091 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.14.tgz", 1092 + "integrity": "sha512-rNXXMDJfCJLw/ZaFTOLOHoGULxyXfh2iXTGiChFiYTSgKBKQHIGEpV0yn5N25WGzJJ+VBnRjHzlmDqRV+d//oQ==", 1093 + "cpu": [ 1094 + "x64" 1095 + ], 1096 + "dev": true, 1097 + "license": "MIT", 1098 + "optional": true, 1099 + "os": [ 1100 + "win32" 1101 + ], 1102 + "engines": { 1103 + "node": ">= 10" 1104 + } 1105 + }, 1106 + "node_modules/@tailwindcss/vite": { 1107 + "version": "4.0.14", 1108 + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.14.tgz", 1109 + "integrity": "sha512-y69ztPTRFy+13EPS/7dEFVl7q2Goh1pQueVO8IfGeyqSpcx/joNJXFk0lLhMgUbF0VFJotwRSb9ZY7Xoq3r26Q==", 1110 + "dev": true, 1111 + "license": "MIT", 1112 + "dependencies": { 1113 + "@tailwindcss/node": "4.0.14", 1114 + "@tailwindcss/oxide": "4.0.14", 1115 + "lightningcss": "1.29.2", 1116 + "tailwindcss": "4.0.14" 1117 + }, 1118 + "peerDependencies": { 1119 + "vite": "^5.2.0 || ^6" 1120 + } 1121 + }, 1122 + "node_modules/@types/cookie": { 1123 + "version": "0.6.0", 1124 + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", 1125 + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", 1126 + "dev": true, 1127 + "license": "MIT" 1128 + }, 1129 + "node_modules/@types/estree": { 1130 + "version": "1.0.6", 1131 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 1132 + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 1133 + "dev": true, 1134 + "license": "MIT" 1135 + }, 1136 + "node_modules/acorn": { 1137 + "version": "8.14.1", 1138 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", 1139 + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", 1140 + "dev": true, 1141 + "license": "MIT", 1142 + "bin": { 1143 + "acorn": "bin/acorn" 1144 + }, 1145 + "engines": { 1146 + "node": ">=0.4.0" 1147 + } 1148 + }, 1149 + "node_modules/aria-query": { 1150 + "version": "5.3.2", 1151 + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", 1152 + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", 1153 + "dev": true, 1154 + "license": "Apache-2.0", 1155 + "engines": { 1156 + "node": ">= 0.4" 1157 + } 1158 + }, 1159 + "node_modules/axobject-query": { 1160 + "version": "4.1.0", 1161 + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", 1162 + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", 1163 + "dev": true, 1164 + "license": "Apache-2.0", 1165 + "engines": { 1166 + "node": ">= 0.4" 1167 + } 1168 + }, 1169 + "node_modules/chokidar": { 1170 + "version": "4.0.3", 1171 + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", 1172 + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", 1173 + "dev": true, 1174 + "license": "MIT", 1175 + "dependencies": { 1176 + "readdirp": "^4.0.1" 1177 + }, 1178 + "engines": { 1179 + "node": ">= 14.16.0" 1180 + }, 1181 + "funding": { 1182 + "url": "https://paulmillr.com/funding/" 1183 + } 1184 + }, 1185 + "node_modules/clsx": { 1186 + "version": "2.1.1", 1187 + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", 1188 + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", 1189 + "dev": true, 1190 + "license": "MIT", 1191 + "engines": { 1192 + "node": ">=6" 1193 + } 1194 + }, 1195 + "node_modules/cookie": { 1196 + "version": "0.6.0", 1197 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", 1198 + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", 1199 + "dev": true, 1200 + "license": "MIT", 1201 + "engines": { 1202 + "node": ">= 0.6" 1203 + } 1204 + }, 1205 + "node_modules/debug": { 1206 + "version": "4.4.0", 1207 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1208 + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1209 + "dev": true, 1210 + "license": "MIT", 1211 + "dependencies": { 1212 + "ms": "^2.1.3" 1213 + }, 1214 + "engines": { 1215 + "node": ">=6.0" 1216 + }, 1217 + "peerDependenciesMeta": { 1218 + "supports-color": { 1219 + "optional": true 1220 + } 1221 + } 1222 + }, 1223 + "node_modules/deepmerge": { 1224 + "version": "4.3.1", 1225 + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 1226 + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 1227 + "dev": true, 1228 + "license": "MIT", 1229 + "engines": { 1230 + "node": ">=0.10.0" 1231 + } 1232 + }, 1233 + "node_modules/detect-libc": { 1234 + "version": "2.0.3", 1235 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", 1236 + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", 1237 + "dev": true, 1238 + "license": "Apache-2.0", 1239 + "engines": { 1240 + "node": ">=8" 1241 + } 1242 + }, 1243 + "node_modules/devalue": { 1244 + "version": "5.1.1", 1245 + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", 1246 + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", 1247 + "dev": true, 1248 + "license": "MIT" 1249 + }, 1250 + "node_modules/enhanced-resolve": { 1251 + "version": "5.18.1", 1252 + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", 1253 + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", 1254 + "dev": true, 1255 + "license": "MIT", 1256 + "dependencies": { 1257 + "graceful-fs": "^4.2.4", 1258 + "tapable": "^2.2.0" 1259 + }, 1260 + "engines": { 1261 + "node": ">=10.13.0" 1262 + } 1263 + }, 1264 + "node_modules/esbuild": { 1265 + "version": "0.25.1", 1266 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", 1267 + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", 1268 + "dev": true, 1269 + "hasInstallScript": true, 1270 + "license": "MIT", 1271 + "bin": { 1272 + "esbuild": "bin/esbuild" 1273 + }, 1274 + "engines": { 1275 + "node": ">=18" 1276 + }, 1277 + "optionalDependencies": { 1278 + "@esbuild/aix-ppc64": "0.25.1", 1279 + "@esbuild/android-arm": "0.25.1", 1280 + "@esbuild/android-arm64": "0.25.1", 1281 + "@esbuild/android-x64": "0.25.1", 1282 + "@esbuild/darwin-arm64": "0.25.1", 1283 + "@esbuild/darwin-x64": "0.25.1", 1284 + "@esbuild/freebsd-arm64": "0.25.1", 1285 + "@esbuild/freebsd-x64": "0.25.1", 1286 + "@esbuild/linux-arm": "0.25.1", 1287 + "@esbuild/linux-arm64": "0.25.1", 1288 + "@esbuild/linux-ia32": "0.25.1", 1289 + "@esbuild/linux-loong64": "0.25.1", 1290 + "@esbuild/linux-mips64el": "0.25.1", 1291 + "@esbuild/linux-ppc64": "0.25.1", 1292 + "@esbuild/linux-riscv64": "0.25.1", 1293 + "@esbuild/linux-s390x": "0.25.1", 1294 + "@esbuild/linux-x64": "0.25.1", 1295 + "@esbuild/netbsd-arm64": "0.25.1", 1296 + "@esbuild/netbsd-x64": "0.25.1", 1297 + "@esbuild/openbsd-arm64": "0.25.1", 1298 + "@esbuild/openbsd-x64": "0.25.1", 1299 + "@esbuild/sunos-x64": "0.25.1", 1300 + "@esbuild/win32-arm64": "0.25.1", 1301 + "@esbuild/win32-ia32": "0.25.1", 1302 + "@esbuild/win32-x64": "0.25.1" 1303 + } 1304 + }, 1305 + "node_modules/esm-env": { 1306 + "version": "1.2.2", 1307 + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", 1308 + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", 1309 + "dev": true, 1310 + "license": "MIT" 1311 + }, 1312 + "node_modules/esrap": { 1313 + "version": "1.4.5", 1314 + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.5.tgz", 1315 + "integrity": "sha512-CjNMjkBWWZeHn+VX+gS8YvFwJ5+NDhg8aWZBSFJPR8qQduDNjbJodA2WcwCm7uQa5Rjqj+nZvVmceg1RbHFB9g==", 1316 + "dev": true, 1317 + "license": "MIT", 1318 + "dependencies": { 1319 + "@jridgewell/sourcemap-codec": "^1.4.15" 1320 + } 1321 + }, 1322 + "node_modules/fdir": { 1323 + "version": "6.4.3", 1324 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", 1325 + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", 1326 + "dev": true, 1327 + "license": "MIT", 1328 + "peerDependencies": { 1329 + "picomatch": "^3 || ^4" 1330 + }, 1331 + "peerDependenciesMeta": { 1332 + "picomatch": { 1333 + "optional": true 1334 + } 1335 + } 1336 + }, 1337 + "node_modules/fsevents": { 1338 + "version": "2.3.3", 1339 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1340 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1341 + "dev": true, 1342 + "hasInstallScript": true, 1343 + "license": "MIT", 1344 + "optional": true, 1345 + "os": [ 1346 + "darwin" 1347 + ], 1348 + "engines": { 1349 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1350 + } 1351 + }, 1352 + "node_modules/graceful-fs": { 1353 + "version": "4.2.11", 1354 + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1355 + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1356 + "dev": true, 1357 + "license": "ISC" 1358 + }, 1359 + "node_modules/import-meta-resolve": { 1360 + "version": "4.1.0", 1361 + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", 1362 + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", 1363 + "dev": true, 1364 + "license": "MIT", 1365 + "funding": { 1366 + "type": "github", 1367 + "url": "https://github.com/sponsors/wooorm" 1368 + } 1369 + }, 1370 + "node_modules/is-reference": { 1371 + "version": "3.0.3", 1372 + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", 1373 + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", 1374 + "dev": true, 1375 + "license": "MIT", 1376 + "dependencies": { 1377 + "@types/estree": "^1.0.6" 1378 + } 1379 + }, 1380 + "node_modules/jiti": { 1381 + "version": "2.4.2", 1382 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", 1383 + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", 1384 + "dev": true, 1385 + "license": "MIT", 1386 + "bin": { 1387 + "jiti": "lib/jiti-cli.mjs" 1388 + } 1389 + }, 1390 + "node_modules/kleur": { 1391 + "version": "4.1.5", 1392 + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 1393 + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 1394 + "dev": true, 1395 + "license": "MIT", 1396 + "engines": { 1397 + "node": ">=6" 1398 + } 1399 + }, 1400 + "node_modules/lightningcss": { 1401 + "version": "1.29.2", 1402 + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", 1403 + "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", 1404 + "dev": true, 1405 + "license": "MPL-2.0", 1406 + "dependencies": { 1407 + "detect-libc": "^2.0.3" 1408 + }, 1409 + "engines": { 1410 + "node": ">= 12.0.0" 1411 + }, 1412 + "funding": { 1413 + "type": "opencollective", 1414 + "url": "https://opencollective.com/parcel" 1415 + }, 1416 + "optionalDependencies": { 1417 + "lightningcss-darwin-arm64": "1.29.2", 1418 + "lightningcss-darwin-x64": "1.29.2", 1419 + "lightningcss-freebsd-x64": "1.29.2", 1420 + "lightningcss-linux-arm-gnueabihf": "1.29.2", 1421 + "lightningcss-linux-arm64-gnu": "1.29.2", 1422 + "lightningcss-linux-arm64-musl": "1.29.2", 1423 + "lightningcss-linux-x64-gnu": "1.29.2", 1424 + "lightningcss-linux-x64-musl": "1.29.2", 1425 + "lightningcss-win32-arm64-msvc": "1.29.2", 1426 + "lightningcss-win32-x64-msvc": "1.29.2" 1427 + } 1428 + }, 1429 + "node_modules/lightningcss-darwin-arm64": { 1430 + "version": "1.29.2", 1431 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", 1432 + "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", 1433 + "cpu": [ 1434 + "arm64" 1435 + ], 1436 + "dev": true, 1437 + "license": "MPL-2.0", 1438 + "optional": true, 1439 + "os": [ 1440 + "darwin" 1441 + ], 1442 + "engines": { 1443 + "node": ">= 12.0.0" 1444 + }, 1445 + "funding": { 1446 + "type": "opencollective", 1447 + "url": "https://opencollective.com/parcel" 1448 + } 1449 + }, 1450 + "node_modules/lightningcss-darwin-x64": { 1451 + "version": "1.29.2", 1452 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", 1453 + "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", 1454 + "cpu": [ 1455 + "x64" 1456 + ], 1457 + "dev": true, 1458 + "license": "MPL-2.0", 1459 + "optional": true, 1460 + "os": [ 1461 + "darwin" 1462 + ], 1463 + "engines": { 1464 + "node": ">= 12.0.0" 1465 + }, 1466 + "funding": { 1467 + "type": "opencollective", 1468 + "url": "https://opencollective.com/parcel" 1469 + } 1470 + }, 1471 + "node_modules/lightningcss-freebsd-x64": { 1472 + "version": "1.29.2", 1473 + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", 1474 + "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", 1475 + "cpu": [ 1476 + "x64" 1477 + ], 1478 + "dev": true, 1479 + "license": "MPL-2.0", 1480 + "optional": true, 1481 + "os": [ 1482 + "freebsd" 1483 + ], 1484 + "engines": { 1485 + "node": ">= 12.0.0" 1486 + }, 1487 + "funding": { 1488 + "type": "opencollective", 1489 + "url": "https://opencollective.com/parcel" 1490 + } 1491 + }, 1492 + "node_modules/lightningcss-linux-arm-gnueabihf": { 1493 + "version": "1.29.2", 1494 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", 1495 + "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", 1496 + "cpu": [ 1497 + "arm" 1498 + ], 1499 + "dev": true, 1500 + "license": "MPL-2.0", 1501 + "optional": true, 1502 + "os": [ 1503 + "linux" 1504 + ], 1505 + "engines": { 1506 + "node": ">= 12.0.0" 1507 + }, 1508 + "funding": { 1509 + "type": "opencollective", 1510 + "url": "https://opencollective.com/parcel" 1511 + } 1512 + }, 1513 + "node_modules/lightningcss-linux-arm64-gnu": { 1514 + "version": "1.29.2", 1515 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", 1516 + "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", 1517 + "cpu": [ 1518 + "arm64" 1519 + ], 1520 + "dev": true, 1521 + "license": "MPL-2.0", 1522 + "optional": true, 1523 + "os": [ 1524 + "linux" 1525 + ], 1526 + "engines": { 1527 + "node": ">= 12.0.0" 1528 + }, 1529 + "funding": { 1530 + "type": "opencollective", 1531 + "url": "https://opencollective.com/parcel" 1532 + } 1533 + }, 1534 + "node_modules/lightningcss-linux-arm64-musl": { 1535 + "version": "1.29.2", 1536 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", 1537 + "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", 1538 + "cpu": [ 1539 + "arm64" 1540 + ], 1541 + "dev": true, 1542 + "license": "MPL-2.0", 1543 + "optional": true, 1544 + "os": [ 1545 + "linux" 1546 + ], 1547 + "engines": { 1548 + "node": ">= 12.0.0" 1549 + }, 1550 + "funding": { 1551 + "type": "opencollective", 1552 + "url": "https://opencollective.com/parcel" 1553 + } 1554 + }, 1555 + "node_modules/lightningcss-linux-x64-gnu": { 1556 + "version": "1.29.2", 1557 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", 1558 + "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", 1559 + "cpu": [ 1560 + "x64" 1561 + ], 1562 + "dev": true, 1563 + "license": "MPL-2.0", 1564 + "optional": true, 1565 + "os": [ 1566 + "linux" 1567 + ], 1568 + "engines": { 1569 + "node": ">= 12.0.0" 1570 + }, 1571 + "funding": { 1572 + "type": "opencollective", 1573 + "url": "https://opencollective.com/parcel" 1574 + } 1575 + }, 1576 + "node_modules/lightningcss-linux-x64-musl": { 1577 + "version": "1.29.2", 1578 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", 1579 + "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", 1580 + "cpu": [ 1581 + "x64" 1582 + ], 1583 + "dev": true, 1584 + "license": "MPL-2.0", 1585 + "optional": true, 1586 + "os": [ 1587 + "linux" 1588 + ], 1589 + "engines": { 1590 + "node": ">= 12.0.0" 1591 + }, 1592 + "funding": { 1593 + "type": "opencollective", 1594 + "url": "https://opencollective.com/parcel" 1595 + } 1596 + }, 1597 + "node_modules/lightningcss-win32-arm64-msvc": { 1598 + "version": "1.29.2", 1599 + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", 1600 + "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", 1601 + "cpu": [ 1602 + "arm64" 1603 + ], 1604 + "dev": true, 1605 + "license": "MPL-2.0", 1606 + "optional": true, 1607 + "os": [ 1608 + "win32" 1609 + ], 1610 + "engines": { 1611 + "node": ">= 12.0.0" 1612 + }, 1613 + "funding": { 1614 + "type": "opencollective", 1615 + "url": "https://opencollective.com/parcel" 1616 + } 1617 + }, 1618 + "node_modules/lightningcss-win32-x64-msvc": { 1619 + "version": "1.29.2", 1620 + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", 1621 + "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", 1622 + "cpu": [ 1623 + "x64" 1624 + ], 1625 + "dev": true, 1626 + "license": "MPL-2.0", 1627 + "optional": true, 1628 + "os": [ 1629 + "win32" 1630 + ], 1631 + "engines": { 1632 + "node": ">= 12.0.0" 1633 + }, 1634 + "funding": { 1635 + "type": "opencollective", 1636 + "url": "https://opencollective.com/parcel" 1637 + } 1638 + }, 1639 + "node_modules/locate-character": { 1640 + "version": "3.0.0", 1641 + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", 1642 + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", 1643 + "dev": true, 1644 + "license": "MIT" 1645 + }, 1646 + "node_modules/magic-string": { 1647 + "version": "0.30.17", 1648 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1649 + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1650 + "dev": true, 1651 + "license": "MIT", 1652 + "dependencies": { 1653 + "@jridgewell/sourcemap-codec": "^1.5.0" 1654 + } 1655 + }, 1656 + "node_modules/mri": { 1657 + "version": "1.2.0", 1658 + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", 1659 + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", 1660 + "dev": true, 1661 + "license": "MIT", 1662 + "engines": { 1663 + "node": ">=4" 1664 + } 1665 + }, 1666 + "node_modules/mrmime": { 1667 + "version": "2.0.1", 1668 + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", 1669 + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", 1670 + "dev": true, 1671 + "license": "MIT", 1672 + "engines": { 1673 + "node": ">=10" 1674 + } 1675 + }, 1676 + "node_modules/ms": { 1677 + "version": "2.1.3", 1678 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1679 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1680 + "dev": true, 1681 + "license": "MIT" 1682 + }, 1683 + "node_modules/nanoid": { 1684 + "version": "3.3.10", 1685 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", 1686 + "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", 1687 + "dev": true, 1688 + "funding": [ 1689 + { 1690 + "type": "github", 1691 + "url": "https://github.com/sponsors/ai" 1692 + } 1693 + ], 1694 + "license": "MIT", 1695 + "bin": { 1696 + "nanoid": "bin/nanoid.cjs" 1697 + }, 1698 + "engines": { 1699 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1700 + } 1701 + }, 1702 + "node_modules/picocolors": { 1703 + "version": "1.1.1", 1704 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1705 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1706 + "dev": true, 1707 + "license": "ISC" 1708 + }, 1709 + "node_modules/postcss": { 1710 + "version": "8.5.3", 1711 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 1712 + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 1713 + "dev": true, 1714 + "funding": [ 1715 + { 1716 + "type": "opencollective", 1717 + "url": "https://opencollective.com/postcss/" 1718 + }, 1719 + { 1720 + "type": "tidelift", 1721 + "url": "https://tidelift.com/funding/github/npm/postcss" 1722 + }, 1723 + { 1724 + "type": "github", 1725 + "url": "https://github.com/sponsors/ai" 1726 + } 1727 + ], 1728 + "license": "MIT", 1729 + "dependencies": { 1730 + "nanoid": "^3.3.8", 1731 + "picocolors": "^1.1.1", 1732 + "source-map-js": "^1.2.1" 1733 + }, 1734 + "engines": { 1735 + "node": "^10 || ^12 || >=14" 1736 + } 1737 + }, 1738 + "node_modules/prettier": { 1739 + "version": "3.5.3", 1740 + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", 1741 + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", 1742 + "dev": true, 1743 + "license": "MIT", 1744 + "bin": { 1745 + "prettier": "bin/prettier.cjs" 1746 + }, 1747 + "engines": { 1748 + "node": ">=14" 1749 + }, 1750 + "funding": { 1751 + "url": "https://github.com/prettier/prettier?sponsor=1" 1752 + } 1753 + }, 1754 + "node_modules/prettier-plugin-svelte": { 1755 + "version": "3.3.3", 1756 + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz", 1757 + "integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==", 1758 + "dev": true, 1759 + "license": "MIT", 1760 + "peerDependencies": { 1761 + "prettier": "^3.0.0", 1762 + "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" 1763 + } 1764 + }, 1765 + "node_modules/prettier-plugin-tailwindcss": { 1766 + "version": "0.6.11", 1767 + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", 1768 + "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", 1769 + "dev": true, 1770 + "license": "MIT", 1771 + "engines": { 1772 + "node": ">=14.21.3" 1773 + }, 1774 + "peerDependencies": { 1775 + "@ianvs/prettier-plugin-sort-imports": "*", 1776 + "@prettier/plugin-pug": "*", 1777 + "@shopify/prettier-plugin-liquid": "*", 1778 + "@trivago/prettier-plugin-sort-imports": "*", 1779 + "@zackad/prettier-plugin-twig": "*", 1780 + "prettier": "^3.0", 1781 + "prettier-plugin-astro": "*", 1782 + "prettier-plugin-css-order": "*", 1783 + "prettier-plugin-import-sort": "*", 1784 + "prettier-plugin-jsdoc": "*", 1785 + "prettier-plugin-marko": "*", 1786 + "prettier-plugin-multiline-arrays": "*", 1787 + "prettier-plugin-organize-attributes": "*", 1788 + "prettier-plugin-organize-imports": "*", 1789 + "prettier-plugin-sort-imports": "*", 1790 + "prettier-plugin-style-order": "*", 1791 + "prettier-plugin-svelte": "*" 1792 + }, 1793 + "peerDependenciesMeta": { 1794 + "@ianvs/prettier-plugin-sort-imports": { 1795 + "optional": true 1796 + }, 1797 + "@prettier/plugin-pug": { 1798 + "optional": true 1799 + }, 1800 + "@shopify/prettier-plugin-liquid": { 1801 + "optional": true 1802 + }, 1803 + "@trivago/prettier-plugin-sort-imports": { 1804 + "optional": true 1805 + }, 1806 + "@zackad/prettier-plugin-twig": { 1807 + "optional": true 1808 + }, 1809 + "prettier-plugin-astro": { 1810 + "optional": true 1811 + }, 1812 + "prettier-plugin-css-order": { 1813 + "optional": true 1814 + }, 1815 + "prettier-plugin-import-sort": { 1816 + "optional": true 1817 + }, 1818 + "prettier-plugin-jsdoc": { 1819 + "optional": true 1820 + }, 1821 + "prettier-plugin-marko": { 1822 + "optional": true 1823 + }, 1824 + "prettier-plugin-multiline-arrays": { 1825 + "optional": true 1826 + }, 1827 + "prettier-plugin-organize-attributes": { 1828 + "optional": true 1829 + }, 1830 + "prettier-plugin-organize-imports": { 1831 + "optional": true 1832 + }, 1833 + "prettier-plugin-sort-imports": { 1834 + "optional": true 1835 + }, 1836 + "prettier-plugin-style-order": { 1837 + "optional": true 1838 + }, 1839 + "prettier-plugin-svelte": { 1840 + "optional": true 1841 + } 1842 + } 1843 + }, 1844 + "node_modules/readdirp": { 1845 + "version": "4.1.2", 1846 + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", 1847 + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", 1848 + "dev": true, 1849 + "license": "MIT", 1850 + "engines": { 1851 + "node": ">= 14.18.0" 1852 + }, 1853 + "funding": { 1854 + "type": "individual", 1855 + "url": "https://paulmillr.com/funding/" 1856 + } 1857 + }, 1858 + "node_modules/rollup": { 1859 + "version": "4.36.0", 1860 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.36.0.tgz", 1861 + "integrity": "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==", 1862 + "dev": true, 1863 + "license": "MIT", 1864 + "dependencies": { 1865 + "@types/estree": "1.0.6" 1866 + }, 1867 + "bin": { 1868 + "rollup": "dist/bin/rollup" 1869 + }, 1870 + "engines": { 1871 + "node": ">=18.0.0", 1872 + "npm": ">=8.0.0" 1873 + }, 1874 + "optionalDependencies": { 1875 + "@rollup/rollup-android-arm-eabi": "4.36.0", 1876 + "@rollup/rollup-android-arm64": "4.36.0", 1877 + "@rollup/rollup-darwin-arm64": "4.36.0", 1878 + "@rollup/rollup-darwin-x64": "4.36.0", 1879 + "@rollup/rollup-freebsd-arm64": "4.36.0", 1880 + "@rollup/rollup-freebsd-x64": "4.36.0", 1881 + "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", 1882 + "@rollup/rollup-linux-arm-musleabihf": "4.36.0", 1883 + "@rollup/rollup-linux-arm64-gnu": "4.36.0", 1884 + "@rollup/rollup-linux-arm64-musl": "4.36.0", 1885 + "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", 1886 + "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", 1887 + "@rollup/rollup-linux-riscv64-gnu": "4.36.0", 1888 + "@rollup/rollup-linux-s390x-gnu": "4.36.0", 1889 + "@rollup/rollup-linux-x64-gnu": "4.36.0", 1890 + "@rollup/rollup-linux-x64-musl": "4.36.0", 1891 + "@rollup/rollup-win32-arm64-msvc": "4.36.0", 1892 + "@rollup/rollup-win32-ia32-msvc": "4.36.0", 1893 + "@rollup/rollup-win32-x64-msvc": "4.36.0", 1894 + "fsevents": "~2.3.2" 1895 + } 1896 + }, 1897 + "node_modules/sade": { 1898 + "version": "1.8.1", 1899 + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", 1900 + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", 1901 + "dev": true, 1902 + "license": "MIT", 1903 + "dependencies": { 1904 + "mri": "^1.1.0" 1905 + }, 1906 + "engines": { 1907 + "node": ">=6" 1908 + } 1909 + }, 1910 + "node_modules/set-cookie-parser": { 1911 + "version": "2.7.1", 1912 + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", 1913 + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", 1914 + "dev": true, 1915 + "license": "MIT" 1916 + }, 1917 + "node_modules/sirv": { 1918 + "version": "3.0.1", 1919 + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", 1920 + "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", 1921 + "dev": true, 1922 + "license": "MIT", 1923 + "dependencies": { 1924 + "@polka/url": "^1.0.0-next.24", 1925 + "mrmime": "^2.0.0", 1926 + "totalist": "^3.0.0" 1927 + }, 1928 + "engines": { 1929 + "node": ">=18" 1930 + } 1931 + }, 1932 + "node_modules/source-map-js": { 1933 + "version": "1.2.1", 1934 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1935 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1936 + "dev": true, 1937 + "license": "BSD-3-Clause", 1938 + "engines": { 1939 + "node": ">=0.10.0" 1940 + } 1941 + }, 1942 + "node_modules/svelte": { 1943 + "version": "5.23.1", 1944 + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.23.1.tgz", 1945 + "integrity": "sha512-DUu3e5tQDO+PtKffjqJ548YfeKtw2Rqc9/+nlP26DZ0AopWTJNylkNnTOP/wcgIt1JSnovyISxEZ/lDR1OhbOw==", 1946 + "dev": true, 1947 + "license": "MIT", 1948 + "dependencies": { 1949 + "@ampproject/remapping": "^2.3.0", 1950 + "@jridgewell/sourcemap-codec": "^1.5.0", 1951 + "@sveltejs/acorn-typescript": "^1.0.5", 1952 + "@types/estree": "^1.0.5", 1953 + "acorn": "^8.12.1", 1954 + "aria-query": "^5.3.1", 1955 + "axobject-query": "^4.1.0", 1956 + "clsx": "^2.1.1", 1957 + "esm-env": "^1.2.1", 1958 + "esrap": "^1.4.3", 1959 + "is-reference": "^3.0.3", 1960 + "locate-character": "^3.0.0", 1961 + "magic-string": "^0.30.11", 1962 + "zimmerframe": "^1.1.2" 1963 + }, 1964 + "engines": { 1965 + "node": ">=18" 1966 + } 1967 + }, 1968 + "node_modules/svelte-check": { 1969 + "version": "4.1.5", 1970 + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.5.tgz", 1971 + "integrity": "sha512-Gb0T2IqBNe1tLB9EB1Qh+LOe+JB8wt2/rNBDGvkxQVvk8vNeAoG+vZgFB/3P5+zC7RWlyBlzm9dVjZFph/maIg==", 1972 + "dev": true, 1973 + "license": "MIT", 1974 + "dependencies": { 1975 + "@jridgewell/trace-mapping": "^0.3.25", 1976 + "chokidar": "^4.0.1", 1977 + "fdir": "^6.2.0", 1978 + "picocolors": "^1.0.0", 1979 + "sade": "^1.7.4" 1980 + }, 1981 + "bin": { 1982 + "svelte-check": "bin/svelte-check" 1983 + }, 1984 + "engines": { 1985 + "node": ">= 18.0.0" 1986 + }, 1987 + "peerDependencies": { 1988 + "svelte": "^4.0.0 || ^5.0.0-next.0", 1989 + "typescript": ">=5.0.0" 1990 + } 1991 + }, 1992 + "node_modules/tailwindcss": { 1993 + "version": "4.0.14", 1994 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.14.tgz", 1995 + "integrity": "sha512-92YT2dpt671tFiHH/e1ok9D987N9fHD5VWoly1CdPD/Cd1HMglvZwP3nx2yTj2lbXDAHt8QssZkxTLCCTNL+xw==", 1996 + "dev": true, 1997 + "license": "MIT" 1998 + }, 1999 + "node_modules/tapable": { 2000 + "version": "2.2.1", 2001 + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", 2002 + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", 2003 + "dev": true, 2004 + "license": "MIT", 2005 + "engines": { 2006 + "node": ">=6" 2007 + } 2008 + }, 2009 + "node_modules/totalist": { 2010 + "version": "3.0.1", 2011 + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", 2012 + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", 2013 + "dev": true, 2014 + "license": "MIT", 2015 + "engines": { 2016 + "node": ">=6" 2017 + } 2018 + }, 2019 + "node_modules/typescript": { 2020 + "version": "5.8.2", 2021 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", 2022 + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", 2023 + "dev": true, 2024 + "license": "Apache-2.0", 2025 + "bin": { 2026 + "tsc": "bin/tsc", 2027 + "tsserver": "bin/tsserver" 2028 + }, 2029 + "engines": { 2030 + "node": ">=14.17" 2031 + } 2032 + }, 2033 + "node_modules/vite": { 2034 + "version": "6.2.2", 2035 + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz", 2036 + "integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==", 2037 + "dev": true, 2038 + "license": "MIT", 2039 + "dependencies": { 2040 + "esbuild": "^0.25.0", 2041 + "postcss": "^8.5.3", 2042 + "rollup": "^4.30.1" 2043 + }, 2044 + "bin": { 2045 + "vite": "bin/vite.js" 2046 + }, 2047 + "engines": { 2048 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2049 + }, 2050 + "funding": { 2051 + "url": "https://github.com/vitejs/vite?sponsor=1" 2052 + }, 2053 + "optionalDependencies": { 2054 + "fsevents": "~2.3.3" 2055 + }, 2056 + "peerDependencies": { 2057 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2058 + "jiti": ">=1.21.0", 2059 + "less": "*", 2060 + "lightningcss": "^1.21.0", 2061 + "sass": "*", 2062 + "sass-embedded": "*", 2063 + "stylus": "*", 2064 + "sugarss": "*", 2065 + "terser": "^5.16.0", 2066 + "tsx": "^4.8.1", 2067 + "yaml": "^2.4.2" 2068 + }, 2069 + "peerDependenciesMeta": { 2070 + "@types/node": { 2071 + "optional": true 2072 + }, 2073 + "jiti": { 2074 + "optional": true 2075 + }, 2076 + "less": { 2077 + "optional": true 2078 + }, 2079 + "lightningcss": { 2080 + "optional": true 2081 + }, 2082 + "sass": { 2083 + "optional": true 2084 + }, 2085 + "sass-embedded": { 2086 + "optional": true 2087 + }, 2088 + "stylus": { 2089 + "optional": true 2090 + }, 2091 + "sugarss": { 2092 + "optional": true 2093 + }, 2094 + "terser": { 2095 + "optional": true 2096 + }, 2097 + "tsx": { 2098 + "optional": true 2099 + }, 2100 + "yaml": { 2101 + "optional": true 2102 + } 2103 + } 2104 + }, 2105 + "node_modules/vitefu": { 2106 + "version": "1.0.6", 2107 + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", 2108 + "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", 2109 + "dev": true, 2110 + "license": "MIT", 2111 + "workspaces": [ 2112 + "tests/deps/*", 2113 + "tests/projects/*" 2114 + ], 2115 + "peerDependencies": { 2116 + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" 2117 + }, 2118 + "peerDependenciesMeta": { 2119 + "vite": { 2120 + "optional": true 2121 + } 2122 + } 2123 + }, 2124 + "node_modules/zimmerframe": { 2125 + "version": "1.1.2", 2126 + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", 2127 + "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", 2128 + "dev": true, 2129 + "license": "MIT" 2130 + } 2131 + } 2132 + }
+30
package.json
··· 1 + { 2 + "name": "website", 3 + "private": true, 4 + "version": "0.0.1", 5 + "type": "module", 6 + "scripts": { 7 + "dev": "vite dev", 8 + "build": "vite build", 9 + "preview": "vite preview", 10 + "prepare": "svelte-kit sync || echo ''", 11 + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 12 + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 13 + "format": "prettier --write .", 14 + "lint": "prettier --check ." 15 + }, 16 + "devDependencies": { 17 + "@sveltejs/adapter-auto": "^4.0.0", 18 + "@sveltejs/kit": "^2.16.0", 19 + "@sveltejs/vite-plugin-svelte": "^5.0.0", 20 + "@tailwindcss/vite": "^4.0.0", 21 + "prettier": "^3.4.2", 22 + "prettier-plugin-svelte": "^3.3.3", 23 + "prettier-plugin-tailwindcss": "^0.6.11", 24 + "svelte": "^5.0.0", 25 + "svelte-check": "^4.0.0", 26 + "tailwindcss": "^4.0.0", 27 + "typescript": "^5.0.0", 28 + "vite": "^6.0.0" 29 + } 30 + }
+1
src/app.css
··· 1 + @import 'tailwindcss';
+13
src/app.d.ts
··· 1 + // See https://svelte.dev/docs/kit/types#app.d.ts 2 + // for information about these interfaces 3 + declare global { 4 + namespace App { 5 + // interface Error {} 6 + // interface Locals {} 7 + // interface PageData {} 8 + // interface PageState {} 9 + // interface Platform {} 10 + } 11 + } 12 + 13 + export {};
+12
src/app.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <link rel="icon" href="%sveltekit.assets%/favicon.png" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 + %sveltekit.head% 8 + </head> 9 + <body data-sveltekit-preload-data="hover"> 10 + <div style="display: contents">%sveltekit.body%</div> 11 + </body> 12 + </html>
+1
src/lib/index.ts
··· 1 + // place files you want to import through the `$lib` alias in this folder.
+6
src/routes/+layout.svelte
··· 1 + <script lang="ts"> 2 + import '../app.css'; 3 + let { children } = $props(); 4 + </script> 5 + 6 + {@render children()}
+2
src/routes/+page.svelte
··· 1 + <h1>Welcome to SvelteKit</h1> 2 + <p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
+18
svelte.config.js
··· 1 + import adapter from '@sveltejs/adapter-auto'; 2 + import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 3 + 4 + /** @type {import('@sveltejs/kit').Config} */ 5 + const config = { 6 + // Consult https://svelte.dev/docs/kit/integrations 7 + // for more information about preprocessors 8 + preprocess: vitePreprocess(), 9 + 10 + kit: { 11 + // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. 12 + // If your environment is not supported, or you settled on a specific environment, switch out the adapter. 13 + // See https://svelte.dev/docs/kit/adapters for more information about adapters. 14 + adapter: adapter() 15 + } 16 + }; 17 + 18 + export default config;
+19
tsconfig.json
··· 1 + { 2 + "extends": "./.svelte-kit/tsconfig.json", 3 + "compilerOptions": { 4 + "allowJs": true, 5 + "checkJs": true, 6 + "esModuleInterop": true, 7 + "forceConsistentCasingInFileNames": true, 8 + "resolveJsonModule": true, 9 + "skipLibCheck": true, 10 + "sourceMap": true, 11 + "strict": true, 12 + "moduleResolution": "bundler" 13 + } 14 + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias 15 + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files 16 + // 17 + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 18 + // from the referenced tsconfig.json - TypeScript does not merge them in 19 + }
+7
vite.config.ts
··· 1 + import tailwindcss from '@tailwindcss/vite'; 2 + import { sveltekit } from '@sveltejs/kit/vite'; 3 + import { defineConfig } from 'vite'; 4 + 5 + export default defineConfig({ 6 + plugins: [tailwindcss(), sveltekit()] 7 + });