diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8170d50..6c29514 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -6,62 +6,59 @@ on: workflow_dispatch: jobs: - env-prod: - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - environment: - name: production - url: https://pengu.lol - steps: - - run: echo >nul - - env-dev: - if: github.ref == 'refs/heads/dev' + deploy: runs-on: ubuntu-latest - environment: - name: development - url: https://beta.pengu.lol - steps: - - run: echo >nul - deploy: permissions: - id-token: write contents: read - runs-on: ubuntu-latest + deployments: write + + environment: + name: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} + url: ${{ github.ref == 'refs/heads/main' && 'https://pengu.lol' || 'https://pengu.dev' }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Set environment variables + - name: Resolve Pages project + env: + PROJECT: ${{ secrets.CLOUDFLARE_PROJECT_NAME }} run: | - if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then - echo "DENO_DEPLOY_PROJECT=pengu-docs" >> $GITHUB_ENV - elif [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then - echo "DENO_DEPLOY_PROJECT=pengu-docs-dev" >> $GITHUB_ENV + if [[ -z "$PROJECT" ]]; then + echo "::error::CLOUDFLARE_PROJECT_NAME secret is not set." + exit 1 fi + echo "CF_PAGES_PROJECT=$PROJECT" >> $GITHUB_ENV - - name: Install NodeJS - uses: actions/setup-node@v3 + - name: Setup pnpm + uses: pnpm/action-setup@v4 with: - node-version: 18.x + version: 9 - - name: Install Deno - uses: denoland/setup-deno@v2 + - name: Setup Node.js + uses: actions/setup-node@v4 with: - deno-version: v2.x - - - name: Install Deno deployctl - run: deno install -gArf jsr:@deno/deployctl + node-version: 20.x + cache: pnpm - name: Build project run: | - npm i -g pnpm pnpm install pnpm build - - name: Deploy to Deno Deploy - run: | - cd .vitepress - deployctl deploy --prod --project=$DENO_DEPLOY_PROJECT ./serve.ts --token ${{ secrets.DENO_DEPLOY_TOKEN }} + # Single Pages project, two domains routed by branch: + # main -> production deployment -> pengu.lol + # dev -> dev..pages.dev alias -> pengu.dev + # --branch is what picks between them, so it must always be passed. + # pengu.dev reaches the dev build via a proxied CNAME retargeted at the + # branch alias -- see docs/guide or the Cloudflare dashboard DNS tab. + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: >- + pages deploy .vitepress/dist + --project-name=${{ env.CF_PAGES_PROJECT }} + --branch=${{ github.ref_name }} diff --git a/.vitepress/components/CustomSwitchAppearance.vue b/.vitepress/components/CustomSwitchAppearance.vue new file mode 100644 index 0000000..5963d9a --- /dev/null +++ b/.vitepress/components/CustomSwitchAppearance.vue @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/.vitepress/components/Download.vue b/.vitepress/components/Download.vue new file mode 100644 index 0000000..65806c4 --- /dev/null +++ b/.vitepress/components/Download.vue @@ -0,0 +1,207 @@ + + + + + + + \ No newline at end of file diff --git a/.vitepress/components/Home.vue b/.vitepress/components/Home.vue new file mode 100644 index 0000000..24d22ce --- /dev/null +++ b/.vitepress/components/Home.vue @@ -0,0 +1,124 @@ + + + \ No newline at end of file diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 923bfcd..be4db13 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -1,47 +1,69 @@ -import { defineConfig } from 'vitepress' -import { join } from 'node:path' +import { defineConfig, type DefaultTheme } from 'vitepress' +import { join, resolve } from 'node:path' import pkg from '../package.json' import { execSync } from 'node:child_process' +import { sidebar } from './sidebar' + const gitBranch = execSync('git rev-parse --abbrev-ref HEAD').toString().trimEnd() -const isBeta = gitBranch !== 'main' +const isDev = gitBranch !== 'main' +const domain = isDev ? 'pengu.dev' : 'pengu.lol' + +const meta = { + title: 'Pengu Loader', + description: 'The ultimate JavaScript plugin loader, build your unmatched LoL Client.', + url: `https://${domain}/`, + image: `https://${domain}/banner.jpg`, +} // https://vitepress.dev/reference/site-config export default defineConfig({ - title: "Pengu Loader" + (isBeta ? ' Beta' : ''), - description: "Unleash the power of Customization from your League of Legends Client.", + title: meta.title, + description: meta.description, lang: 'en', - appearance: isBeta ? undefined : 'dark', + appearance: isDev ? undefined : 'dark', lastUpdated: true, cleanUrls: true, - srcDir: './docs', + srcDir: resolve(__dirname, '../docs'), vite: { - publicDir: join(__dirname, '../public') + publicDir: resolve(__dirname, '../public'), + resolve: { + alias: [ + { + find: '@components', + replacement: resolve(__dirname, 'components'), + }, + { + find: /^.*VPSwitchAppearance\.vue$/, + replacement: resolve(__dirname, 'components/CustomSwitchAppearance.vue'), + }, + ] + } }, head: [ ['meta', { name: 'theme-color', content: '#1e1e20' }], - ['link', { rel: 'icon', href: '/PenguLoader.png', type: 'image/png' }], + ['link', { rel: 'icon', href: '/icon.png', type: 'image/png' }], ['meta', { name: 'og:type', content: 'website' }], - ['meta', { name: 'og:url', content: 'https://pengu.lol/' }], - ['meta', { name: 'og:title', content: 'Pengu Loader' }], - ['meta', { name: 'og:description', content: 'Unleash the power of Customization from your League of Legends Client.' }], - ['meta', { name: 'og:image', content: 'https://pengu.lol/banner.jpg' }], + ['meta', { name: 'og:url', content: meta.url }], + ['meta', { name: 'og:title', content: meta.title }], + ['meta', { name: 'og:description', content: meta.description }], + ['meta', { name: 'og:image', content: meta.image }], ['meta', { name: 'twitter:card', content: 'summary_large_image' }], - ['meta', { name: 'twitter:url', content: 'https://pengu.lol/' }], - ['meta', { name: 'twitter:title', content: 'Pengu Loader' }], - ['meta', { name: 'twitter:description', content: 'Unleash the power of Customization from your League of Legends Client.' }], - ['meta', { name: 'twitter:image', content: 'https://pengu.lol/banner.jpg' }], + ['meta', { name: 'twitter:url', content: meta.url }], + ['meta', { name: 'twitter:title', content: meta.title }], + ['meta', { name: 'twitter:description', content: meta.description }], + ['meta', { name: 'twitter:image', content: meta.image }], ], themeConfig: { // https://vitepress.dev/reference/default-theme-config - logo: '/PenguLoader.png', + logo: `/icon.png`, nav: nav(), algolia: { @@ -66,76 +88,33 @@ export default defineConfig({ }, footer: { - message: 'Released under the WTF License.', + message: 'Released under the MIT License.', copyright: `Copyright © 2023-present Pengu Loader` }, }, }) -function nav() { +function nav(): DefaultTheme.NavItem[] { return [ { - text: 'Guide', + text: 'Download', + link: '/download', + activeMatch: '/download' + }, + { + text: 'Docs', link: '/guide/welcome', activeMatch: '/guide/' }, { - text: 'Runtime API', + text: 'API', link: '/runtime-api/', activeMatch: '/runtime-api/' }, - { - text: `v${pkg.version}` + (isBeta ? '-beta' : ''), - link: isBeta ? 'https://github.com/PenguLoader/PenguLoader/actions' - : `https://github.com/PenguLoader/PenguLoader/releases/` - } - ] -} - -function sidebar() { - return [ - { - text: 'Getting Started', - collapsed: false, - items: [ - { text: 'Welcome', link: '/guide/welcome' }, - { text: 'Installation', link: '/guide/installation' }, - { text: 'FAQs', link: '/guide/faqs' }, - ] - }, - { - text: 'Plugins', - collapsed: false, - items: [ - { text: 'JavaScript Plugin', link: '/guide/javascript-plugin' }, - { text: 'Module System', link: '/guide/module-system' }, - { text: 'CSS Theme', link: '/guide/css-theme' }, - { text: 'Asset Handling', link: '/guide/asset-handling' }, - { text: 'LCU Request', link: '/guide/lcu-request' }, - { text: 'Npm Compatibility', link: '/guide/npm-compatibility' }, - ] - }, - { - text: 'Runtime API', - collapsed: false, - items: [ - { text: 'Overview', link: '/runtime-api/' }, - { text: '[Pengu]', link: '/runtime-api/pengu' }, - { text: '[CommandBar]', link: '/runtime-api/command-bar' }, - { text: '[DataStore]', link: '/runtime-api/data-store' }, - { text: '[Effect]', link: '/runtime-api/effect' }, - { text: '[PluginFS]', link: '/runtime-api/plugin-fs' }, - { text: '[Toast]', link: '/runtime-api/toast' }, - { text: '[rcp] context.rcp', link: '/runtime-api/rcp' }, - { text: 'context.socket', link: '/runtime-api/socket' }, - ] - }, - { - text: 'Migrations', - collapsed: false, - items: [ - { text: 'Migration from v0.6', link: '/guide/migration-from-v0-6' }, - ] - } + // { + // text: `v${pkg.version}` + (isDev ? '-dev' : ''), + // link: isDev ? 'https://github.com/PenguLoader/PenguLoader/tree/dev' + // : `https://github.com/PenguLoader/PenguLoader/releases/tag/v${pkg.version}` + // } ] } diff --git a/.vitepress/lib/gh-utils.ts b/.vitepress/lib/gh-utils.ts new file mode 100644 index 0000000..2c96b86 --- /dev/null +++ b/.vitepress/lib/gh-utils.ts @@ -0,0 +1,135 @@ +import { archLabel, getAssetArch, Platform, type MacArch } from './utils' + +// NOTE: this module runs in the browser, so it must never carry a token -- +// anything passed here ends up verbatim in the published JS bundle. +// Unauthenticated GitHub API calls are rate limited per visitor IP (60/hour), +// which is plenty for a single "latest release" lookup. +const LATEST_RELEASE_URL = + 'https://api.github.com/repos/PenguLoader/PenguLoader/releases/latest' + +type RawAsset = { + name: string + size: number + browser_download_url: string +} + +type RawRelease = { + tag_name: string + name: string | null + published_at: string | null + assets: RawAsset[] +} + +export type AssetInfo = { + name: string + url: string + fileName: string + fileSize: string + arch?: MacArch +} + +export type Release = { + version: string + name: string + publishedAt: string + downloads: Partial> +} + +const dateFormat = new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: '2-digit', +}) + +const getReadableName = (rawName: string, arch?: MacArch): string => { + // asset names are mixed case on the releases page, match case-insensitively + const name = rawName.toLowerCase() + if (name.endsWith('.exe')) { + return 'Installer' + } + if (name.endsWith('.msi')) { + return 'MSI installer' + } + if (name.endsWith('.dmg')) { + return 'Installer' + } + if (arch) { + return archLabel(arch) + } + if (name.includes('portable') || /\.(7z|zip)$/.test(name)) { + return 'Portable' + } + + return '' +} + +const getPlatformTypByAssetName = (rawName: string): Platform => { + const name = rawName.toLowerCase() + // macOS first -- 'exe' is a loose substring that can appear anywhere + if (name.includes('macos') || name.includes('darwin') || name.endsWith('.dmg')) { + return Platform.MacOS + } + if (name.includes('windows') || name.includes('exe')) { + return Platform.Windows + } + + return Platform.Windows +} + +function getAssetInfo(asset: RawAsset): AssetInfo { + const fileSize = asset.size / 1024 / 1024 + const arch = getAssetArch(asset.name) + return { + url: asset.browser_download_url, + fileName: asset.name, + name: getReadableName(asset.name, arch), + fileSize: `${fileSize.toFixed(2)} MB`, + arch, + } +} + +export async function getRelease(): Promise { + try { + const response = await fetch(LATEST_RELEASE_URL, { + headers: { + accept: 'application/vnd.github+json', + 'x-github-api-version': '2022-11-28', + }, + }) + + if (!response.ok) { + // a 403/429 with no quota left means this visitor's IP hit the + // unauthenticated limit, not that the release is missing + if (response.headers.get('x-ratelimit-remaining') === '0') { + console.error('GitHub API rate limit reached for this IP') + } else { + console.error(`Failed to fetch release data: ${response.status}`) + } + return null + } + + const data: RawRelease = await response.json() + + if (!Array.isArray(data.assets) || data.published_at === null) { + console.error('Failed to fetch release data') + return null + } + + const downloads: Partial> = {} + for (const asset of data.assets) { + const platform = getPlatformTypByAssetName(asset.name) + const list = downloads[platform] ?? (downloads[platform] = []) + list.push(getAssetInfo(asset)) + } + + return { + version: data.tag_name, + name: data.name || data.tag_name, + publishedAt: dateFormat.format(new Date(data.published_at)), + downloads, + } + } catch (e) { + console.error('Failed to fetch release data', e) + return null + } +} diff --git a/.vitepress/lib/utils.ts b/.vitepress/lib/utils.ts new file mode 100644 index 0000000..6a139e8 --- /dev/null +++ b/.vitepress/lib/utils.ts @@ -0,0 +1,70 @@ + +export enum Platform { + Windows = 'Windows 10/11', + MacOS = 'macOS 12+', +} + +export type MacArch = 'arm64' | 'x64' + +export function getPlatform(ua: string): Platform { + ua = ua.toLowerCase() + // check mac first: some UA strings carry both tokens + if (ua.indexOf('mac') !== -1) { + return Platform.MacOS + } + if (ua.indexOf('windows') !== -1) { + return Platform.Windows + } + + return Platform.Windows +} + +export const archLabel = (arch: MacArch) => + arch === 'arm64' ? 'Apple Silicon' : 'Intel' + +/** + * Which macOS build to hand the visitor. + * + * Best effort by necessity: Safari and Firefox still report `Intel Mac OS X` + * on Apple Silicon, so the UA string alone can never answer this. We try the + * two signals that do differ, then guess. + */ +export async function detectMacArch(): Promise { + // 1. Chromium exposes the real architecture through UA Client Hints. + const uaData = (navigator as any).userAgentData + if (uaData?.getHighEntropyValues) { + try { + const { architecture } = await uaData.getHighEntropyValues(['architecture']) + if (architecture === 'arm') return 'arm64' + if (architecture === 'x86') return 'x64' + } catch { + // permission denied or hint unsupported, fall through + } + } + + // 2. The GPU renderer string still differs between the two. + try { + const gl = document.createElement('canvas').getContext('webgl') + if (gl) { + const ext = gl.getExtension('WEBGL_debug_renderer_info') + const renderer = String( + ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER) + ) + if (/apple\s*(m\d|gpu|silicon)/i.test(renderer)) return 'arm64' + if (/intel|radeon|amd|nvidia|geforce/i.test(renderer)) return 'x64' + } + } catch { + // canvas/webgl unavailable + } + + // 3. Apple stopped selling Intel Macs in 2023, so arm64 is the better bet. + // Both builds stay listed in the table either way. + return 'arm64' +} + +export function getAssetArch(fileName: string): MacArch | undefined { + const name = fileName.toLowerCase() + if (/arm64|aarch64|apple-?silicon/.test(name)) return 'arm64' + if (/x64|x86[-_]?64|amd64|intel/.test(name)) return 'x64' + return undefined +} diff --git a/.vitepress/sidebar.ts b/.vitepress/sidebar.ts new file mode 100644 index 0000000..0b3e74d --- /dev/null +++ b/.vitepress/sidebar.ts @@ -0,0 +1,59 @@ +import { type DefaultTheme } from 'vitepress' + +export function sidebar(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Introduction', + collapsed: false, + items: [ + { text: 'Welcome', link: '/guide/welcome' }, + { text: 'Installation', link: '/guide/installation' }, + { text: 'FAQs', link: '/guide/faqs' }, + { text: 'What\'s new in v1.2', link: '/guide/pengu-v1.2' }, + ] + }, + { + text: 'Plugins', + // collapsed: false, + items: [ + { text: 'JavaScript Plugin', link: '/guide/javascript-plugin' }, + { text: 'Module System', link: '/guide/module-system' }, + { text: 'CSS Theme', link: '/guide/css-theme' }, + { text: 'Asset Handling', link: '/guide/asset-handling' }, + { text: 'LCU Request', link: '/guide/lcu-request' }, + { text: 'NPM & TypeScript', link: '/guide/npm-typescript' }, + ] + }, + { + text: 'Runtime API', + // collapsed: false, + items: [ + { text: 'General', link: '/runtime-api/' }, + { text: 'window.Pengu', link: '/runtime-api/pengu' }, + { text: 'window.DataStore', link: '/runtime-api/data-store' }, + { text: 'window.Effect (Visual)', link: '/runtime-api/effect' }, + { text: 'window.CommandBar (UI)', link: '/runtime-api/command-bar' }, + { text: 'window.Toast (UI)', link: '/runtime-api/toast' }, + { text: 'window.Settings (UI)', link: '/runtime-api/settings' }, + { text: 'context.rcp', link: '/runtime-api/rcp' }, + { text: 'context.socket', link: '/runtime-api/socket' }, + { text: 'context.fs (PluginFS)', link: '/runtime-api/fs' }, + { + text: 'Modules', + // collapsed: false, + items: [ + { text: 'JSON', link: '/runtime-api/modules/json' }, + { text: 'Directory', link: '/runtime-api/modules/directory' }, + ] + }, + ] + }, + { + text: 'Migrations', + // collapsed: false, + items: [ + { text: 'Migration from v0.6', link: '/guide/migration-from-v0-6' }, + ] + } + ] +} \ No newline at end of file diff --git a/.vitepress/theme/Layout.vue b/.vitepress/theme/Layout.vue new file mode 100644 index 0000000..9930649 --- /dev/null +++ b/.vitepress/theme/Layout.vue @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file diff --git a/.vitepress/theme/analytics.ts b/.vitepress/theme/analytics.ts index 1ef29e3..20e2df7 100644 --- a/.vitepress/theme/analytics.ts +++ b/.vitepress/theme/analytics.ts @@ -1,33 +1,33 @@ declare global { interface Window { - dataLayer?: any[]; - gtag?: (...args: any[]) => void; + dataLayer?: any[] + gtag?: (...args: any[]) => void } } function mountGoogleAnalytics(id: string) { // avoid duplicated import if (window.dataLayer && window.gtag) { - return; + return } // insert gtag ` + + diff --git a/docs/guide/asset-handling.md b/docs/guide/asset-handling.md index f0cf245..428d99e 100644 --- a/docs/guide/asset-handling.md +++ b/docs/guide/asset-handling.md @@ -51,27 +51,6 @@ import this theme.css from your index.js */ ::: -### Common assets - -Since v0.5, we have provided access to local assets via the `//assets/` domain. - -Example: - -``` -loader/ - |__assets/ - |__your-image.png - |__your-background.mp4 - |... - |__plugins/ - |... -``` - -```html - - -``` - ## Remote assets ### GitHub file hosting diff --git a/docs/guide/faqs.md b/docs/guide/faqs.md index 5f4a357..281fec0 100644 --- a/docs/guide/faqs.md +++ b/docs/guide/faqs.md @@ -1,16 +1,30 @@ # FAQs

- +

## Can I get banned? -Pengu Loader is totally safe to use. +Pengu Loader itself is safe — it only restyles the League Client's interface and +never touches the game. Themes and cosmetic plugins give you no advantage over +anyone else, which is what the vast majority of people use it for. + +That said, it is a third-party tool that Riot Games does not endorse, so it sits +in a gray area, and nobody can honestly promise you zero risk. What actually +gets accounts banned isn't Pengu — it's what some plugins do with it. Automation +(auto-accept, auto-dodge, bots), scripting, exploiting Client or LCU bugs, or +anything giving you an unfair advantage is bannable no matter which tool it went +through. + +So: install plugins you trust, keep it cosmetic, and you're doing what Pengu was +built for. See the [Usage Policy](/policy) for the full picture. ## Does it affect the in-game? -No. +No. Pengu Loader only runs inside `LeagueClientUx.exe`, the process that draws +the Client interface. It never loads into the game process, so nothing it does +can reach a live match. ## Regions support? @@ -18,7 +32,8 @@ Pengu Loader works for all regions, including Tencent server. ## MacOS support? -Coming soon. +Yes, since v1.2. Separate builds are available for Apple Silicon and Intel Macs +on the [Download](/download) page. ## Reloading the Client causes high memory usage? @@ -51,8 +66,8 @@ your theme. ## Followed the instructions, but the plugin/theme does not work? -If you have been renamed some files, be sure this File Explorer option is -unchecked, then recheck your file names. +If you have renamed some files, make sure that this File Explorer option is unchecked, +and then check your file names again. ![](https://i.imgur.com/SUFr9Qk.png) diff --git a/docs/guide/javascript-plugin.md b/docs/guide/javascript-plugin.md index cd8b71f..371a119 100644 --- a/docs/guide/javascript-plugin.md +++ b/docs/guide/javascript-plugin.md @@ -58,19 +58,34 @@ Hello, League Client! -A plugin's entry point is an exported function in the plugin index that is called automatically by the loader. -The `init` entry should be called before League Client initializes its scripts. +A plugin's entry point is an exported function in the plugin index that is +called automatically by the loader. The `init` entry is called before League +Client initializes its scripts. ```js export function init(context) { // your code here } ``` -- See [`context.rcp`](../runtime-api/rcp) to use RiotClientPlugin hooks from this `context`. -- See [`context.socket`](../runtime-api/socket.md) to use built-in socket observation. -As of v1.1.0, you no longer need to put your load script in the `load` event of `window`. -Instead, you can put in the `load` entry, it will be called even after window is loaded. +The `context` gives you: + +- [`context.rcp`](../runtime-api/rcp) — RiotClientPlugin hooks. +- [`context.socket`](../runtime-api/socket) — built-in socket observation. +- `context.meta` — `{ name }`, your plugin's folder name. + +- [`context.fs`](../runtime-api/fs) — read/write access to your own plugin + folder. + +`meta` and `fs` are only present for **folder plugins** — see +[Plugin layouts](#plugin-layouts) below. + +`init` may be `async`, and the loader awaits it. That is how you delay the +Client's own startup until your setup is done — but keep it short, see +[Load timing](#load-timing). + +As of v1.1.0, you no longer need to register a `load` listener on `window` +yourself. Export a `load` entry instead and the loader wires it up for you. ```js export function load() { @@ -78,6 +93,50 @@ export function load() { } ``` +`load` runs once the Client's HTML has been parsed, which is where you should +touch the DOM. A `default` export is treated the same way if you don't export +`load`: + +```js +export default function () { + // same as `export function load()` +} +``` + +## Plugin layouts + +Pengu recognises three shapes inside the **plugins** folder: + +``` +plugins/ + |__quick-tweak.js <- single-file plugin + |__your-plugin/ + | |__index.js <- folder plugin + |__@author/ + |__their-plugin/ + |__index.js <- namespaced folder plugin +``` + +Single-file plugins work, but they get neither `context.meta` nor `context.fs` +— they have no folder of their own to scope those to. If your plugin needs to +store anything next to itself, give it a folder. + +Namespaced plugins (`@author/name/index.js`) are supported since v1.2, and are +the convention for anything you publish for others to install. + +## Load timing + +Every plugin's `init` is awaited before the Client's first RCP plugin is +released, so slow work in `init` delays Client startup for your users. + +Pengu caps the total wait at **15 seconds**. If your plugins collectively take +longer, the Client is released anyway and a warning appears in the console. +Plugins still finish loading in the background, but they may miss `preInit` / +`postInit` hooks for RCP plugins that already got past those phases. + +If a plugin throws while loading, the error is logged with the plugin name and +the remaining plugins carry on — one broken plugin does not take down the rest. + ## Plugin templates To get started with ease, we have already provided base plugins, check it out: diff --git a/docs/guide/lcu-request.md b/docs/guide/lcu-request.md index 73f006a..b5293f2 100644 --- a/docs/guide/lcu-request.md +++ b/docs/guide/lcu-request.md @@ -50,7 +50,7 @@ async function quitLobby() { // dont know why people call it 'dodge' When the WebSocket is ready, this link tag will appear: ```html - + ``` Getting its URI with a simple query. @@ -97,7 +97,8 @@ socket.send(JSON.stringify([6, ''])) ::: tip -Since v1.1.0, we have introduced [`context.socket`](../runtime-api/socket) to for easier socket observation. +Since v1.1.0, we have introduced [`context.socket`](../runtime-api/socket) to +for easier socket observation. ::: diff --git a/docs/guide/migration-from-v0-6.md b/docs/guide/migration-from-v0-6.md index ed5bcfd..4038c3f 100644 --- a/docs/guide/migration-from-v0-6.md +++ b/docs/guide/migration-from-v0-6.md @@ -1,5 +1,8 @@ # Migration from v0.6 +Pengu Loader v0.6 is known as **League Loader**, the old name of the project +before rebranding. + ## New plugin project structure @@ -145,5 +148,5 @@ In this case above, `import` becomes an async function like. You can also add a ### JSON and CSS modules -You should refer to the [Module System](./module-system) to handle -importing them. +You should refer to the [Module System](./module-system) to handle importing +them. diff --git a/docs/guide/module-system.md b/docs/guide/module-system.md index 93dc4e4..d8c708b 100644 --- a/docs/guide/module-system.md +++ b/docs/guide/module-system.md @@ -30,7 +30,7 @@ console.log(utils.greeting) // -> hello ```ts [utils.js] // export a simple object export default { - gretting: 'Hello' + gretting: 'Hello', } ``` @@ -127,7 +127,7 @@ In your CSS module, you can import plugin assets using relative path: ```css .some-div { background-image: url(./assets/image.png); - /* resolve to //plugins/your-plugin/assets/image.png */ + /* resolve to //plugins/your-plugin/assets/image.png */ } ``` diff --git a/docs/guide/npm-compatibility.md b/docs/guide/npm-compatibility.md deleted file mode 100644 index 174c9b3..0000000 --- a/docs/guide/npm-compatibility.md +++ /dev/null @@ -1,41 +0,0 @@ -# Npm Compatibility - -## Using NodeJS project - -We strongly recommend that you to use NodeJS project to build your plugins. - -With TypeScript or other languages that require transpilation, you need a build -tool to build them, Webpack, Rollup or Vite is the best choice. - -You can also use any front-end library to build custom UI, e.g. React, Preact, -Vue, Svelte, SolidJS, etc. With front-end tooling, its hot-reload/HMR will help -you to do faster. - -::: info - -Note that npm packages those are designed to run only in NodeJS cannot be used -to build plugins. - -::: - -::: tip - -With the build tool, the output of your bundled assets may have incorrect paths. -Please refer to the [Asset Handling](./asset-handling) to make correct -them. - -::: - -## Example plugins - -### Webpack 📦 - -- [douugdev/league-a-better-client](https://github.com/douugdev/league-a-better-client) - - A LCU utilities with HMR + ⚛ Preact + SASS + TypeScript - -### Vite ⚡ - -- [Pengu vite-theme](https://github.com/PenguLoader/PenguLoader/blob/main/plugins/vite-theme) - - A simple theme with HMR + SASS + TypeScript -- [Pengu @default](https://github.com/PenguLoader/PenguLoader/blob/main/plugins/@default) - - The default plugin with HMR + SolidJS + SASS + TypeScript diff --git a/docs/guide/npm-typescript.md b/docs/guide/npm-typescript.md new file mode 100644 index 0000000..9c3176a --- /dev/null +++ b/docs/guide/npm-typescript.md @@ -0,0 +1,112 @@ +# NPM & TypeScript + +## Using Node.js + +We strongly recommend that you to use Node.js project to build your plugins. + +With TypeScript or other languages that require transpilation, you need a build +tool to build them, Webpack, Rollup or Vite is the best choice. + +You can also use any front-end library to build custom UI, e.g. React, Preact, +Vue, Svelte, SolidJS, etc. With front-end tooling, its hot-reload/HMR will help +you to do faster. + +::: info + +Note that NPM packages those are designed to run only in NodeJS cannot be used +to build plugins. + +::: + +::: tip + +With the build tool, the output of your bundled assets may have incorrect paths. +Please refer to the [Asset Handling](./asset-handling) to make correct them. + +::: + +## Using TypeScript + + + +Pengu publishes its type definitions as **[`@pengujs/types`][pkg]**. Install it +as a dev dependency: + +::: code-group + +```sh [npm] +npm install --save-dev @pengujs/types +``` + +```sh [pnpm] +pnpm add -D @pengujs/types +``` + +```sh [yarn] +yarn add -D @pengujs/types +``` + +::: + +Then pull the global declarations in, either from a single source file: + +```ts +/// +``` + +Or once for the whole project, in `tsconfig.json`: + +```json +{ + "compilerOptions": { + "types": ["@pengujs/types"] + } +} +``` + +Every Pengu surface on `window` is now type-checked — +[`Pengu`](../runtime-api/pengu), [`os`](../runtime-api/#window-os), +[`DataStore`](../runtime-api/data-store), [`Toast`](../runtime-api/toast), +[`CommandBar`](../runtime-api/command-bar), [`Effect`](../runtime-api/effect) +and [`Settings`](../runtime-api/settings) — with no imports at the call site. + +### Typing your plugin entry + +The package also exports the plugin module types, so your entry points get +checked against what the loader actually passes: + +```ts +import type { PluginInitContext } from '@pengujs/types' + +export function init({ rcp, socket, meta, fs }: PluginInitContext) { + console.log('loading', meta?.name) +} + +export function load() { + Toast.success('Ready!') +} +``` + +`meta` and `fs` are optional in the type because single-file plugins don't +receive them — see [Plugin layouts](./javascript-plugin#plugin-layouts). + +### Writable JSON imports + +`$write` is added at runtime, so cast at the import site to surface it: + +```ts +import _config from './config.json' +import type { WritableJson } from '@pengujs/types' + +const config = _config as WritableJson + +config.theme = 'dark' +await config.$write(2) +``` + +[pkg]: https://www.npmjs.com/package/@pengujs/types + +## Example plugins + +- [balance-buff-viewer](https://github.com/nomi-san/balance-buff-viewer) - Shows + Aram balance buffs/nerfs in champ-select. Built with Vite and TypeScript. diff --git a/docs/guide/pengu-v1.2.md b/docs/guide/pengu-v1.2.md new file mode 100644 index 0000000..fcfa901 --- /dev/null +++ b/docs/guide/pengu-v1.2.md @@ -0,0 +1,99 @@ +# What's new in Pengu v1.2 + +## New Features + +### Settings API + +Declare a schema and Pengu renders a settings form for your plugin inside the +Client, with an optional hotkey to open it: + +```js +Settings.register({ + id: 'my-plugin', + name: 'My Plugin', + hotkey: 'Ctrl+Shift+S', + schema: { + enabled: { type: 'boolean', label: 'Enabled', default: true }, + }, + state: config, + onChange: () => config.$write(2), +}) +``` + +No more hand-rolled settings UI, and no more asking users to edit JSON by hand. +See [window.Settings](../runtime-api/settings). + +### Writable JSON modules + +`import config from './config.json'` now gives you a `$write` method to save +changes back to disk, with optional pretty-printing: + +```ts +config.theme = 'dark' +await config.$write(2) +``` + +Writes are atomic, and `$write` can only ever overwrite the file it was +imported from. See [JSON Module](../runtime-api/modules/json). + +### Directory imports + +Append `?dir` to an import path to get a handle on a folder — list its files, +build URLs for them, or open it in Explorer / Finder for your user: + +```js +import images from './images?dir' + +for (const name of await images.files()) { + document.body.append(Object.assign(new Image(), { src: images.urlFor(name) })) +} +``` + +See [Directory Module](../runtime-api/modules/directory). + +### PluginFS is back + +Folder plugins get `context.fs` again — `read`, `write`, `mkdir`, `stat`, `ls` +and `rm`, scoped to the plugin's own directory. Namespaced plugins +(`plugins/@author/my-plugin/`) are supported, and top-level single-file plugins +still don't receive it. See [PluginFS](../runtime-api/fs). + +## API Changes + +### PluginFS options objects + +The trailing boolean flags on `write` and `rm` are now options objects: + +```js +await context.fs.write('./log.txt', 'x', true) // [!code --] +await context.fs.write('./log.txt', 'x', { append: true }) // [!code ++] + +await context.fs.rm('./dir', true) // [!code --] +await context.fs.rm('./dir', { recursive: true }) // [!code ++] +``` + +### `context.fs.mkdir` is idempotent + +Creating a directory that already exists now resolves `true`. It used to +resolve `false`, which was indistinguishable from a real failure. + +### `context.fs` can't touch your `index.js` + +`write` returns `false` and `rm` returns `0` for your plugin's own entry point. +It's the only file Pengu auto-executes from your folder, so a write there would +let one bad dependency persist itself across restarts. + +### `Directory.exists()` returns a promise + +```js +if (images.exists()) {} // [!code --] +if (await images.exists()) {} // [!code ++] +``` + +It reads the filesystem on every call rather than caching at import time, which +matters now that `reveal()` can create the folder. + +### `Directory.reveal()` takes no arguments + +It always creates the folder if it's missing, so the `create` flag is gone. It +returns a promise that rejects on failure, instead of `void`. diff --git a/docs/guide/welcome.md b/docs/guide/welcome.md index 8578a6b..0e81690 100644 --- a/docs/guide/welcome.md +++ b/docs/guide/welcome.md @@ -3,7 +3,7 @@ ## What is Pengu Loader?

- +

**Pengu Loader** (formerly **League Loader**) is a **plugin loader** designed diff --git a/docs/index.md b/docs/index.md index a33e6b7..5758bc1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,42 +1,41 @@ --- layout: home - title: Pengu Loader titleTemplate: Pengu Loader - hero: - name: Pengu Loader - # text: Pengu Loader - tagline: Unleash the power of Customization from your League of Legends Client + name: Build your unmatched + text: LoL Client + tagline: Start customizing now! image: - src: /Pengu_Featherknight_144.jpg - alt: VitePress + src: /images/visual-acrylic.png + alt: Pengu Loader actions: - theme: brand + text: Download + link: /download + - theme: alt text: Get Started link: /guide/welcome - theme: alt - text: Join our Discord + text: Join Discord link: https://chat.pengu.lol - - theme: alt - text: View on GitHub - link: https://github.com/PenguLoader/PenguLoader - features: - icon: src: /features/javascript.png title: JavaScript-Powered - details: Build a more intelligent Client with JavaScript. It's great to be able to use your favorite front-end technology. + details: Build a more intelligent Client with modern JavaScript and flexible web stacks. + link: /guide/javascript-plugin + linkText: Create your first plugin - icon: src: /features/theme.png title: Personalized Look & Feel details: Customize the Client interface to your preferences and make it unique. + link: /guide/css-theme + linkText: Create your first theme - icon: src: /features/league-of-legends.png title: Inside the League - details: Designed to work seamlessly within the Client, helping you to access the LCU without restriction. - - icon: - src: /features/chrome-dev.png - title: Chrome DevTools - details: Inspect and edit anything on the Client just as you would in a web browser. + details: Designed to work seamlessly within the Client UX, for simplified API access and hooks. + link: /runtime-api/ + linkText: Check out API docs --- diff --git a/docs/policy.md b/docs/policy.md new file mode 100644 index 0000000..1d35afd --- /dev/null +++ b/docs/policy.md @@ -0,0 +1,113 @@ +--- +title: Usage Policy +editLink: false +--- + +# Usage Policy + +**The short version:** Pengu Loader itself is safe — it only restyles the League +Client's interface and never touches the game. But it is a third-party tool that +Riot Games does not endorse, so it sits in a gray area. What gets people banned +is not Pengu, it's what some people choose to build on top of it. + +## Where the gray area is + +The League Client is an embedded Chromium browser. Pengu Loader loads your +JavaScript and CSS into that interface, the same way a browser extension styles +a web page. + +That is not something Riot officially supports. There is no approval process for +Client modifications and no public list of what is or isn't allowed, so nobody — +including us — can promise you that using any third-party tool carries zero +risk. Anyone telling you a Client mod is "100% ban-proof" is guessing. + +What we can tell you is what Pengu actually does, so you can judge the risk +yourself. + +## What Pengu Loader does not do + +- **It never touches the game.** Pengu only runs inside `LeagueClientUx.exe`, + the process that draws the Client UI. The game process is never loaded into, + read from, or modified. Nothing Pengu does can reach a live match. +- **It does not read or write game memory.** +- **It does not automate gameplay** — no scripting, no input simulation, no + bots. +- **It does not give you information you couldn't already see** in the Client. +- **It does not touch your account credentials.** Pengu never sees your + username, password, or session tokens. + +## What will get you banned + +Pengu Loader is a platform. A plugin runs with full access to the Client's own +APIs, which means a plugin author can do things Riot will absolutely act on. +Using a plugin that does any of the following puts your account at risk, and +that risk is on you: + +- **Automation of any kind** — auto-accept queue is the common one, but also + auto-dodge, auto-ban/pick bots, or anything that plays for you. +- **Scripting or gameplay assistance**, in the Client or in game. +- **Exploiting bugs** in the Client or the LCU API, including anything that + grants content, currency, or ranked outcomes you didn't earn. +- **Spamming or abusing LCU endpoints**, such as mass-messaging, friend-request + floods, or lobby spam. +- **Boosting, account sharing, or evading restrictions** with the help of a + plugin. +- **Anything that gives you an unfair advantage** over other players. + +None of this becomes acceptable because it went through Pengu. Riot's +[Terms of Service](https://www.riotgames.com/en/terms-of-service) apply to your +account no matter what tool was involved. + +::: warning Install plugins you trust + +A plugin is ordinary JavaScript with full access to the Client. Treat one like +any other program you run: prefer plugins whose source you can read, be +suspicious of obfuscated code, and remember that a plugin promising an edge in +matchmaking is exactly the kind that gets accounts banned. + +::: + +## Themes and cosmetic plugins + +Purely visual work — CSS themes, custom backgrounds, layout tweaks, new UI +panels — is what Pengu Loader was built for, and it's what the overwhelming +majority of the community uses it for. It changes nothing another player can +see and gives you no advantage. + +## Privacy + +Pengu Loader collects nothing. There is no telemetry, no analytics, no crash +reporting, and no account is required. + +The application makes exactly one outbound network request of its own: a check +against the [public GitHub releases API][gh] to see whether a newer version +exists. It sends no personal data, and you can turn it off with the +**automatic update check** toggle in the Pengu hub. + +Anything else your Client talks to is either Riot's own services or a request +made by a plugin you installed. Plugins are not sandboxed from the network, so a +plugin can make its own requests — another reason to install ones you trust. + +[gh]: https://api.github.com/repos/PenguLoader/PenguLoader/releases/latest + +## No warranty + +Pengu Loader is free, open source, and provided as-is under the +[MIT License](https://github.com/PenguLoader/PenguLoader/blob/main/LICENSE). +There is no warranty. You install and use it at your own risk, and you are +responsible for what you and your plugins do with your account. + +If you aren't comfortable with that, don't install it — that's a completely +reasonable call. + +## Questions + +Ask in the [Discord server](https://chat.pengu.lol) or open an issue on +[GitHub](https://github.com/PenguLoader/PenguLoader). + +--- + +Pengu Loader isn't endorsed by Riot Games and doesn't reflect the views or +opinions of Riot Games or anyone officially involved in producing or managing +Riot Games properties. Riot Games, and all associated properties are trademarks +or registered trademarks of Riot Games, Inc. diff --git a/docs/runtime-api/command-bar.md b/docs/runtime-api/command-bar.md index b0eae30..30733a8 100644 --- a/docs/runtime-api/command-bar.md +++ b/docs/runtime-api/command-bar.md @@ -1,8 +1,7 @@ # CommandBar -Since v1.1.0, we bring to you a new Command Bar -that can provide access to app-level commands -and can be used with any navigation pattern. +Since v1.1.0, we bring to you a new Command Bar that can provide access to +app-level commands and can be used with any navigation pattern. Let's press `Ctrl + K` to open the Command Bar. @@ -27,7 +26,8 @@ To add your custom actions, please use the APIs below. function addAction(action: Action): void ``` -Add a new action item to the Command Bar. It will automatically update even when showing. +Add a new action item to the Command Bar. It will automatically update even when +showing. #### Params @@ -35,17 +35,44 @@ Add a new action item to the Command Bar. It will automatically update even when ```ts interface Action { - id?: string // (optional) an unique idetifier for the action - name: string // action's name - legend?: string // (optional) action's note/legend or shortcut key - tags?: string[] // (optional) tags or keywords to search - icon?: string // (optional) HTML tag in string - group?: string // (optional) group name - hidden?: boolean // (optional) hide the action, except for search results - perform?: (id?: string) => any // called when the action is executed + id?: string // (optional) a unique identifier for the action + name: string | (() => string) // action's name + legend?: string | (() => string) // (optional) action's note/legend or shortcut key + tags?: string[] // (optional) tags or keywords to search + icon?: string // (optional) HTML tag in string + group?: string | (() => string) // (optional) group name + hidden?: boolean // (optional) hide the action, except for search results + perform?: (id?: string) => unknown // called when the action is executed } ``` +`name`, `legend` and `group` accept a **function** as well as a string. The +function is called each time the bar renders, which is what you want for labels +that change — a toggle whose name flips between "Enable X" and "Disable X", or +text that follows the Client's language. + +An action with no `group` is filed under `uncategorized`. + +An action that isn't an object, or has no `name`, is rejected with a warning in +the DevTools console. + +Example: + +```js +let enabled = false + +CommandBar.addAction({ + id: 'my-plugin/toggle', + name: () => (enabled ? 'Disable my plugin' : 'Enable my plugin'), + group: 'My Plugin', + tags: ['toggle'], + perform: () => { + enabled = !enabled + CommandBar.update() + }, +}) +``` + ## CommandBar.show @@ -66,5 +93,5 @@ Show the Command Bar programmatically if it was hidden. function update(): void ``` -Manually trigger the Command Bar to update its items. -Only use this function if your added actions are not updating. \ No newline at end of file +Manually trigger the Command Bar to update its items. Only use this function if +your added actions are not updating. diff --git a/docs/runtime-api/data-store.md b/docs/runtime-api/data-store.md index c87b15d..d7055f7 100644 --- a/docs/runtime-api/data-store.md +++ b/docs/runtime-api/data-store.md @@ -3,24 +3,44 @@ League Client does not store user data on disk, similar to incognito mode in web browsers. This namespace helps you to store user data on disk. -## DataStore.set(key, value) +The whole store is read from disk **before any plugin runs**, and kept in memory +for the rest of the session. Reads (`get`, `has`) are therefore synchronous and +safe to call from your plugin's `init`. Writes update memory immediately and +commit to disk on a short debounce, so a burst of `set` calls (a settings slider, +say) collapses into a single write. + +## DataStore.set() -Call this function to store your data with a given key. +```ts +function set(key: string, value: unknown): boolean +``` + +Stores data associated with the specified key. + +#### Parameters + +- `key` (string) The key under which the data will be stored. Keys must be unique across + all plugins to avoid conflicts. + +- `value` (unknown) The value to store. Supported types include: + - Primitive types: string, number, boolean, null + - Collections: arrays, objects -Parameters: +All data is serialized into JSON format, so non-serializable types such as +functions and runtime objects will be ignored. -- `key` (required) Keys should be string or number. -- `value` (required) Value may be string, number, boolean, null or collection - like array and object. Actually, it will be stored as JSON format, so any - value like function and runtime object are ignored. +#### Returns -Returns: -- A boolean value that indicates your key is valid and the data is stored successfully. +`true` if the value was accepted, `false` if `key` was not a string. -Example: +The return value is **not** a write confirmation — it means "stored in memory, +and it will reach disk shortly". Use [`flush()`](#datastore-flush) if you need +to know the data is durable. + +#### Example ```js let my_num = 10 @@ -29,23 +49,46 @@ DataStore.set('my_num', my_num) DataStore.set('my_str', my_str) ``` -::: tip Unique keys +#### Remarks + +To avoid data conflicts, use unique and descriptive key names, preferably +prefixed with your plugin’s identifier. For example, use +`plugin-name/user-settings` instead of generic names like `settings` or `data`. -You should use unique names for keys, do not use common names, e.g -`access_token`, `is_logged`, etc. Other plugins can override your data, you can -add prefix to your keys. +For multiple data entries such as config or user settings, you should store them +in an object. -::: +```ts +let config = { a: 10, b: 'hello' } +DataStore.set('my-config', config) +``` -## DataStore.get(key, fallback?) +## DataStore.get() -Retrieve your stored data with a given key. If the key does not exist, it will -return `undefined`. +```ts +function get(key: string, fallback?: T): T | undefined +``` + +Retrieves stored data by key. If the key does not exist, the function will +return undefined or an optional fallback value. -Example: +This is a synchronous read against the in-memory copy, so it is safe to call +from your plugin's `init`. + +#### Parameters + +- `key` (string) The key associated with the data. + +- `fallback` (T) (optional) A default value to return if the key does not exist. + +#### Returns + +The stored data, or the fallback value if the key is missing. + +#### Example ```js console.log(DataStore.get('my_str')) @@ -61,30 +104,82 @@ console.log(DataStore.get('key-does-not-exist', 1000)) // 1000 ``` -## DataStore.has(key) +## DataStore.has() -This function returns a boolean indicating whether data with the specified key -exists or not. +```ts +function has(key: string): boolean +``` + +Checks if a specific key exists in the storage. + +#### Parameters + +- `key` (string) The key to check. + +#### Returns + +A boolean value indicating whether the key exists. + +#### Example ```js console.log(DataStore.has('my_num')) console.log(DataStore.has('key-does-not-exist')) ``` -## DataStore.remove(key) +## DataStore.remove() -This function removes the specified data from storage by key, returns true if -the existing key-value pair has been removed. +```ts +function remove(key: string): boolean +``` + +Removes a key-value pair from storage. + +#### Parameters + +- `key` (string) The key of the data to remove. -Example: +#### Returns + +- `true` if the key was found and removed. +- `false` if the key does not exist. + +Like `set`, the removal applies to memory immediately and is committed to disk +on the same debounce. + +#### Example ```js DataStore.remove('some-key') DataStore.has('some-key') // -> false -``` \ No newline at end of file +``` + +## DataStore.flush() + + + + +```ts +function flush(): Promise +``` + +Writes any pending changes out immediately and resolves once they are durable +on disk. + +Most plugins never need this — the debounced commit already handles normal use. +Reach for it when you are about to do something that could end the session +before the debounce fires, such as calling `restartClient()`. + +#### Example + +```js +DataStore.set('my-config', config) +await DataStore.flush() +window.restartClient() +``` diff --git a/docs/runtime-api/effect.md b/docs/runtime-api/effect.md index 3cd61cc..cf83144 100644 --- a/docs/runtime-api/effect.md +++ b/docs/runtime-api/effect.md @@ -1,110 +1,219 @@ -# Effect +# `window.Effect` -This namespace supports changing window transparency/translucent effect. +This namespace object allows you to change the visual effect behind the Client +window. -
- -![](https://user-images.githubusercontent.com/38210249/216951830-b3bb3ce3-7a5f-4e60-8a67-33d0bce799cf.png) +## Visual Effects -## Effect.current +### `transparent` - - +

+ +

-A read-only property that returns the currently applied effect or `null` if -no effect has been applied. +Transparent window background, you can see other windows and desktop background +under the window. -Available effects: `mica`, `acrylic`, `unified` and `blurbehind`. +> Available on Windows 7+, macOS 10.14+ -Example: +### `blurbehind` -```js -console.log(Effect.current) -// mica -``` +

+ +

-## Effect.apply(name, options?) +Blurbehind is also known as **aero glass** effect, it looks like Windows Vista & +Windows 7 glossy blur effect. - - +> Available on Windows 7+, macOS 10.14+ -A function that takes the name of the desired effect name and an optional -object.
It returns a boolean indicating whether the effect was successfully -applied or not. +### `acrylic` -Parameters: +

+ +

-- `name` [required] These effect names above to be applied, in string. +Acrylic is a type of brush that creates a translucent texture. You can apply +acrylic to app surfaces to add depth and help establish a visual hierarchy. +Works only on Windows 10 version 1803 or higher. -- `options` [optional] Additional options for the effect, `acrylic`, `unified` - and `blurbehind` could have tint color, but `mica` will ignore this options. +> Available on Windows 10 1803+, macOS 10.14+ -This function returns `false` if the effect could not be applied, see the -[System compatibility](#system-compatibility) below. +### `unified` -Example: +Unified is a mix of Acrylic and Blurbehind. It is available on Windows 11, but +you can use on Windows 10 with no difference from Acrylic. -```js -// enable acrylic on Windows 10 -Effect.apply('acrylic') +> Available on Windows 11, macOS 10.14+ -// with a tint color -Effect.apply('unified', { color: '#4446' }) +### `mica` -// mica on windows 11, no options needed -Effect.apply('mica') -``` +Mica is an opaque, dynamic material that incorporates theme and desktop +wallpaper to paint the background of long-lived windows. Works only on Windows +11 or greater. -::: info +> Available on Windows 11, macOS 10.14+ -Tint colors must be in CSS hex color format, e.g. #RGB, #RGBA, #RRGGBB, -#RRGGBBAA. +[Mica Alt](https://learn.microsoft.com/en-us/windows/apps/design/style/mica#app-layering-with-mica-alt) +or mica with material is introduced in Windows 11 build 22523. -To see transparency effect correctly, you should remove all lowest backgrounds. +- `none` +- `auto` +- `mica` +- `acrylic` Acrylic is a type of brush that creates a translucent texture. You + can apply acrylic to app surfaces to add depth and help establish a visual + hierarchy. +- `tabbed` Tabbed is a Mica like material that incorporates theme and desktop + wallpaper, but is more sensitive to desktop wallpaper color. -::: +### `vibrancy` -![](https://user-images.githubusercontent.com/38210249/216951865-bb9c6676-58ec-4c81-ad96-67e94e91ac22.png) +Vibrancy is a subtle blending of foreground and background colors to increase +the contrast and make the foreground content stand out visually. -## Effect.clear() +> Available on macOS 10.14+ - - +Vibrancy works with material like Mica on Windows 11, here is the list based on +[NSVisualEffectMaterial](https://developer.apple.com/documentation/appkit/nsvisualeffectmaterial): -A function that clears any currently applied effect, then the Client background -will be black.
Using `Effect.current` after clearing will give you -`undefined`. - -Example: - -```js -// just clear applied effect, even if nothing applied -Effect.clear() -``` +- `Titlebar` The material for a window's titlebar. +- `Selection` The material for text selection. +- `Menu` The material for menus. +- `Popover` The material for the background of popover windows. +- `Sidebar` The material for the background of window sidebars. +- `HeaderView` The material for in-line header or footer views. +- `Sheet` The material for the background of sheet windows. +- `WindowBackground` The material for the background of opaque windows. +- `HudWindow` The material for the background of heads-up display (HUD) windows. +- `FullScreenUI` The material for the background of a full-screen modal + interface. +- `Tooltip` The material for the background of a tool tip. +- `ContentBackground` The material for the background of opaque content. +- `UnderWindowBackground` The material to show under a window's background. +- `UnderPageBackground` The material for the area behind the pages of a + document. ## System compatibility +### Windows + - On Windows 7, only the `blurbehind` is supported. -- On Windows 10, requires build 1703 or higher to use `acrylic`. +- On Windows 10, requires version 1803 or higher to use `acrylic`. - `mica` and `unified` are only supported on Windows 11, but `unified` can be enabled on Windows 10 without different from `acrylic`. ::: warning -On Windows 10 build **1903** (19H1) and higher, enabling `acrylic/mica/unified` with -**Transparency effects** (in Personalize -> Color settings) will cause lag when -moving the Client window. +On Windows 10 build **1903** (19H1) and higher, enabling `acrylic/mica/unified` +with **Transparency effects** (in Personalize -> Color settings) will cause lag +when moving the Client window. ::: -## Listening for changes +### macOS + +On macOS, we only have the `vibrancy` effect, so those Windows-based effects +will be treated as `vibrancy` with the appropriate material, and the effect will +appear when the Client window is active. + +- `transparent` => `UnderWindowBackground` material +- `blurbehind` => `HudWindow` material +- `acrylic` => `FullScreenUI` material +- `unified` => `Popover` material +- `mica` => `HeaderView` material + +
+ +## API functions + +### `Effect.apply()` + +```ts +function apply( + name: 'transparent' | 'blurbehind' | 'acrylic' | 'unified', + options?: { color: string }, +): void +function apply( + name: 'mica', + options?: { material?: 'auto' | 'none' | 'mica' | 'acrylic' | 'tabbed' }, +): void +function apply( + name: 'vibrancy', + options: { material: string; alwaysOn?: boolean }, +): void +``` + +Apply window visual effect with the name of the desired effect. + +#### Parameters + +- `name` These effect names above to be applied, in string. + +- `options` [optional] Additional options for the effect. + +An unknown effect name, or an unknown `mica` / `vibrancy` material, is ignored +with a warning in the DevTools console rather than throwing. + +#### Remarks + +- `transparent`, `blurbehind`, `acrylic` and `unified` require options object + with a `color` field is CSS hex color. + + ```js + // enable transparent effect with accent color is #0008 + Effect.apply('transparent', { color: '#0008' }) + ``` + +- The `mica` might require the options with material. + + ```js + // enable pure mica effect (Windows 11) + Effect.apply('mica') + + // enable mica alt effect with acrylic material (Windows 11 build 22523+) + Effect.apply('mica', { material: 'acrylic' }) + ``` + +- The `vibrancy` effect is like the `mica` but also has an option `alwaysOn` to + indicate that the effect should always appear even the window is inactive, it + is `false` by default. + + ```js + // enable vibrancy effect with HudWindow material (macOS) + Effect.apply('vibrancy', { material: 'HudWindow' }) + // always on + Effect.apply('vibrancy', { material: 'HudWindow', alwaysOn: true }) + ``` + +::: info + +Accent color must be in CSS hex color format. + +- #RGB, #RRGGBB (red-green-blue) +- #RGBA, #RRGGBBAA (red-green-blue-alpha) + +To see transparency effect correctly, you should remove all opaque backgrounds. + +::: + +### Effect.clear() + +```ts +function clear() +``` + +Call this function to clear the applied window visual effect. + +### `Effect.setTheme()` + +```ts +function setTheme(theme: 'light' | 'dark') +``` -Add a listener which will be triggered when effect changed. +Change the default theme of the Client window. There are two options `light` or +`dark`, the initial value is set by system settings. -```js -window.addEventListener('effect-changed', (event) => { - console.log(event.detail) -}) -``` \ No newline at end of file +Since v1.2.0, window theme is set to `dark` by default, and won't be affected by +system settings. You can call this function to turn on `light` theme. diff --git a/docs/runtime-api/fs.md b/docs/runtime-api/fs.md new file mode 100644 index 0000000..478ebb7 --- /dev/null +++ b/docs/runtime-api/fs.md @@ -0,0 +1,329 @@ +# PluginFS + +This namespace helps you to gain access to **plugin's own directory** and +perform some basic file system operations. + +```js +export function init({ meta, fs }) { + if (!fs) return // top-level plugin, see below + await fs.write('state.json', JSON.stringify({ ok: true })) +} +``` + +::: tip + +**Top-level** plugins don't have this namespace since they don't own a +directory. + +A folder plugin — `plugins/my-plugin/index.js`, or +`plugins/@author/my-plugin/index.js` — gets an `fs` scoped to that folder. A +single-file `plugins/my-plugin.js` gets nothing, because the only folder it +could be scoped to is the plugins root, which holds everyone else's files. If +you need a filesystem, ship your plugin as a folder. + +::: + +::: warning + +All paths passed into this API are **relative to the root** directory of your +plugin. + +::: + +::: danger + +APIs under this namespace return a **Promise of `undefined`** (or `false` / `0`, +depending on the method) when the path is rejected. They don't throw, so check +the return value. + +::: + +## What counts as a legal path + +Everything is resolved inside your plugin folder, and there is no way to address +anything outside it: + +- Absolute paths are rejected. +- `..` is rejected as a path component — not stripped, rejected. +- Symlinks are rejected at **every** level of the path, not just the last one. +- The final resolved path is re-checked against your plugin root before anything + runs. + +Also rejected: empty path components, components longer than 255 bytes, paths +longer than 4096 bytes, `:` and NUL anywhere in a component, and — on Windows — +reserved device names (`CON`, `PRN`, `AUX`, `NUL`, `COM1`–`COM9`, `LPT1`–`LPT9`) +plus names ending in a dot or a space. + +Reads and writes are capped at **16 MB**. + +## Security model + +`fs` is a **capability object**: whoever holds it can use it. There's no further +check on who's calling. + +That's different from [`$write`](./modules/json) and +[`?dir`](./modules/directory), which figure out their target from the calling +script and can't be handed to anyone. + +::: danger + +Passing your `fs` to imported third-party code gives that code your plugin's +folder, including the ability to leave files behind that survive restarts. Treat +it like an API key. + +::: + +What limits the damage is the scope: a leaked `fs` reaches one plugin's folder, +never another plugin's, and never your `index.js`. + +## context.fs.read(path) + + + + +Read a file in text mode. + +### Params + +- `path` - The path of the file you want to access with respect to the plugin + root directory. + +### Return value + +A `Promise` of content `string` on success. + +A `Promise` of `undefined` on failure — missing, not a file, unreadable, or +larger than 16 MB. These aren't distinguished. + +### Example + +```javascript +context.fs.read('./index.js').then((content) => { + console.log(content) +}) + +const content = await context.fs.read('./README.md') +``` + +::: tip + +Text only. There's no byte-array API, so reading a binary file gives you +mojibake rather than an error. + +::: + +## context.fs.write(path,content,options?) + + + + +Write a file in text mode. + +### Params + +- `path` - The path of the file you want to access with respect to the plugin + root directory. +- `content` - The content `string` you want to write into the file. +- `options.append` - Append to file if set to `true` or overwrite file if + `false`. This is `false` by default. + +::: warning + +`since v1.2.0` the third argument is an options object. It used to be a bare +`enableAppendMode` boolean. + +```javascript +await context.fs.write('./log.txt', 'x', true) // [!code --] +await context.fs.write('./log.txt', 'x', { append: true }) // [!code ++] +``` + +::: + +### Return value + +A `Promise` of `boolean` indicating success or failure. + +### Example + +```javascript +// Create test.txt and write "Hello" into it +context.fs.write('./test.txt', 'Hello').then((result) => { + if (result) { + // success + } else { + // fail + } +}) + +// Appending " World!" to it +const result = await context.fs.write('./test.txt', ' World!', { append: true }) +``` + +::: tip + +This API can create a file but can't create a file under a non-existing +directory. Call `context.fs.mkdir` first. + +::: + +::: danger + +**Your plugin's own `index.js` can't be written or removed.** `write` returns +`false` and `rm` returns `0` for it. + +It's the only file in your folder that Pengu executes on its own at launch, so +allowing writes there would let a single bad dependency install itself +permanently. Every other file in your folder is writable, and nothing else is +auto-loaded. + +::: + +### Writes are atomic + +Overwriting goes through a temporary file in the same directory, then a rename. +A crash mid-write leaves the previous contents intact instead of a truncated +file. Appending writes directly. + +## context.fs.mkdir(path) + + + + +Create directories recursively. + +### Params + +`path` - The directory path you want to create with respect to the plugin root +directory. + +### Return Value + +A `Promise` of `boolean` indicating success or failure. + +::: warning + +`since v1.2.0` this is idempotent — a directory that already exists counts as +success. It used to return `false` in that case. + +::: + +### Example + +```javascript +const bMkdir0 = await context.fs.mkdir('utils') +const bMkdir1 = await context.fs.mkdir('/a/b') +const bMkdir2 = await context.fs.mkdir('/a\\c') +// true — already exists is not a failure +const bMkdir3 = await context.fs.mkdir('a\\b/') +``` + +## context.fs.stat(path) + + + + +Get status of a file. + +### Params + +- `path` - The file path with respect to the plugin root directory. Omit it to + stat your plugin root. + +### Return value + +A `Promise` of `FileStat` on success. A `Promise` of `undefined` on failure. + +```typescript +interface FileStat { + fileName: string + + // 0 if isDir is true + length: number + isDir: boolean + isFile: boolean +} +``` + +### Example + +```javascript +const stat1 = await context.fs.stat('a/b') +if (stat1) { + console.log("it's a directory") +} +const stat2 = await context.fs.stat('a/random.js') +``` + +## context.fs.ls(path) + + + + +List files and directories under given path. + +### Params + +- `path` - The directory path with respect to the plugin root directory. Omit it + to list your plugin root. + +### Return value + +A `Promise` of `string[]` of file name strings on success, sorted +alphabetically. Symlinked entries are skipped rather than listed. + +A `Promise` of `undefined` on failure. + +## context.fs.rm(path,options?) + + + + +::: danger + +You should know what you are doing when using this. + +::: + +Remove file/directories. + +Just like `rm` command in Unix-like systems. + +### Params + +- `path` - The file/directory path with respect to the plugin root directory. +- `options.recursive` - Delete all files/directories under the given path + recursively. This is `false` by default. + +::: warning + +`since v1.2.0` the second argument is an options object. It used to be a bare +`recursively` boolean. + +```javascript +await context.fs.rm('./dir', true) // [!code --] +await context.fs.rm('./dir', { recursive: true }) // [!code ++] +``` + +::: + +### Return value + +A `Promise` of `number` showing how many files and directories is deleted. + +Your plugin root itself and your `index.js` are refused, and return `0`. + +### Example + +You can only delete a non-empty directory with `recursive` set to `true` + +```javascript +// 1 +const bRm1 = await context.fs.rm('./empty-dir') +// 1 +const bRm2 = await context.fs.rm('./random-file-under-plugin-root') + +// bRm3 == 0 because it's not empty +const bRm3 = await context.fs.rm('./non-empty-dir') +// bRm4 >= 1 with recursive set to true +const bRm4 = await context.fs.rm('./non-empty-dir', { recursive: true }) +``` diff --git a/docs/runtime-api/index.md b/docs/runtime-api/index.md index 8b50fd6..88140fb 100644 --- a/docs/runtime-api/index.md +++ b/docs/runtime-api/index.md @@ -3,7 +3,7 @@ These APIs are designed to use inside League Client with Pengu Loader plugin runtime. -## window.openDevTools(remote?) +## window.openDevTools() @@ -13,22 +13,8 @@ Call this function to open the built-in Chrome DevTools window. Example: ```js -window.openDevTools() // built-in DevTools -window.openDevTools(true) // remote DevTools -``` - -## window.openAssetsFolder() - - - - - -Call this function to open the assets folder in new File Explorer window. - -Example: - -```js -window.openAssetsFolder() +// open the DevTools +window.openDevTools() ``` ## window.openPluginsFolder(path?) @@ -44,7 +30,7 @@ Example: ```js window.openPluginsFolder() -window.openPluginsFolder("/plugin-demo/config") +window.openPluginsFolder('/plugin-demo/config') ``` ## window.reloadClient() @@ -78,33 +64,50 @@ window.restartClient() -Call this function get the current script path. +```ts +function getScriptPath(): string | undefined +``` + +Returns the URL of the script that called it, or `undefined` if it could not be +determined. + +It works by reading the current stack trace, so call it **directly from your own +script**. Calling it from inside a callback that Pengu or the Client invokes may +return a different script's URL, or nothing at all. Example: ```js +console.log(window.getScriptPath()) // https://plugins/your-plugin/index.js -window.getScriptPath() ``` -## window.__llver +## window.os + + + - - - +A read-only object describing the operating system the Client is running on. -This property returns the current version of Pengu Loader. +```ts +interface OsGlobal { + name: 'win' | 'mac' + version: string + build: string +} +``` Example: ```js -console.log(window.__llver) // 0.6.0 -console.log(`You are using Pengu Loader v${window.__llver}`) -``` +console.log(window.os) +// { name: 'win', version: '10.0', build: '19045' } -::: tip - -Since v1.1.0, this property has been deprecated. -Please use `Pengu.version` instead. +if (os.name === 'mac') { + // macOS-only code path +} +``` -::: \ No newline at end of file +For a simple platform check, [`Pengu.isMac`](./pengu#pengu-ismac) is shorter. +Use `os.version` / `os.build` when an effect or API you rely on needs a minimum +OS build — see [Effect compatibility](./effect#system-compatibility). diff --git a/docs/runtime-api/modules/directory.md b/docs/runtime-api/modules/directory.md new file mode 100644 index 0000000..3c8e992 --- /dev/null +++ b/docs/runtime-api/modules/directory.md @@ -0,0 +1,180 @@ +# Directory Module + +Pengu runtime allows you to access plugins' folder using the `import` statement. + +## Importing a directory (folder) + +`since v1.2.0` + +You can import a directory by appending `?dir` to the import path. The result is +an instance of a built-in **Directory** class, which provides various methods to +interact with the folder. + +```js +import images from './images?dir' +``` + +The folder doesn't have to exist yet. `?dir` resolves as long as the path is +valid, so you can import a folder and let `reveal()` create it the first time +your user asks for it. + +### Rules + +- **Relative Paths Only**: Import paths must be relative. +- **No Dynamic Imports**: Using dynamic imports with `?dir` is unsupported. +- **Local Only**: Directory imports from remote URLs are not allowed. + +These aren't style rules — together they're what keeps the plugins folder out of +reach of remote scripts. A relative import resolves against the URL of the file +doing the importing, so `./images?dir` inside your plugin resolves to +`https://plugins/your-plugin/images`, while the same line inside a script loaded +from `https://example.com/` resolves against *that* origin and never reaches +Pengu. There's no constructor and no way to build a Directory from a string at +runtime. + +::: warning + +A Directory is scoped to the **plugins folder**, not to your plugin. Any plugin +can reach any folder under `plugins/`. Don't treat it as a privacy boundary +between plugins — if you need one, folder plugins get a properly scoped +[PluginFS](../fs). + +::: + +
+ +See the sections below to use the instance properties and methods. + +## `Directory.url` + +```ts +const url: string +``` + +A read-only property that returns the URL to the directory, without a trailing +slash. + +For example, your plugin name is `your-plugin` and the code is executed in the +`index.js`. + +```ts +// plugin index.js +import images from './images?dir' + +console.log(images.url) +// output: https://plugins/your-plugin/images +``` + +To build the URL of a file *inside* the folder, use `urlFor()` below rather than +joining strings yourself. + +## `Directory.exists()` + +```ts +function exists(): Promise +``` + +Indicates whether the directory exists or not. The filesystem is checked on +every call, so the answer is always current. + +```js +import images from './images?dir' + +if (!(await images.exists())) { + console.log('no images folder yet') +} +``` + +## `Directory.files()` + +```ts +function files(): Promise +``` + +Lists all files in the directory, not including folders and files in subfolders. +The method returns a promise with array of file names, sorted, so your UI +renders in a stable order. + +```js +import images from './images?dir' + +for (let file of await images.files()) { + console.log('image: %s', file) +} +``` + +A directory that doesn't exist resolves to an empty array — that's the normal +state before your user has added anything, not an error. A directory that exists +but can't be read rejects, so a real permission problem doesn't quietly look +like an empty folder. + +## `Directory.urlFor()` + +```ts +function urlFor(name: string): string +``` + +Returns the URL of a file inside the directory, with the name properly encoded. + +```js +import images from './images?dir' + +for (const file of await images.files()) { + const img = document.createElement('img') + img.src = images.urlFor(file) + document.body.appendChild(img) +} +``` + +::: warning + +Don't join `url` and a file name yourself. `url` has no trailing slash, and raw +file names aren't URL-safe — a file called `hero#2.png` would be cut off at the +`#`, and names containing `%` or `?` break in other ways. `urlFor()` handles all +of it. + +::: + +`name` must be a plain file name. Path separators and `..` throw a `TypeError`, +since this method reaches into the folder and never out of it. + +## `Directory.reveal()` + +```ts +function reveal(): Promise +``` + +Call this method to open the directory in the system's file explorer, such as +**Explorer** on Windows or **Finder** on macOS. If the directory doesn't exist, +it's created first, along with any missing parent folders. + +That's useful when user needs to add files to the folder, just clicks a button +and the folder appears. + +```js +import images from './images?dir' + +document.querySelector('#browse').onclick = () => images.reveal() +``` + +The promise rejects if the folder couldn't be created or opened. To open only a +folder that already exists, check first: + +```js +if (await images.exists()) { + await images.reveal() +} +``` + +## What Directory doesn't do + +These are deliberate omissions, not oversights: + +- **No sub-folder listing.** There's no `dirs()`, because a Directory can't be + built from a string — the names would be useless. A sub-folder you know about + is still reachable with a second import: + `import icons from './images/icons?dir'`. +- **No reading or writing files.** Use [`?raw` or `?url`](../../guide/asset-handling) + imports to read a file, [`$write`](./json) on an imported `.json` to save one, + or [PluginFS](../fs) for general access. +- **No delete or rename.** diff --git a/docs/runtime-api/modules/json.md b/docs/runtime-api/modules/json.md new file mode 100644 index 0000000..a4b7fb8 --- /dev/null +++ b/docs/runtime-api/modules/json.md @@ -0,0 +1,107 @@ +# JSON Module + +This page describes how to use ESM-style imports for JSON files and the special +`$write` functionality to persist changes back to the file system. This runtime +feature allows importing JSON files as modules, similar to Node.js, while also +enabling programmatic updates to the imported JSON data. + +## Importing a JSON File + +To import a JSON file in this CEF runtime, use ESM syntax as you would in +Node.js: + +```ts +import config from './config.json' +``` + +Once imported, config holds the JSON data as an object. + +::: warning + +You cannot import JSON modules from remote URL. + +::: + +## Accessing JSON Properties + +You can read properties from the imported JSON object as usual: + +```ts +console.log(config.x) // Outputs the value of `x` in config.json +``` + +## Writing JSON Data + +`since v1.2.0` + +Pengu runtime allows you to modify properties of the imported JSON object. To +persist these changes back to the file system, use the special `$write` method. + +Modify the properties: + +```ts +config.x = 20 // Modify a property +``` + +Call `$write` to save: + +```ts +await config.$write() +``` + +The `$write` method asynchronously writes the current state of the `config` +object back to `config.json`, preserving all modifications. The returned promise +resolves once the file is on disk, and rejects if the write failed. + +### Formatting the output + +`$write` accepts an optional argument that mirrors the third parameter of +[`JSON.stringify`][stringify]: + +```ts +await config.$write() // compact, no whitespace +await config.$write(2) // indent with 2 spaces +await config.$write('\t') // indent with tabs +``` + +A number from 0 to 10 indents by that many spaces, and a string of up to 10 +characters is used as the indent verbatim. Anything else is ignored and the +output is compact. + +[stringify]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify + +### Writes are atomic + +Pengu writes to a temporary file next to the target first, then renames it over +the original. If the client crashes mid-write, your `config.json` is left intact +rather than truncated. + +::: tip + +`$write` only exists on JSON files whose top level is an object or an array — +primitives like `42` or `"hello"` can't carry a method. Ship your config as +`{ ... }` and you'll never hit this. + +::: + +## What `$write` can reach + +`since v1.2.0` + +**`$write` can only overwrite the exact file it was imported from.** It takes no +path, and there is no way to point it somewhere else. + +This is enforced by the runtime rather than by convention: the native side +identifies the calling script from the JavaScript stack, which can't be forged, +and refuses anything that isn't a `.json` module served from `https://plugins/`. + +The practical consequence: importing a third-party library into your plugin does +**not** give that library the ability to modify your plugin's files, or any +other plugin's. + +::: tip + +Need to read or write more than one file? Folder plugins get a scoped +filesystem — see [PluginFS](../fs). + +::: diff --git a/docs/runtime-api/pengu.md b/docs/runtime-api/pengu.md index 333a347..7146dd8 100644 --- a/docs/runtime-api/pengu.md +++ b/docs/runtime-api/pengu.md @@ -1,6 +1,7 @@ -# Pengu namespace +# window.Pengu -This namespace provides information about current Pengu version and its settings. +This is an namespace object that provides information about current Pengu +version and the settings. ## Pengu.version @@ -11,7 +12,7 @@ A read-only property that returns the current version of Pengu Loader. ```js console.log(Pengu.version) -// 1.0.6 +// v1.2.0 ``` ## Pengu.superPotato @@ -23,9 +24,25 @@ A boolean value that indicates the **Super Low Spec Mode** is enabled or not. ```js console.log(Pengu.superPotato) -// true +// true or false ``` +## Pengu.autoUpdateCheck + + + + +A read-only property that indicates whether the user has **automatic update +checking** enabled. Mirrors the toggle in the Pengu hub. + +```js +console.log(Pengu.autoUpdateCheck) +// true or false +``` + +If your plugin ships its own update check, respect this flag — a user who +turned updates off does not expect your plugin to phone home either. + ## Pengu.plugins @@ -36,4 +53,17 @@ An array of plugin entries. ```js console.log(Pengu.plugins) // [ '@default/index.js', 'your-plugin/index.js' ] -``` \ No newline at end of file +``` + +## Pengu.isMac + + + + +A read-only property that indicates the running operating system is **MacOS** or +not. + +```js +console.log(Pengu.isMac) +// true or false +``` diff --git a/docs/runtime-api/plugin-fs.md b/docs/runtime-api/plugin-fs.md deleted file mode 100644 index d86c9f3..0000000 --- a/docs/runtime-api/plugin-fs.md +++ /dev/null @@ -1,201 +0,0 @@ -# PluginFS - -This API allows plugins to access **their own directory** and perform some basic file operations. - -::: warning - -**Top-level** plugin is not allowed since they don't own a directory. - -This API currently does not support calls in **remote** script. - -::: - -::: tip - -All paths passed into this API are relative to the root directory of your plugin. - -::: - -## PluginFS.read(path) - - - - -Read a file in text mode. - -### Params - -- `path` - The path of the file you want to access with respect to the plugin root directory. - -### Return value - -A `Promise` of the content string on success. - -A `Promise` of `undefined` on failure. - -### Example - -```javascript -PluginFS.read("./index.js").then( content => { - console.log(content) -}) - -const content = await PluginFs.read("./README.md") -``` - -## PluginFS.write(path,content,enableAppendMode?) - - - - -Write to a file in text mode. - -### Params - -- `path` - The path of the file you want to access with respect to the plugin root directory. -- `content` - The content string you want to write into. -- `enableAppendMode` - Append to file if set to `true` or overwrite file if `false`. This is `false` by default. - -### Return value - -A `Promise` of a boolean result indicating success or failure. - -### Example - -```javascript -// Create test.txt and write "Hello" into it -PluginFS.write("./test.txt","Hello").then( result => { - if(result){ - // success - }else{ - // fail - } -}) - -// Appending " World!" to it -const result = await PluginFs.write("./test.txt"," World!",true) -``` - -::: tip - -This API can create a file but can't create a file under a non-existing directory. - -::: - -## PluginFS.mkdir(path) - - - - -Create directories recursively. - -### Params - -`path` - The directory path you want to create with respect to the plugin root directory. - -### Return Value - -A `Promise` of a boolean result indicating success or failure. - -### Example - -```javascript -const bMkdir0 = await PluginFS.mkdir("utils") -const bMkdir1 = await PluginFS.mkdir("/a/b") -const bMkdir2 = await PluginFS.mkdir("/a\\c") -// false because it already exists -const bMkdir3 = await PluginFS.mkdir("a\\b/") -``` - -## PluginFS.stat(path) - - - - -Get the status of a file. - -### Params - -- `path` - The file path with respect to the plugin root directory. - -### Return value - -A `Promise` of `FileStat` or `undefined` depending on success or failure. - -```typescript -interface FileStat{ - fileName: string - // 0 if isDir is true - length: number - isDir: boolean -} -``` - -### Example - -```javascript -const stat1 = await PluginFS.stat("a/b") -if(stat1){ - console.log("it's a directory") -} -const stat2 = await PluginFS.stat("a/random.js") -``` - -## PluginFS.ls(path) - - - - -List files and directories under given path. - -### Params - -- `path` - The directory path with respect to the plugin root directory. - -### Return value - -A `Promise` of `Array` of file name strings on success. - -A `Promise` of `undefined` on failure. - -## PluginFS.rm(path,recursively?) - - - - -::: danger - -You should know what you are doing when using this. - -::: - -Remove file/directories. - -Just like `rm` command in Unix-like systems. - -### Params - -- `path` - The file/directory path with respect to the plugin root directory. -- `recursively` - Delete all files/directories under the give path recursively. This is `false` by default. - -### Return value - -A `Promise` of a `number` showing how many files and directories is deleted. - -When deleting with `recursively` set to `true`, the number value is sum of deleted `directories` and `files`. - -### Example - -You can only delete a non-empty directory with `recursively` set to `true` - -```javascript -// 1 -const bRm1 = await PluginFS.rm("./empty-dir") -// 1 -const bRm2 = await PluginFS.rm("./random-file-under-plugin-root") - -// bRm3 == 0 because it's not empty -const bRm3 = await PluginFS.rm("./non-empty-dir") -// bRm4 >= 1 with recursively set to true -const bRm4 = await PluginFS.rm("./non-empty-dir",true) -``` diff --git a/docs/runtime-api/rcp.md b/docs/runtime-api/rcp.md index 64977b9..bc60ee9 100644 --- a/docs/runtime-api/rcp.md +++ b/docs/runtime-api/rcp.md @@ -2,7 +2,8 @@ ## General usage -This object provides easy access and hook to the Riot Client Plugin (RCP) system. +This object provides easy access and hook to the Riot Client Plugin (RCP) +system. Get the `rcp` in your plugin entry: @@ -43,14 +44,14 @@ You can delay the plugin loads by blocking your async callback: ```js rcp.preInit('rcp-name', async () => { // delay 2 seconds - await new Promise(r => setTimeout(r, 2000)) + await new Promise((r) => setTimeout(r, 2000)) }) ``` ::: warning -Do not pre-hook `rcp-fe-commom-libs`. It is used for the plugin loader, -so your callbacks sometimes will not triggered. +Do not pre-hook `rcp-fe-commom-libs`. It is used for the plugin loader, so your +callbacks sometimes will not triggered. ::: @@ -66,7 +67,8 @@ Gives you an opportunity to access the plugin API. - `name` - RCP name, should be prefixed with `rcp-`. - `callback` - A function will be triggered after the plugin is loaded. -- `blocking` - A boolean value indicating whether this callback will be executed in blocking way. It's `false` by default. +- `blocking` - A boolean value indicating whether this callback will be executed + in blocking way. It's `false` by default. Example: @@ -79,8 +81,9 @@ rcp.postInit('rcp-name', (api) => { ::: tip -`postInit` and `preInit` should be called before the target plugin loads, -preferably witin your plugin's `init` entry. So they will not work after the plugin is loaded. +`postInit` and `preInit` should be called before the target plugin loads, +preferably witin your plugin's `init` entry. So they will not work after the +plugin is loaded. ::: @@ -89,8 +92,8 @@ preferably witin your plugin's `init` entry. So they will not work after the plu -This function works as same as `postInit` but allows you -to get the target plugin asynchronously and also works even after the plugin is loaded. +This function works as same as `postInit` but allows you to get the target +plugin asynchronously and also works even after the plugin is loaded. Example with async context: @@ -102,7 +105,7 @@ Or with .then chain: ```js rcp.whenReady('rcp-fe-lol-uikit') - .then(uikit => { + .then((uikit) => { // do something }) ``` diff --git a/docs/runtime-api/settings.md b/docs/runtime-api/settings.md new file mode 100644 index 0000000..2500ba7 --- /dev/null +++ b/docs/runtime-api/settings.md @@ -0,0 +1,269 @@ +# window.Settings + + + +Register a settings form and Pengu renders it for you, inside the Client's own +settings drawer. You describe the fields, Pengu builds the widgets, and your +values object is kept up to date as the user changes them. + +This replaces the usual approach of hand-rolling a settings UI, or asking users +to edit a JSON file by hand. + +## A complete example + +```js +import config from './config.json' + +const schema = { + enabled: { + type: 'boolean', + label: 'Enable my plugin', + default: true, + }, + intensity: { + type: 'number', + label: 'Effect intensity', + default: 50, + min: 0, + max: 100, + slider: true, + }, +} + +Settings.register({ + id: 'my-plugin', + name: 'My Plugin', + description: 'Does something great.', + schema, + state: config, + onChange: () => config.$write(2), +}) +``` + +Pairing `state` with a [writable JSON module](./modules/json) is the shortest +path to settings that survive a restart: the drawer mutates `config` directly, +and `onChange` writes it back to disk. + +## Settings.register(options) + + + +```ts +function register( + options: SettingsRegister, +): SettingsHandle> +``` + +Add your plugin to the settings drawer. + +#### Options + +- `id` (string) a stable identifier, used as the drawer entry key. Your plugin's + folder name is the usual choice. +- `name` (string) the display name in the drawer sidebar. +- `description` (string) [optional] a one-line description shown under the name. +- `icon` (string) [optional] a single character or emoji shown next to the name. +- `schema` ([Schema](#field-types)) the fields to render. +- `hotkey` (string) [optional] a shortcut that opens the drawer with your plugin + selected, e.g. `'Ctrl+,'`. See [Hotkeys](#hotkeys). +- `state` (object) [optional] the object the drawer reads and writes. Omit it + for ephemeral settings that live only for the session. +- `onChange` (function) [optional] called after any change. See + [Persisting values](#persisting-values). + +#### Returns + +A handle: + +```ts +interface SettingsHandle { + values: () => V + set: (patch: Partial) => void + unregister: () => void +} +``` + +- `values()` returns the current values. Call it each time you need them rather + than holding onto the result. +- `set(patch)` applies a partial update and fires `onChange`. +- `unregister()` removes the drawer entry and unbinds the hotkey. + +#### Remarks + +Registering the same `id` twice replaces the first registration and logs a +warning. This is deliberate, so reloading a plugin during development doesn't +leave a duplicate entry behind. + +## Field types + +A schema is a plain object of field id → field. The rendered order follows the +order you write them in. + +```ts +type Field = + | { type: 'boolean'; label: string; default: boolean; description?: string } + | { type: 'string'; label: string; default: string; description?: string + placeholder?: string; multiline?: boolean } + | { type: 'number'; label: string; default: number; description?: string + min?: number; max?: number; step?: number; slider?: boolean } + | { type: 'select'; label: string; default: string; description?: string + options: ReadonlyArray<{ value: string; label: string }> } + | { type: 'action'; label: string; description?: string; perform: () => void } + | { type: 'note'; text: string } +``` + +- **`boolean`** renders a toggle. +- **`string`** renders a text input, or a textarea with `multiline: true`. +- **`number`** renders a number input, or a slider with `slider: true`. +- **`select`** renders a dropdown of `options`. +- **`action`** renders a button that calls `perform`. Holds no value. +- **`note`** renders a line of explanatory text. Holds no value. + +`action` and `note` are the two field types that carry no value, so they never +appear in your values object. + +```js +const schema = { + mode: { + type: 'select', + label: 'Theme mode', + default: 'auto', + options: [ + { value: 'auto', label: 'Follow Client' }, + { value: 'light', label: 'Light' }, + { value: 'dark', label: 'Dark' }, + ], + }, + note: { + type: 'note', + text: 'Changes apply on the next Client reload.', + }, + reload: { + type: 'action', + label: 'Reload now', + perform: () => window.reloadClient(), + }, +} +``` + +## Persisting values + +Pengu does not persist anything on its own. You choose the storage: + +```js +// writable JSON module — the file lives next to your plugin +import config from './config.json' +Settings.register({ id, name, schema, state: config, + onChange: () => config.$write(2) }) + +// DataStore — a single key holding the whole object +const state = DataStore.get('my-plugin/settings', {}) +Settings.register({ id, name, schema, state, + onChange: (values) => DataStore.set('my-plugin/settings', values) }) + +// nothing — settings reset every launch +Settings.register({ id, name, schema }) +``` + +At register time, any schema key missing from `state` is filled in with its +`default`, mutating your object in place. A `config.json` that starts as `{}` +therefore ends up fully populated on the first save. + +`onChange` is debounced by about 80 ms, so dragging a slider produces one write +rather than one per pixel. It receives the current values object. An async +`onChange` is not awaited — rejections are logged to the console so a failed +save doesn't block the drawer. + +::: warning + +The drawer only re-renders for changes made through the drawer itself or +through `handle.set()`. If you mutate your `state` object directly, the form +will keep showing the old value until it is reopened — route programmatic +changes through `set()` instead. + +::: + +## Hotkeys + +```js +Settings.register({ + id: 'my-plugin', + name: 'My Plugin', + hotkey: 'Ctrl+Shift+S', + schema, +}) +``` + +The hotkey opens the drawer with your plugin selected. Rules: + +- At least one modifier (`Ctrl`, `Alt`, `Shift`, `Meta`) is required. A bare key + is rejected with a console warning. +- `Ctrl` also matches `Cmd` on macOS, so one registration covers both platforms. +- Hotkeys don't fire while a text input or textarea has focus. +- If two plugins claim the same combination, the most recently registered one + wins and a warning is logged. + +`Cmd`, `Command`, `Control` and `Option` are all accepted spellings. + +## Settings.open(pluginId?) + + + +```ts +function open(pluginId?: string): void +``` + +Open the drawer. Pass a plugin id to focus that pane; omit it to reopen wherever +the user last was. + +```js +CommandBar.addAction({ + name: 'My Plugin settings', + perform: () => Settings.open('my-plugin'), +}) +``` + +## Settings.close() + + + +```ts +function close(): void +``` + +Close the drawer. + +## Settings.list() + + + +```ts +function list(): Array<{ id: string; name: string }> +``` + +Every plugin currently registered, in registration order. + +```js +console.log(Settings.list()) +// [ { id: 'my-plugin', name: 'My Plugin' } ] +``` + +## TypeScript + +With [`@pengujs/types`](../guide/npm-typescript) installed, writing the schema +`as const` lets TypeScript infer the shape of your values object from the +defaults: + +```ts +const schema = { + enabled: { type: 'boolean', label: 'Enabled', default: true }, + threshold: { type: 'number', label: 'Threshold', default: 50 }, +} as const + +const handle = Settings.register({ id: 'my-plugin', name: 'My Plugin', schema }) + +handle.values().enabled // boolean +handle.values().threshold // number +handle.set({ threshold: 80 }) // ok +handle.set({ threshold: 'high' }) // type error +``` diff --git a/docs/runtime-api/socket.md b/docs/runtime-api/socket.md index 4fb67ec..a7854af 100644 --- a/docs/runtime-api/socket.md +++ b/docs/runtime-api/socket.md @@ -1,7 +1,8 @@ # LCU Socket observation -This namespace helps you to observe specific LCU APIs without creating a new WebSocket. -You cannot get it directly from `window`, instead use the context of the [`init` entry point](../guide/javascript-plugin#plugin-entry-points). +This namespace helps you to observe specific LCU APIs without creating a new +WebSocket. You cannot get it directly from `window`, instead use the context of +the [`init` entry point](../guide/javascript-plugin#plugin-entry-points). ## socket.observe(api, listener) @@ -11,7 +12,7 @@ You cannot get it directly from `window`, instead use the context of the [`init` ```ts function observe( api: string, - listener: ApiListener + listener: ApiListener, ): { disconnect: () => void } interface EventData { @@ -34,7 +35,8 @@ Subscribe a listener to listen when the given API endpoint get called. ### Return value: -An object with a prop `disconnect` that could be called to disconnect the observer. +An object with a prop `disconnect` that could be called to disconnect the +observer. Example: @@ -53,4 +55,5 @@ socket.observe('/lol-matchmaking/v1/ready-check', (data) => { function disconnect(api: string, listener: ApiListener) ``` -Disconnect a subscribed listener. The function parameters like the function above. \ No newline at end of file +Disconnect a subscribed listener. The function parameters like the function +above. diff --git a/docs/runtime-api/toast.md b/docs/runtime-api/toast.md index a10045e..1bf3cfc 100644 --- a/docs/runtime-api/toast.md +++ b/docs/runtime-api/toast.md @@ -1,14 +1,58 @@ # Toast -This namespace is used to push your toast notifications onto the League Client screen. +This namespace is used to push your toast notifications onto the League Client +screen. -## Toast.success(message) +Every method that pushes a toast returns its **id** as a string. Keep it if you +want to [update](#toast-update-id-patch) or [dismiss](#toast-dismiss-id) the toast later — +otherwise you can ignore it. + +## Toast options + + + +All push methods take an optional options object as their last argument. + +```ts +interface ToastOptions { + duration?: number + position?: ToastPosition + icon?: string + className?: string + id?: string + dismissable?: boolean +} + +type ToastPosition = + | 'top-left' | 'top-center' | 'top-right' + | 'bottom-left' | 'bottom-center' | 'bottom-right' +``` + +- `duration` how long the toast stays, in milliseconds. Defaults to `5000`. + `0`, a negative number, or `Infinity` makes it **sticky** — it stays until + dismissed. `Toast.loading()` is sticky by default. +- `position` where it appears. Defaults to `bottom-right`. +- `icon` a single character or emoji, replacing the type's default glyph. +- `className` extra CSS class on the toast element, for your own styling. +- `id` reuse an id to **replace** the existing toast instead of stacking a new + one. Handy for de-duping a toast fired from a repeating event. +- `dismissable` whether to show the × button. Defaults to `true`. + +```js +Toast.info('Saved to your config', { + duration: 2000, + position: 'top-center', + id: 'config-saved', // repeated saves replace, never stack +}) +``` + +## Toast.success(message, options?) ```ts -function success(message: string): void +function success(message: string, options?: ToastOptions): string ``` Push a simple notification with a success checkmark. @@ -16,6 +60,7 @@ Push a simple notification with a success checkmark. Params: - `message` a string to be shown on the notification. +- `options` [optional] see [Toast options](#toast-options). Example: @@ -23,13 +68,13 @@ Example: Toast.success('Welcome to my theme!') ``` -## Toast.error(message) +## Toast.error(message, options?) ```ts -function error(message: string): void +function error(message: string, options?: ToastOptions): string ``` Push a simple notification with a failure icon. @@ -37,6 +82,7 @@ Push a simple notification with a failure icon. Params: - `message` a string to be shown on the notification. +- `options` [optional] see [Toast options](#toast-options). Example: @@ -44,21 +90,117 @@ Example: Toast.error('Oops! Something went wrong.') ``` +## Toast.info(message, options?) + + + + +```ts +function info(message: string, options?: ToastOptions): string +``` + +Push a neutral, informational notification. + +Example: + +```ts +Toast.info('3 new plugins were loaded.') +``` + +## Toast.warning(message, options?) + + + + +```ts +function warning(message: string, options?: ToastOptions): string +``` + +Push a notification with a warning icon. + +Example: + +```ts +Toast.warning('This theme was built for an older Client version.') +``` + +## Toast.loading(message, options?) + + + + +```ts +function loading(message: string, options?: ToastOptions): string +``` + +Push a notification with a spinner. Unlike the others this one is **sticky by +default** — it stays until you `update` it into a terminal state or `dismiss` +it. Pass an explicit `duration` to override that. + +If all you want is "spinner until this promise settles", use +[`Toast.promise`](#toast-promise-promise-msg) instead. + +Example: + +```js +const id = Toast.loading('Downloading assets...') + +await downloadAssets() +Toast.update(id, { type: 'success', message: 'Assets ready!' }) +``` + +## Toast.custom(html, options?) + + + + +```ts +function custom(html: string, options?: ToastOptions): string +``` + +Push a notification with a body you render yourself. The string is inserted as +HTML. + +Params: + +- `html` an HTML string for the toast body. +- `options` [optional] see [Toast options](#toast-options). + +Example: + +```js +Toast.custom('Patch 14.1
Your theme has been updated.', { + duration: 8000, +}) +``` + +::: warning + +The HTML is inserted as-is. Never build it from data you did not produce — +a champion name or summoner name pulled from the LCU should be escaped, or +passed as a plain `message` to one of the typed methods instead. + +::: + ## Toast.promise(promise, msg) ```ts -function promise(promise: Promise, msg: { - loading: string - success: string - error: string -}): Promise +function promise( + promise: Promise, + msg: { + loading: string + success: string + error: string | ((err: unknown) => string) + }, + options?: ToastOptions, +): Promise ``` -Push a progress notification and wait for the given promise to complete. -This function returns the given promise that is helpful for then/catch chain. +Push a progress notification and wait for the given promise to complete. This +function returns the given promise that is helpful for then/catch chain. Params: @@ -66,7 +208,9 @@ Params: - `msg` an object with these properties: - `loading` a string message to be shown when the progress starts loading. - `success` a string to be shown when the promise is resolved. - - `error` a string to be shown when the promise is rejected. + - `error` a string to be shown when the promise is rejected, or a function + receiving the rejection value and returning the message. +- `options` [optional] see [Toast options](#toast-options). Example: @@ -74,16 +218,86 @@ Example: let myTask = new Promise((resolve, reject) => { // wait for 3s then fulfill randomly setTimeout(() => { - if (Math.random() > 0.5) + if (Math.random() > 0.5) { resolve(10) - else + } else { reject() + } }, 3000) }) Toast.promise(myTask, { loading: 'Working in progress...', success: 'Oh nice! 😎', - error: 'OOps! 😥' + error: 'OOps! 😥', +}) +``` + +Use the function form of `error` when you want the reason in the message: + +```js +Toast.promise(fetchRank(), { + loading: 'Fetching your rank...', + success: 'Got it!', + error: (err) => `Could not fetch rank: ${err}`, }) -``` \ No newline at end of file +``` + +## Toast.update(id, patch) + + + + +```ts +function update(id: string, patch: { + message?: string + type?: ToastType + icon?: string +}): void +``` + +Change a toast that is already on screen, keeping it in place instead of +stacking a new one. Does nothing if the id is unknown. + +Moving a sticky `loading` toast to a terminal type (`success`, `error`, ...) +re-arms its auto-dismiss timer, so it will fade out on its own afterwards. + +Params: + +- `id` the id returned when the toast was pushed. +- `patch` the fields to change. Omitted fields are left alone. + +Example: + +```js +const id = Toast.loading('Connecting to server...') + +try { + await connect() + Toast.update(id, { type: 'success', message: 'Connected!' }) +} catch (err) { + Toast.update(id, { type: 'error', message: 'Connection failed.' }) +} +``` + +## Toast.dismiss(id?) + + + + +```ts +function dismiss(id?: string): void +``` + +Remove a toast immediately. Omit `id` to clear **every** toast currently on +screen. + +Example: + +```js +const id = Toast.info('Hold tight...') +Toast.dismiss(id) + +// clear everything +Toast.dismiss() +``` diff --git a/package.json b/package.json index 8a9422c..eade439 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pengu-docs", - "version": "1.1.0", - "description": "Pengu Loader docs", + "version": "1.2.0", + "description": "Pengu Loader Docs", "license": "MIT", "type": "module", "scripts": { @@ -10,14 +10,19 @@ "preview": "vitepress preview" }, "devDependencies": { - "@types/node": "^18.14.6", - "vitepress": "^1.0.0-rc.4", - "vitepress-plugin-nprogress": "^0.0.4", - "vitepress-plugin-tabs": "^0.2.0", - "vue": "^3.3.4" + "@types/node": "^20", + "autoprefixer": "^10.5.4", + "postcss": "^8.5.25", + "sass": "^1.102.0", + "tailwindcss": "^3.4.14", + "vitepress": "^1.6.4", + "vitepress-plugin-nprogress": "^0.1.1", + "vitepress-plugin-tabs": "^0.9.1", + "vue": "^3.5.40" }, "engines": { - "node": ">=18" + "node": ">=20", + "pnpm": ">=9" }, "pnpm": { "peerDependencyRules": { @@ -26,5 +31,11 @@ "search-insights" ] } + }, + "postcss": { + "plugins": { + "tailwindcss": {}, + "autoprefixer": {} + } } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2387549..5f9a57f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,218 +1,153 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -devDependencies: - '@types/node': - specifier: ^18.14.6 - version: 18.14.6 - vitepress: - specifier: ^1.0.0-rc.4 - version: 1.0.0-rc.4(@types/node@18.14.6) - vitepress-plugin-nprogress: - specifier: ^0.0.4 - version: 0.0.4 - vitepress-plugin-tabs: - specifier: ^0.2.0 - version: 0.2.0(vitepress@1.0.0-rc.4)(vue@3.3.4) - vue: - specifier: ^3.3.4 - version: 3.3.4 +importers: + + .: + devDependencies: + '@types/node': + specifier: ^20 + version: 20.17.6 + autoprefixer: + specifier: ^10.5.4 + version: 10.5.4(postcss@8.5.25) + postcss: + specifier: ^8.5.25 + version: 8.5.25 + sass: + specifier: ^1.102.0 + version: 1.102.0 + tailwindcss: + specifier: ^3.4.14 + version: 3.4.14 + vitepress: + specifier: ^1.6.4 + version: 1.6.4(@algolia/client-search@5.56.0)(@types/node@20.17.6)(nprogress@0.2.0)(postcss@8.5.25)(sass@1.102.0)(search-insights@2.17.0) + vitepress-plugin-nprogress: + specifier: ^0.1.1 + version: 0.1.1 + vitepress-plugin-tabs: + specifier: ^0.9.1 + version: 0.9.1(vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@20.17.6)(nprogress@0.2.0)(postcss@8.5.25)(sass@1.102.0)(search-insights@2.17.0))(vue@3.5.40) + vue: + specifier: ^3.5.40 + version: 3.5.40 packages: - /@algolia/autocomplete-core@1.9.3(algoliasearch@4.17.0): - resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} - dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(algoliasearch@4.17.0) - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.17.0) - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - - search-insights - dev: true + '@algolia/abtesting@1.22.0': + resolution: {integrity: sha512-BFR6zNowNKcY7Ou7TaJc9QWexES4YKPbmf/OTFofpdsdhz4x6q0lbxp3duO0EHnyrN7rE4ba/TSXuY+BDGu4+g==} + engines: {node: '>= 14.0.0'} - /@algolia/autocomplete-plugin-algolia-insights@1.9.3(algoliasearch@4.17.0): - resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} + '@algolia/autocomplete-core@1.17.7': + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7': + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} peerDependencies: search-insights: '>= 1 < 3' - peerDependenciesMeta: - search-insights: - optional: true - dependencies: - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.17.0) - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - dev: true - /@algolia/autocomplete-preset-algolia@1.9.3(algoliasearch@4.17.0): - resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + '@algolia/autocomplete-preset-algolia@1.17.7': + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - peerDependenciesMeta: - '@algolia/client-search': - optional: true - dependencies: - '@algolia/autocomplete-shared': 1.9.3(algoliasearch@4.17.0) - algoliasearch: 4.17.0 - dev: true - /@algolia/autocomplete-shared@1.9.3(algoliasearch@4.17.0): - resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + '@algolia/autocomplete-shared@1.17.7': + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - peerDependenciesMeta: - '@algolia/client-search': - optional: true - dependencies: - algoliasearch: 4.17.0 - dev: true - /@algolia/cache-browser-local-storage@4.17.0: - resolution: {integrity: sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==} - dependencies: - '@algolia/cache-common': 4.17.0 - dev: true + '@algolia/client-abtesting@5.56.0': + resolution: {integrity: sha512-7r4Z3NC7yU1oAQVWJNA2HX7tX481F3pJvCGyLIXiTdBcthz4Q/o21jwcMYDFkuI92UWTNBQQmHYgwHo1zS5dzg==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-common@4.17.0: - resolution: {integrity: sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==} - dev: true + '@algolia/client-analytics@5.56.0': + resolution: {integrity: sha512-avmjXQSq+jadFO8Xl2em05/uQdQnEmHsJyOAdVbZkmVgpMfxL12aJwVVfGNwYr9nulcpuJN1X0lTaQ5wxuNGcA==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-in-memory@4.17.0: - resolution: {integrity: sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==} - dependencies: - '@algolia/cache-common': 4.17.0 - dev: true + '@algolia/client-common@5.56.0': + resolution: {integrity: sha512-v2TPStUhY//ripPjIVclZ8AWc7DEGooXULZGFlFu37zNatgHjw34oZZ+OSbbc/YHO+xZwPl62I1k8xH1m4S2eg==} + engines: {node: '>= 14.0.0'} - /@algolia/client-account@4.17.0: - resolution: {integrity: sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==} - dependencies: - '@algolia/client-common': 4.17.0 - '@algolia/client-search': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true + '@algolia/client-insights@5.56.0': + resolution: {integrity: sha512-P0ehROpM4Sem3Sqo5x2cKPgj67D3G3jy0rh1Amwkcvsfr6tkvIcdCmerieanqTF7NxUMPNFLkpIFeMO8Rpa50w==} + engines: {node: '>= 14.0.0'} - /@algolia/client-analytics@4.17.0: - resolution: {integrity: sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==} - dependencies: - '@algolia/client-common': 4.17.0 - '@algolia/client-search': 4.17.0 - '@algolia/requester-common': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true + '@algolia/client-personalization@5.56.0': + resolution: {integrity: sha512-SXK3Vn3WVxyzbm31oePZBJkp1wpOyuWdd4B/Pv7n0aXDxmeSWhC1R1FC1517mMrFAIaPH4Rt0x6RUe7ZNjz8FA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-common@4.17.0: - resolution: {integrity: sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==} - dependencies: - '@algolia/requester-common': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true + '@algolia/client-query-suggestions@5.56.0': + resolution: {integrity: sha512-5+ZdX8garFnmycnZgKhtXHePEaLj5zqDxI/0lkhhluzCcvTn0/PvvTirTg8hHYetQHvn7GDyeAiqTAieMvMW4A==} + engines: {node: '>= 14.0.0'} - /@algolia/client-personalization@4.17.0: - resolution: {integrity: sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==} - dependencies: - '@algolia/client-common': 4.17.0 - '@algolia/requester-common': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true + '@algolia/client-search@5.56.0': + resolution: {integrity: sha512-+mKUdYvqOi0BcvpAEyCEw49vSBptufIcfibtHz2bdr1pI789M46Yt0uQEk/sxtK3teh71OQvVFHaTDzShUWewQ==} + engines: {node: '>= 14.0.0'} - /@algolia/client-search@4.17.0: - resolution: {integrity: sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==} - dependencies: - '@algolia/client-common': 4.17.0 - '@algolia/requester-common': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true + '@algolia/ingestion@1.56.0': + resolution: {integrity: sha512-9g/zj+AZx5moFcdFIrYQoVrueXivjUcc3MQHtCYT8WhIuk1lUh1AyEhvJCS0XBZld09cLvd1AZ3BvDBpVpX2UA==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-common@4.17.0: - resolution: {integrity: sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==} - dev: true + '@algolia/monitoring@1.56.0': + resolution: {integrity: sha512-Qf3Sr6f9A9uxCZUf3MXS0d2b877uYzEB5yxqpVGXAhcJnBCQjrRRon0KvefpGkxy+BshrIJs96OUoMtGqXTFDA==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-console@4.17.0: - resolution: {integrity: sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==} - dependencies: - '@algolia/logger-common': 4.17.0 - dev: true + '@algolia/recommend@5.56.0': + resolution: {integrity: sha512-GXWG1rWc5wu8hY4N33Y3b6ernY6sAdAvmKWN/zHAiACOx40WnpG0TVX5YazCAr/9gOYGInSiM2A0y2jy2xbiDA==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-browser-xhr@4.17.0: - resolution: {integrity: sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==} - dependencies: - '@algolia/requester-common': 4.17.0 - dev: true + '@algolia/requester-browser-xhr@5.56.0': + resolution: {integrity: sha512-7t24cBxaInS3mZb7ddEaZT/tp6q+/aR4YttsQVyP1/i+LmwPR34atO35KjaLFCcRVrlP7sYOAqkCfg6lIRB+ew==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-common@4.17.0: - resolution: {integrity: sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==} - dev: true + '@algolia/requester-fetch@5.56.0': + resolution: {integrity: sha512-R7ePHgVYmDFjZpvrsVAfbDz/d4RxKAYZ5/vgLfIsCVRZRryjWl/3INOxpOICzitehQ5FjNtNjcLQTrmHPTcHBQ==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-node-http@4.17.0: - resolution: {integrity: sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==} - dependencies: - '@algolia/requester-common': 4.17.0 - dev: true + '@algolia/requester-node-http@5.56.0': + resolution: {integrity: sha512-PIOUXlSnrqM0S+WOgDRb4RzotydJH7ZoT6tOyL7tAO7qJOfvX5wsEW8Pe+PMKMwvuI4/gIyK9cg2H7lJXqnc4Q==} + engines: {node: '>= 14.0.0'} - /@algolia/transporter@4.17.0: - resolution: {integrity: sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==} - dependencies: - '@algolia/cache-common': 4.17.0 - '@algolia/logger-common': 4.17.0 - '@algolia/requester-common': 4.17.0 - dev: true + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} - /@babel/helper-string-parser@7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - dev: true - /@babel/parser@7.21.4: - resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} engines: {node: '>=6.0.0'} hasBin: true - dependencies: - '@babel/types': 7.21.4 - dev: true - /@babel/types@7.21.4: - resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: true - /@docsearch/css@3.5.1: - resolution: {integrity: sha512-2Pu9HDg/uP/IT10rbQ+4OrTQuxIWdKVUEdcw9/w7kZJv9NeHS6skJx1xuRiFyoGKwAzcHXnLp7csE99sj+O1YA==} - dev: true + '@docsearch/css@3.8.2': + resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} - /@docsearch/js@3.5.1: - resolution: {integrity: sha512-EXi8de5njxgP6TV3N9ytnGRLG9zmBNTEZjR4VzwPcpPLbZxxTLG2gaFyJyKiFVQxHW/DPlMrDJA3qoRRGEkgZw==} - dependencies: - '@docsearch/react': 3.5.1 - preact: 10.13.2 - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/react' - - react - - react-dom - - search-insights - dev: true + '@docsearch/js@3.8.2': + resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} - /@docsearch/react@3.5.1: - resolution: {integrity: sha512-t5mEODdLzZq4PTFAm/dvqcvZFdPDMdfPE5rJS5SC8OUq9mPzxEy6b+9THIqNM9P0ocCb4UC5jqBrxKclnuIbzQ==} + '@docsearch/react@3.8.2': + resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' peerDependenciesMeta: '@types/react': optional: true @@ -220,351 +155,472 @@ packages: optional: true react-dom: optional: true - dependencies: - '@algolia/autocomplete-core': 1.9.3(algoliasearch@4.17.0) - '@algolia/autocomplete-preset-algolia': 1.9.3(algoliasearch@4.17.0) - '@docsearch/css': 3.5.1 - algoliasearch: 4.17.0 - transitivePeerDependencies: - - '@algolia/client-search' - - search-insights - dev: true + search-insights: + optional: true + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] - /@esbuild/android-arm64@0.18.16: - resolution: {integrity: sha512-wsCqSPqLz+6Ov+OM4EthU43DyYVVyfn15S4j1bJzylDpc1r1jZFFfJQNfDuT8SlgwuqpmpJXK4uPlHGw6ve7eA==} + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.18.16: - resolution: {integrity: sha512-gCHjjQmA8L0soklKbLKA6pgsLk1byULuHe94lkZDzcO3/Ta+bbeewJioEn1Fr7kgy9NWNFy/C+MrBwC6I/WCug==} + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.18.16: - resolution: {integrity: sha512-ldsTXolyA3eTQ1//4DS+E15xl0H/3DTRJaRL0/0PgkqDsI0fV/FlOtD+h0u/AUJr+eOTlZv4aC9gvfppo3C4sw==} + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.18.16: - resolution: {integrity: sha512-aBxruWCII+OtluORR/KvisEw0ALuw/qDQWvkoosA+c/ngC/Kwk0lLaZ+B++LLS481/VdydB2u6tYpWxUfnLAIw==} + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.18.16: - resolution: {integrity: sha512-6w4Dbue280+rp3LnkgmriS1icOUZDyPuZo/9VsuMUTns7SYEiOaJ7Ca1cbhu9KVObAWfmdjUl4gwy9TIgiO5eA==} + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.18.16: - resolution: {integrity: sha512-x35fCebhe9s979DGKbVAwXUOcTmCIE32AIqB9CB1GralMIvxdnMLAw5CnID17ipEw9/3MvDsusj/cspYt2ZLNQ==} + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.18.16: - resolution: {integrity: sha512-YM98f+PeNXF3GbxIJlUsj+McUWG1irguBHkszCIwfr3BXtXZsXo0vqybjUDFfu9a8Wr7uUD/YSmHib+EeGAFlg==} + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.18.16: - resolution: {integrity: sha512-XIqhNUxJiuy+zsR77+H5Z2f7s4YRlriSJKtvx99nJuG5ATuJPjmZ9n0ANgnGlPCpXGSReFpgcJ7O3SMtzIFeiQ==} + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.18.16: - resolution: {integrity: sha512-b5ABb+5Ha2C9JkeZXV+b+OruR1tJ33ePmv9ZwMeETSEKlmu/WJ45XTTG+l6a2KDsQtJJ66qo/hbSGBtk0XVLHw==} + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.18.16: - resolution: {integrity: sha512-no+pfEpwnRvIyH+txbBAWtjxPU9grslmTBfsmDndj7bnBmr55rOo/PfQmRfz7Qg9isswt1FP5hBbWb23fRWnow==} + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.18.16: - resolution: {integrity: sha512-Zbnczs9ZXjmo0oZSS0zbNlJbcwKXa/fcNhYQjahDs4Xg18UumpXG/lwM2lcSvHS3mTrRyCYZvJbmzYc4laRI1g==} + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.18.16: - resolution: {integrity: sha512-YMF7hih1HVR/hQVa/ot4UVffc5ZlrzEb3k2ip0nZr1w6fnYypll9td2qcoMLvd3o8j3y6EbJM3MyIcXIVzXvQQ==} + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.18.16: - resolution: {integrity: sha512-Wkz++LZ29lDwUyTSEnzDaaP5OveOgTU69q9IyIw9WqLRxM4BjTBjz9un4G6TOvehWpf/J3gYVFN96TjGHrbcNQ==} + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.18.16: - resolution: {integrity: sha512-LFMKZ30tk78/mUv1ygvIP+568bwf4oN6reG/uczXnz6SvFn4e2QUFpUpZY9iSJT6Qpgstrhef/nMykIXZtZWGQ==} + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.18.16: - resolution: {integrity: sha512-3ZC0BgyYHYKfZo3AV2/66TD/I9tlSBaW7eWTEIkrQQKfJIifKMMttXl9FrAg+UT0SGYsCRLI35Gwdmm96vlOjg==} + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.18.16: - resolution: {integrity: sha512-xu86B3647DihHJHv/wx3NCz2Dg1gjQ8bbf9cVYZzWKY+gsvxYmn/lnVlqDRazObc3UMwoHpUhNYaZset4X8IPA==} + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.18.16: - resolution: {integrity: sha512-uVAgpimx9Ffw3xowtg/7qQPwHFx94yCje+DoBx+LNm2ePDpQXHrzE+Sb0Si2VBObYz+LcRps15cq+95YM7gkUw==} + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.18.16: - resolution: {integrity: sha512-6OjCQM9wf7z8/MBi6BOWaTL2AS/SZudsZtBziXMtNI8r/U41AxS9x7jn0ATOwVy08OotwkPqGRMkpPR2wcTJXA==} + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.18.16: - resolution: {integrity: sha512-ZoNkruFYJp9d1LbUYCh8awgQDvB9uOMZqlQ+gGEZR7v6C+N6u7vPr86c+Chih8niBR81Q/bHOSKGBK3brJyvkQ==} + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.18.16: - resolution: {integrity: sha512-+j4anzQ9hrs+iqO+/wa8UE6TVkKua1pXUb0XWFOx0FiAj6R9INJ+WE//1/Xo6FG1vB5EpH3ko+XcgwiDXTxcdw==} + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.18.16: - resolution: {integrity: sha512-5PFPmq3sSKTp9cT9dzvI67WNfRZGvEVctcZa1KGjDDu4n3H8k59Inbk0du1fz0KrAbKKNpJbdFXQMDUz7BG4rQ==} + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.18.16: - resolution: {integrity: sha512-sCIVrrtcWN5Ua7jYXNG1xD199IalrbfV2+0k/2Zf2OyV2FtnQnMgdzgpRAbi4AWlKJj1jkX+M+fEGPQj6BQB4w==} + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + '@iconify-json/simple-icons@1.2.93': + resolution: {integrity: sha512-/XhANjfGYOuqvSR3TmUnkQkINvQ4GVjVuukvymRbxtVFBvIq/yiXJqCDycKcQPT401OYT9H2vIY6ihAlz1QIAw==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@parcel/watcher-android-arm64@2.5.0': + resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.0': + resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.0': + resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.0': + resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.0': + resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.5.0': + resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.0': + resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.5.0': + resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.5.0': + resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.5.0': + resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.5.0': + resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.0': + resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.0': + resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.0': + resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/rollup-android-arm-eabi@4.21.0': + resolution: {integrity: sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.21.0': + resolution: {integrity: sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.21.0': + resolution: {integrity: sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.21.0': + resolution: {integrity: sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': + resolution: {integrity: sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.21.0': + resolution: {integrity: sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.21.0': + resolution: {integrity: sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.21.0': + resolution: {integrity: sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': + resolution: {integrity: sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.21.0': + resolution: {integrity: sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.21.0': + resolution: {integrity: sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.21.0': + resolution: {integrity: sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.21.0': + resolution: {integrity: sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.21.0': + resolution: {integrity: sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.21.0': + resolution: {integrity: sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.21.0': + resolution: {integrity: sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==} + cpu: [x64] + os: [win32] + + '@shikijs/core@2.5.0': + resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==} + + '@shikijs/engine-javascript@2.5.0': + resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==} + + '@shikijs/engine-oniguruma@2.5.0': + resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==} + + '@shikijs/langs@2.5.0': + resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==} + + '@shikijs/themes@2.5.0': + resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==} + + '@shikijs/transformers@2.5.0': + resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==} + + '@shikijs/types@2.5.0': + resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - /@types/node@18.14.6: - resolution: {integrity: sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==} - dev: true + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - /@types/web-bluetooth@0.0.17: - resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} - dev: true + '@types/node@20.17.6': + resolution: {integrity: sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==} - /@vitejs/plugin-vue@4.2.3(vite@4.4.9)(vue@3.3.4): - resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} - engines: {node: ^14.18.0 || >=16.0.0} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^4.0.0 + vite: ^5.0.0 || ^6.0.0 vue: ^3.2.25 - dependencies: - vite: 4.4.9(@types/node@18.14.6) - vue: 3.3.4 - dev: true - /@vue/compiler-core@3.3.4: - resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} - dependencies: - '@babel/parser': 7.21.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - source-map-js: 1.0.2 - dev: true + '@vue/compiler-core@3.5.40': + resolution: {integrity: sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==} - /@vue/compiler-dom@3.3.4: - resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} - dependencies: - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 - dev: true + '@vue/compiler-dom@3.5.40': + resolution: {integrity: sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==} - /@vue/compiler-sfc@3.3.4: - resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} - dependencies: - '@babel/parser': 7.21.4 - '@vue/compiler-core': 3.3.4 - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-ssr': 3.3.4 - '@vue/reactivity-transform': 3.3.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - magic-string: 0.30.1 - postcss: 8.4.27 - source-map-js: 1.0.2 - dev: true + '@vue/compiler-sfc@3.5.40': + resolution: {integrity: sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==} - /@vue/compiler-ssr@3.3.4: - resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} - dependencies: - '@vue/compiler-dom': 3.3.4 - '@vue/shared': 3.3.4 - dev: true + '@vue/compiler-ssr@3.5.40': + resolution: {integrity: sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==} - /@vue/devtools-api@6.5.0: - resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} - dev: true + '@vue/devtools-api@7.7.10': + resolution: {integrity: sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==} - /@vue/reactivity-transform@3.3.4: - resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} - dependencies: - '@babel/parser': 7.21.4 - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 - estree-walker: 2.0.2 - magic-string: 0.30.1 - dev: true + '@vue/devtools-kit@7.7.10': + resolution: {integrity: sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==} - /@vue/reactivity@3.3.4: - resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} - dependencies: - '@vue/shared': 3.3.4 - dev: true + '@vue/devtools-shared@7.7.10': + resolution: {integrity: sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==} - /@vue/runtime-core@3.3.4: - resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} - dependencies: - '@vue/reactivity': 3.3.4 - '@vue/shared': 3.3.4 - dev: true + '@vue/reactivity@3.5.40': + resolution: {integrity: sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==} - /@vue/runtime-dom@3.3.4: - resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} - dependencies: - '@vue/runtime-core': 3.3.4 - '@vue/shared': 3.3.4 - csstype: 3.1.2 - dev: true + '@vue/runtime-core@3.5.40': + resolution: {integrity: sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==} - /@vue/server-renderer@3.3.4(vue@3.3.4): - resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} - peerDependencies: - vue: 3.3.4 - dependencies: - '@vue/compiler-ssr': 3.3.4 - '@vue/shared': 3.3.4 - vue: 3.3.4 - dev: true + '@vue/runtime-dom@3.5.40': + resolution: {integrity: sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==} - /@vue/shared@3.3.4: - resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} - dev: true + '@vue/server-renderer@3.5.40': + resolution: {integrity: sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==} - /@vueuse/core@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==} - dependencies: - '@types/web-bluetooth': 0.0.17 - '@vueuse/metadata': 10.3.0 - '@vueuse/shared': 10.3.0(vue@3.3.4) - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true + '@vue/shared@3.5.40': + resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} + + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} - /@vueuse/integrations@10.3.0(focus-trap@7.5.2)(vue@3.3.4): - resolution: {integrity: sha512-Jgiv7oFyIgC6BxmDtiyG/fxyGysIds00YaY7sefwbhCZ2/tjEx1W/1WcsISSJPNI30in28+HC2J4uuU8184ekg==} + '@vueuse/integrations@12.8.2': + resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==} peerDependencies: - async-validator: '*' - axios: '*' - change-case: '*' - drauu: '*' - focus-trap: '*' - fuse.js: '*' - idb-keyval: '*' - jwt-decode: '*' - nprogress: '*' - qrcode: '*' - sortablejs: '*' - universal-cookie: '*' + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 peerDependenciesMeta: async-validator: optional: true @@ -590,194 +646,628 @@ packages: optional: true universal-cookie: optional: true - dependencies: - '@vueuse/core': 10.3.0(vue@3.3.4) - '@vueuse/shared': 10.3.0(vue@3.3.4) - focus-trap: 7.5.2 - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - /@vueuse/metadata@10.3.0: - resolution: {integrity: sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==} - dev: true + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} - dependencies: - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - - /algoliasearch@4.17.0: - resolution: {integrity: sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==} - dependencies: - '@algolia/cache-browser-local-storage': 4.17.0 - '@algolia/cache-common': 4.17.0 - '@algolia/cache-in-memory': 4.17.0 - '@algolia/client-account': 4.17.0 - '@algolia/client-analytics': 4.17.0 - '@algolia/client-common': 4.17.0 - '@algolia/client-personalization': 4.17.0 - '@algolia/client-search': 4.17.0 - '@algolia/logger-common': 4.17.0 - '@algolia/logger-console': 4.17.0 - '@algolia/requester-browser-xhr': 4.17.0 - '@algolia/requester-common': 4.17.0 - '@algolia/requester-node-http': 4.17.0 - '@algolia/transporter': 4.17.0 - dev: true - - /ansi-sequence-parser@1.1.0: - resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} - dev: true - - /body-scroll-lock@4.0.0-beta.0: - resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} - dev: true - - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true - - /esbuild@0.18.16: - resolution: {integrity: sha512-1xLsOXrDqwdHxyXb/x/SOyg59jpf/SH7YMvU5RNSU7z3TInaASNJWNFJ6iRvLvLETZMasF3d1DdZLg7sgRimRQ==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.18.16 - '@esbuild/android-arm64': 0.18.16 - '@esbuild/android-x64': 0.18.16 - '@esbuild/darwin-arm64': 0.18.16 - '@esbuild/darwin-x64': 0.18.16 - '@esbuild/freebsd-arm64': 0.18.16 - '@esbuild/freebsd-x64': 0.18.16 - '@esbuild/linux-arm': 0.18.16 - '@esbuild/linux-arm64': 0.18.16 - '@esbuild/linux-ia32': 0.18.16 - '@esbuild/linux-loong64': 0.18.16 - '@esbuild/linux-mips64el': 0.18.16 - '@esbuild/linux-ppc64': 0.18.16 - '@esbuild/linux-riscv64': 0.18.16 - '@esbuild/linux-s390x': 0.18.16 - '@esbuild/linux-x64': 0.18.16 - '@esbuild/netbsd-x64': 0.18.16 - '@esbuild/openbsd-x64': 0.18.16 - '@esbuild/sunos-x64': 0.18.16 - '@esbuild/win32-arm64': 0.18.16 - '@esbuild/win32-ia32': 0.18.16 - '@esbuild/win32-x64': 0.18.16 - dev: true - - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} - /focus-trap@7.5.2: - resolution: {integrity: sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==} - dependencies: - tabbable: 6.2.0 - dev: true + algoliasearch@5.56.0: + resolution: {integrity: sha512-PrqppUmhT4ENdas2pH9caE7efUcxy6EcSFhWzosiVuQBzu2tQ5yLTI6jwomT/1cuBnivzGfxiJCqDNN9FRRh+Q==} + engines: {node: '>= 14.0.0'} - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} - /magic-string@0.30.1: - resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /mark.js@8.11.1: - resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} - dev: true + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - /minisearch@6.1.0: - resolution: {integrity: sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==} - dev: true + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + autoprefixer@10.5.4: + resolution: {integrity: sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + baseline-browser-mapping@2.11.11: + resolution: {integrity: sha512-/yImnXwyTvgMkhgekLHok/Rx5vO6E0BmStWlSqKWMVm2a2ITuZ1Tn+9bgLS+gZRdZmWtd8nxuhHpdmCUOWsTQQ==} + engines: {node: '>=6.0.0'} hasBin: true - dev: true - /nprogress@0.2.0: - resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} - dev: true + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} - /postcss@8.4.27: - resolution: {integrity: sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: true + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - /preact@10.13.2: - resolution: {integrity: sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==} - dev: true + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} - /rollup@3.28.0: - resolution: {integrity: sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - optionalDependencies: - fsevents: 2.3.2 - dev: true - /shiki@0.14.3: - resolution: {integrity: sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==} - dependencies: - ansi-sequence-parser: 1.1.0 - jsonc-parser: 3.2.0 - vscode-oniguruma: 1.7.0 - vscode-textmate: 8.0.0 - dev: true + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} - /tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - dev: true + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} - dev: true + hasBin: true + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} - /vite@4.4.9(@types/node@18.14.6): - resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} - engines: {node: ^14.18.0 || >=16.0.0} + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.399: + resolution: {integrity: sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==} + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + focus-trap@7.8.0: + resolution: {integrity: sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.3.12: + resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + immutable@5.1.9: + resolution: {integrity: sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + + minisearch@7.2.0: + resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + oniguruma-to-es@3.1.1: + resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.0.1: + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.13.2: + resolution: {integrity: sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==} + + property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup@4.21.0: + resolution: {integrity: sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sass@1.102.0: + resolution: {integrity: sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==} + engines: {node: '>=20.19.0'} + hasBin: true + + search-insights@2.17.0: + resolution: {integrity: sha512-AskayU3QNsXQzSL6v4LTYST7NNfs2HWyHHB+sdORP9chsytAhro5XRfToAMI/LAVYgNbzowVZTMfBRodgbUHKg==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@2.5.0: + resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tabbable@6.5.0: + resolution: {integrity: sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==} + + tailwindcss@3.4.14: + resolution: {integrity: sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - '@types/node': '>= 14' + '@types/node': ^18.0.0 || >=20.0.0 less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -790,59 +1280,1315 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: optional: true terser: optional: true + + vitepress-plugin-nprogress@0.1.1: + resolution: {integrity: sha512-rpiFJjAUkF2judTaqfk36L+Y8mJxoHWgkUgp2HMBGIfy60HDADGSxgIPQ//bpsSLdtiRq+YPKugYXl+Yr03Pfw==} + + vitepress-plugin-tabs@0.9.1: + resolution: {integrity: sha512-cRys9pWhyl5YnxXZ3BAdSDW8DriuXBewYhmUu4bBlnzksEDjzbKUwbNi30T74Vi1UXnY1a19Ap6DJDTOWJWdzA==} + peerDependencies: + vitepress: ^1.0.0 || ^2.0.0-alpha.17 + vue: ^3.5.0 + + vitepress@1.6.4: + resolution: {integrity: sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==} + hasBin: true + peerDependencies: + markdown-it-mathjax3: ^4 + postcss: ^8 + peerDependenciesMeta: + markdown-it-mathjax3: + optional: true + postcss: + optional: true + + vue@3.5.40: + resolution: {integrity: sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + yaml@2.4.1: + resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + engines: {node: '>= 14'} + hasBin: true + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@algolia/abtesting@1.22.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)(search-insights@2.17.0)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)(search-insights@2.17.0) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)(search-insights@2.17.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + search-insights: 2.17.0 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@algolia/client-search': 5.56.0 + algoliasearch: 5.56.0 + + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)': + dependencies: + '@algolia/client-search': 5.56.0 + algoliasearch: 5.56.0 + + '@algolia/client-abtesting@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-analytics@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-common@5.56.0': {} + + '@algolia/client-insights@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-personalization@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-query-suggestions@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/client-search@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/ingestion@1.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/monitoring@1.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/recommend@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + '@algolia/requester-browser-xhr@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + + '@algolia/requester-fetch@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + + '@algolia/requester-node-http@5.56.0': + dependencies: + '@algolia/client-common': 5.56.0 + + '@alloc/quick-lru@5.2.0': {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@docsearch/css@3.8.2': {} + + '@docsearch/js@3.8.2(@algolia/client-search@5.56.0)(search-insights@2.17.0)': + dependencies: + '@docsearch/react': 3.8.2(@algolia/client-search@5.56.0)(search-insights@2.17.0) + preact: 10.13.2 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + + '@docsearch/react@3.8.2(@algolia/client-search@5.56.0)(search-insights@2.17.0)': + dependencies: + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0)(search-insights@2.17.0) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.56.0)(algoliasearch@5.56.0) + '@docsearch/css': 3.8.2 + algoliasearch: 5.56.0 + optionalDependencies: + search-insights: 2.17.0 + transitivePeerDependencies: + - '@algolia/client-search' + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@iconify-json/simple-icons@1.2.93': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@parcel/watcher-android-arm64@2.5.0': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.0': + optional: true + + '@parcel/watcher-darwin-x64@2.5.0': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.0': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.0': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.0': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.0': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.0': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.0': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.0': + optional: true + + '@parcel/watcher-win32-arm64@2.5.0': + optional: true + + '@parcel/watcher-win32-ia32@2.5.0': + optional: true + + '@parcel/watcher-win32-x64@2.5.0': + optional: true + + '@parcel/watcher@2.5.0': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.5 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.0 + '@parcel/watcher-darwin-arm64': 2.5.0 + '@parcel/watcher-darwin-x64': 2.5.0 + '@parcel/watcher-freebsd-x64': 2.5.0 + '@parcel/watcher-linux-arm-glibc': 2.5.0 + '@parcel/watcher-linux-arm-musl': 2.5.0 + '@parcel/watcher-linux-arm64-glibc': 2.5.0 + '@parcel/watcher-linux-arm64-musl': 2.5.0 + '@parcel/watcher-linux-x64-glibc': 2.5.0 + '@parcel/watcher-linux-x64-musl': 2.5.0 + '@parcel/watcher-win32-arm64': 2.5.0 + '@parcel/watcher-win32-ia32': 2.5.0 + '@parcel/watcher-win32-x64': 2.5.0 + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.21.0': + optional: true + + '@rollup/rollup-android-arm64@4.21.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.21.0': + optional: true + + '@rollup/rollup-darwin-x64@4.21.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.21.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.21.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.21.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.21.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.21.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.21.0': + optional: true + + '@shikijs/core@2.5.0': + dependencies: + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 3.1.1 + + '@shikijs/engine-oniguruma@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/themes@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/transformers@2.5.0': + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/types': 2.5.0 + + '@shikijs/types@2.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@types/estree@1.0.5': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0': {} + + '@types/node@20.17.6': + dependencies: + undici-types: 6.19.8 + + '@types/unist@3.0.3': {} + + '@types/web-bluetooth@0.0.21': {} + + '@ungap/structured-clone@1.2.0': {} + + '@vitejs/plugin-vue@5.2.4(vite@5.4.21(@types/node@20.17.6)(sass@1.102.0))(vue@3.5.40)': + dependencies: + vite: 5.4.21(@types/node@20.17.6)(sass@1.102.0) + vue: 3.5.40 + + '@vue/compiler-core@3.5.40': + dependencies: + '@babel/parser': 7.29.8 + '@vue/shared': 3.5.40 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.40': + dependencies: + '@vue/compiler-core': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/compiler-sfc@3.5.40': + dependencies: + '@babel/parser': 7.29.8 + '@vue/compiler-core': 3.5.40 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-ssr': 3.5.40 + '@vue/shared': 3.5.40 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.25 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.40': + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/devtools-api@7.7.10': + dependencies: + '@vue/devtools-kit': 7.7.10 + + '@vue/devtools-kit@7.7.10': + dependencies: + '@vue/devtools-shared': 7.7.10 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-shared@7.7.10': + dependencies: + rfdc: 1.4.1 + + '@vue/reactivity@3.5.40': + dependencies: + '@vue/shared': 3.5.40 + + '@vue/runtime-core@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/runtime-dom@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/runtime-core': 3.5.40 + '@vue/shared': 3.5.40 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.40': + dependencies: + '@vue/compiler-ssr': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/shared@3.5.40': {} + + '@vueuse/core@12.8.2': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2 + vue: 3.5.40 + transitivePeerDependencies: + - typescript + + '@vueuse/integrations@12.8.2(focus-trap@7.8.0)(nprogress@0.2.0)': + dependencies: + '@vueuse/core': 12.8.2 + '@vueuse/shared': 12.8.2 + vue: 3.5.40 + optionalDependencies: + focus-trap: 7.8.0 + nprogress: 0.2.0 + transitivePeerDependencies: + - typescript + + '@vueuse/metadata@12.8.2': {} + + '@vueuse/shared@12.8.2': + dependencies: + vue: 3.5.40 + transitivePeerDependencies: + - typescript + + algoliasearch@5.56.0: + dependencies: + '@algolia/abtesting': 1.22.0 + '@algolia/client-abtesting': 5.56.0 + '@algolia/client-analytics': 5.56.0 + '@algolia/client-common': 5.56.0 + '@algolia/client-insights': 5.56.0 + '@algolia/client-personalization': 5.56.0 + '@algolia/client-query-suggestions': 5.56.0 + '@algolia/client-search': 5.56.0 + '@algolia/ingestion': 1.56.0 + '@algolia/monitoring': 1.56.0 + '@algolia/recommend': 5.56.0 + '@algolia/requester-browser-xhr': 5.56.0 + '@algolia/requester-fetch': 5.56.0 + '@algolia/requester-node-http': 5.56.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + autoprefixer@10.5.4(postcss@8.5.25): + dependencies: + browserslist: 4.28.7 + caniuse-lite: 1.0.30001806 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.25 + postcss-value-parser: 4.2.0 + + balanced-match@1.0.2: {} + + baseline-browser-mapping@2.11.11: {} + + binary-extensions@2.2.0: {} + + birpc@2.9.0: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.2: + dependencies: + fill-range: 7.0.1 + + browserslist@4.28.7: + dependencies: + baseline-browser-mapping: 2.11.11 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.399 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.7) + + camelcase-css@2.0.1: {} + + caniuse-lite@1.0.30001806: {} + + ccount@2.0.1: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + chokidar@3.5.3: + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + comma-separated-tokens@2.0.3: {} + + commander@4.1.1: {} + + copy-anything@4.0.5: + dependencies: + is-what: 5.5.0 + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + csstype@3.2.3: {} + + dequal@2.0.3: {} + + detect-libc@1.0.3: + optional: true + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.399: {} + + emoji-regex-xs@1.0.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + entities@7.0.1: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + estree-walker@2.0.2: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.0.1: + dependencies: + to-regex-range: 5.0.1 + + focus-trap@7.8.0: + dependencies: + tabbable: 6.5.0 + + foreground-child@3.1.1: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + fraction.js@5.3.4: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.3.12: + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.4 + minipass: 7.0.4 + path-scurry: 1.10.2 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 7.2.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hookable@5.5.3: {} + + html-void-elements@3.0.0: {} + + immutable@5.1.9: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.2.0 + + is-core-module@2.13.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-what@5.5.0: {} + + isexe@2.0.0: {} + + jackspeak@2.3.6: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.0: {} + + lilconfig@2.1.0: {} + + lilconfig@3.1.1: {} + + lines-and-columns@1.2.4: {} + + lru-cache@10.2.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mark.js@8.11.1: {} + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + merge2@1.4.1: {} + + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-encode@2.0.0: {} + + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + + micromark-util-symbol@2.0.0: {} + + micromark-util-types@2.0.0: {} + + micromatch@4.0.5: + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + minimatch@9.0.4: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.0.4: {} + + minisearch@7.2.0: {} + + mitt@3.0.1: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.16: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.51: {} + + normalize-path@3.0.0: {} + + nprogress@0.2.0: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + oniguruma-to-es@3.1.1: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 6.1.0 + regex-recursion: 6.0.2 + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.10.2: + dependencies: + lru-cache: 10.2.0 + minipass: 7.0.4 + + perfect-debounce@1.0.0: {} + + picocolors@1.0.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + + postcss-import@15.1.0(postcss@8.5.25): + dependencies: + postcss: 8.5.25 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.5.25): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.25 + + postcss-load-config@4.0.2(postcss@8.5.25): + dependencies: + lilconfig: 3.1.1 + yaml: 2.4.1 + optionalDependencies: + postcss: 8.5.25 + + postcss-nested@6.0.1(postcss@8.5.25): + dependencies: + postcss: 8.5.25 + postcss-selector-parser: 6.0.16 + + postcss-selector-parser@6.0.16: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.25: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.13.2: {} + + property-information@7.2.0: {} + + queue-microtask@1.2.3: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@5.0.0: {} + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + resolve@1.22.8: + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rfdc@1.4.1: {} + + rollup@4.21.0: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.21.0 + '@rollup/rollup-android-arm64': 4.21.0 + '@rollup/rollup-darwin-arm64': 4.21.0 + '@rollup/rollup-darwin-x64': 4.21.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.0 + '@rollup/rollup-linux-arm-musleabihf': 4.21.0 + '@rollup/rollup-linux-arm64-gnu': 4.21.0 + '@rollup/rollup-linux-arm64-musl': 4.21.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.0 + '@rollup/rollup-linux-riscv64-gnu': 4.21.0 + '@rollup/rollup-linux-s390x-gnu': 4.21.0 + '@rollup/rollup-linux-x64-gnu': 4.21.0 + '@rollup/rollup-linux-x64-musl': 4.21.0 + '@rollup/rollup-win32-arm64-msvc': 4.21.0 + '@rollup/rollup-win32-ia32-msvc': 4.21.0 + '@rollup/rollup-win32-x64-msvc': 4.21.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + sass@1.102.0: + dependencies: + chokidar: 5.0.0 + immutable: 5.1.9 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.0 + + search-insights@2.17.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shiki@2.5.0: + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/langs': 2.5.0 + '@shikijs/themes': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + signal-exit@4.1.0: {} + + source-map-js@1.2.1: {} + + space-separated-tokens@2.0.2: {} + + speakingurl@14.0.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.3.12 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + superjson@2.2.6: + dependencies: + copy-anything: 4.0.5 + + supports-preserve-symlinks-flag@1.0.0: {} + + tabbable@6.5.0: {} + + tailwindcss@3.4.14: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.1 + postcss: 8.5.25 + postcss-import: 15.1.0(postcss@8.5.25) + postcss-js: 4.0.1(postcss@8.5.25) + postcss-load-config: 4.0.2(postcss@8.5.25) + postcss-nested: 6.0.1(postcss@8.5.25) + postcss-selector-parser: 6.0.16 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + trim-lines@3.0.1: {} + + ts-interface-checker@0.1.13: {} + + undici-types@6.19.8: {} + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + update-browserslist-db@1.2.3(browserslist@4.28.7): + dependencies: + browserslist: 4.28.7 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: {} + + vfile-message@4.0.2: dependencies: - '@types/node': 18.14.6 - esbuild: 0.18.16 - postcss: 8.4.27 - rollup: 3.28.0 + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite@5.4.21(@types/node@20.17.6)(sass@1.102.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.25 + rollup: 4.21.0 optionalDependencies: - fsevents: 2.3.2 - dev: true + '@types/node': 20.17.6 + fsevents: 2.3.3 + sass: 1.102.0 - /vitepress-plugin-nprogress@0.0.4: - resolution: {integrity: sha512-YzW36kBnjuFH91DOFIA5snyBf4WpF/cYfhAiyNefhqif8QQIKGsbpzvI8VN0M8RHLGr9iQyHhF7dQsm//Xf5Hw==} + vitepress-plugin-nprogress@0.1.1: dependencies: nprogress: 0.2.0 - dev: true - /vitepress-plugin-tabs@0.2.0(vitepress@1.0.0-rc.4)(vue@3.3.4): - resolution: {integrity: sha512-jTdtz4Z5fHllzcDAJaJK/bxE/2PhJSqetFUFgiB7xzw23O4yI+ntJrN+D3oP8XH/0559QUbrYd0K3YLoRaHbAA==} - peerDependencies: - vitepress: ^1.0.0-alpha.29 - vue: ^3.2.45 + vitepress-plugin-tabs@0.9.1(vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@20.17.6)(nprogress@0.2.0)(postcss@8.5.25)(sass@1.102.0)(search-insights@2.17.0))(vue@3.5.40): dependencies: - vitepress: 1.0.0-rc.4(@types/node@18.14.6) - vue: 3.3.4 - dev: true + vitepress: 1.6.4(@algolia/client-search@5.56.0)(@types/node@20.17.6)(nprogress@0.2.0)(postcss@8.5.25)(sass@1.102.0)(search-insights@2.17.0) + vue: 3.5.40 - /vitepress@1.0.0-rc.4(@types/node@18.14.6): - resolution: {integrity: sha512-JCQ89Bm6ECUTnyzyas3JENo00UDJeK8q1SUQyJYou+4Yz5BKEc/F3O21cu++DnUT2zXc0kvQ2Aj4BZCc/nioXQ==} - hasBin: true + vitepress@1.6.4(@algolia/client-search@5.56.0)(@types/node@20.17.6)(nprogress@0.2.0)(postcss@8.5.25)(sass@1.102.0)(search-insights@2.17.0): dependencies: - '@docsearch/css': 3.5.1 - '@docsearch/js': 3.5.1 - '@vitejs/plugin-vue': 4.2.3(vite@4.4.9)(vue@3.3.4) - '@vue/devtools-api': 6.5.0 - '@vueuse/core': 10.3.0(vue@3.3.4) - '@vueuse/integrations': 10.3.0(focus-trap@7.5.2)(vue@3.3.4) - body-scroll-lock: 4.0.0-beta.0 - focus-trap: 7.5.2 + '@docsearch/css': 3.8.2 + '@docsearch/js': 3.8.2(@algolia/client-search@5.56.0)(search-insights@2.17.0) + '@iconify-json/simple-icons': 1.2.93 + '@shikijs/core': 2.5.0 + '@shikijs/transformers': 2.5.0 + '@shikijs/types': 2.5.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.2.4(vite@5.4.21(@types/node@20.17.6)(sass@1.102.0))(vue@3.5.40) + '@vue/devtools-api': 7.7.10 + '@vue/shared': 3.5.40 + '@vueuse/core': 12.8.2 + '@vueuse/integrations': 12.8.2(focus-trap@7.8.0)(nprogress@0.2.0) + focus-trap: 7.8.0 mark.js: 8.11.1 - minisearch: 6.1.0 - shiki: 0.14.3 - vite: 4.4.9(@types/node@18.14.6) - vue: 3.3.4 + minisearch: 7.2.0 + shiki: 2.5.0 + vite: 5.4.21(@types/node@20.17.6)(sass@1.102.0) + vue: 3.5.40 + optionalDependencies: + postcss: 8.5.25 transitivePeerDependencies: - '@algolia/client-search' - '@types/node' - '@types/react' - - '@vue/composition-api' - async-validator - axios - change-case @@ -857,43 +2603,39 @@ packages: - react - react-dom - sass + - sass-embedded - search-insights - sortablejs - stylus - sugarss - terser + - typescript - universal-cookie - dev: true - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - dev: true + vue@3.5.40: + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-sfc': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/server-renderer': 3.5.40 + '@vue/shared': 3.5.40 - /vscode-textmate@8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - dev: true + which@2.0.2: + dependencies: + isexe: 2.0.0 - /vue-demi@0.14.5(vue@3.3.4): - resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true + wrap-ansi@7.0.0: dependencies: - vue: 3.3.4 - dev: true + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 - /vue@3.3.4: - resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} + wrap-ansi@8.1.0: dependencies: - '@vue/compiler-dom': 3.3.4 - '@vue/compiler-sfc': 3.3.4 - '@vue/runtime-dom': 3.3.4 - '@vue/server-renderer': 3.3.4(vue@3.3.4) - '@vue/shared': 3.3.4 - dev: true + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + yaml@2.4.1: {} + + zwitch@2.0.4: {} diff --git a/public/Pengu_Featherknight_144.jpg b/public/Pengu_Featherknight_144.jpg deleted file mode 100644 index e9a8707..0000000 Binary files a/public/Pengu_Featherknight_144.jpg and /dev/null differ diff --git a/public/PenguLoader.png b/public/icon.png similarity index 100% rename from public/PenguLoader.png rename to public/icon.png diff --git a/public/icons/4216.jpg b/public/icons/4216.jpg new file mode 100644 index 0000000..eba1034 Binary files /dev/null and b/public/icons/4216.jpg differ diff --git a/public/icons/4274.jpg b/public/icons/4274.jpg new file mode 100644 index 0000000..6ea6b68 Binary files /dev/null and b/public/icons/4274.jpg differ diff --git a/public/images/visual-acrylic.png b/public/images/visual-acrylic.png new file mode 100644 index 0000000..321422c Binary files /dev/null and b/public/images/visual-acrylic.png differ diff --git a/public/images/visual-blurbehind.png b/public/images/visual-blurbehind.png new file mode 100644 index 0000000..6036028 Binary files /dev/null and b/public/images/visual-blurbehind.png differ diff --git a/public/images/visual-transparent.png b/public/images/visual-transparent.png new file mode 100644 index 0000000..979de89 Binary files /dev/null and b/public/images/visual-transparent.png differ diff --git a/public/lol-banner.png b/public/lol-banner.png new file mode 100644 index 0000000..f5e0183 Binary files /dev/null and b/public/lol-banner.png differ diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..70d13ef --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,81 @@ +import { Config } from 'tailwindcss' + +export default { + darkMode: 'class', + content: [ + './.vitepress/**/*.{ts,vue}', + './docs/**/*.md', + ], + theme: { + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px', + }, + }, + extend: { + // fontFamily: { + // sans: ["var(--font-sans)", ...fontFamily.sans], + // }, + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', + }, + 'primary-highlight': { + DEFAULT: 'hsl(var(--primary-highlight))', + foreground: 'hsl(var(--primary-highlight-foreground))', + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', + }, + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' }, + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' }, + }, + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', + }, + }, + }, +} as Config