diff --git a/.env.example b/.env.example deleted file mode 100644 index da95031de..000000000 --- a/.env.example +++ /dev/null @@ -1,25 +0,0 @@ -# Monochrome Docker Configuration -# Copy to .env and edit: cp .env.example .env - -# --- Monochrome --- -MONOCHROME_PORT=3000 -MONOCHROME_DEV_PORT=5173 - -# --- Auth Gate (server-side authentication) --- -# Set AUTH_ENABLED=true to enable the auth gate entirely (login required) -AUTH_ENABLED=false -AUTH_SECRET=change-me-to-a-random-string -APPWRITE_ENDPOINT=https://auth.yourdomain.com/v1 -APPWRITE_PROJECT_ID=auth-for-monochrome -# Optional: toggle login providers (defaults to true when unset) -# AUTH_GOOGLE_ENABLED=true -# AUTH_EMAIL_ENABLED=true -# Optional: set PocketBase URL (hides the field in settings when set) -# POCKETBASE_URL=https://monodb.samidy.com -# SESSION_MAX_AGE=604800000 # 7 days in ms (default) - -# --- PocketBase (only used with --profile pocketbase) --- -POCKETBASE_PORT=8090 -PB_ADMIN_EMAIL=admin@example.com -PB_ADMIN_PASSWORD=changeme -TZ=UTC diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f33a02cd1..f6401cb08 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,7 +6,7 @@ version: 2 updates: - - package-ecosystem: "devcontainers" - directory: "/" - schedule: - interval: weekly + - package-ecosystem: 'devcontainers' + directory: '/' + schedule: + interval: weekly diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a7b191901..516b72d96 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,19 @@ ### Description + ### Type of Change + - [ ] Bug fix - [ ] New feature - [ ] Style/UI update - [ ] Docs only ### Checklist + - [ ] **I have read the [Contributing Guidelines](https://github.com/monochrome-music/monochrome/blob/main/CONTRIBUTING.md).** - [ ] **I understand every line of code I am submitting.** - [ ] I have tested these changes locally, and they work as expected. +- [ ] Is this Pull request Using AI/Is Vibecoded? --- -*By submitting this PR, I agree to follow the guidelines. I understand that the final decision to merge rests with the maintainers and that not all contributions can be accepted.* \ No newline at end of file + +_By submitting this PR, I agree to follow the guidelines. I understand that the final decision to merge rests with the maintainers and that not all contributions can be accepted._ diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fd0235d25..c7f29d019 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,23 +1,25 @@ name: Lint Codebase on: - push: - branches: [main] - pull_request: - branches: [main] + push: + branches: [main] + pull_request: + branches: [main] permissions: - contents: write + contents: write + actions: write jobs: - lint: - runs-on: ubuntu-latest + lint: + runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 1 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 1 + ref: ${{ github.head_ref || github.ref }} - name: Setup Node uses: actions/setup-node@v4 @@ -40,13 +42,12 @@ jobs: run: npm run format continue-on-error: true - - name: Commit and Push lint fixes - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: 'style: auto-fix linting issues' - commit_user_name: 'github-actions[bot]' - commit_user_email: 'github-actions[bot]@users.noreply.github.com' - only_if_changed: true + - name: Commit and Push lint fixes + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: 'style: auto-fix linting issues' + commit_user_name: 'github-actions[bot]' + commit_user_email: 'github-actions[bot]@users.noreply.github.com' - name: Run HTML Lint run: npm run lint:html diff --git a/.github/workflows/update-lockfile.yml b/.github/workflows/update-lockfile.yml index db5d39f5d..73be2b4bd 100644 --- a/.github/workflows/update-lockfile.yml +++ b/.github/workflows/update-lockfile.yml @@ -1,43 +1,43 @@ name: Update Lock File on: - workflow_dispatch: + workflow_dispatch: permissions: - contents: write + contents: write jobs: - update-lock: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Configure Git - uses: DanTheMan827/config-git-user-action@v1 - - - name: Setup Bun - uses: oven-sh/setup-bun@v1 - with: - bun-version: latest - - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: | - ./bun_modules - ./node_modules - ./bun.lock - key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - - - name: Install dependencies - run: bun install - - - name: Commit changes - run: | - git add -A . || true - git commit "update lockfile" || true - git push || true + update-lock: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Configure Git + uses: DanTheMan827/config-git-user-action@v1 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: | + ./bun_modules + ./node_modules + ./bun.lock + key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} + + - name: Install dependencies + run: bun install + + - name: Commit changes + run: | + git add -A . || true + git commit "update lockfile" || true + git push || true diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/.htmlhintignore b/.htmlhintignore deleted file mode 100644 index 2730e75e1..000000000 --- a/.htmlhintignore +++ /dev/null @@ -1,3 +0,0 @@ -dist/ -node_modules/ -legacy/ diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index df8a97bbc..000000000 --- a/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -dist/ -node_modules/ -legacy/ -package-lock.json -*.min.js -.github/ \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 693875458..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "build", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "label": "npm: build", - "detail": "vite build" - }, - { - "type": "npm", - "script": "dev", - "problemMatcher": [], - "label": "npm: dev", - "detail": "vite" - } - ] -} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dfa1305cb..1e916cc0d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,6 @@ Thank you for your interest in contributing to Monochrome! This guide will help - [Contributing Workflow](#contributing-workflow) - [Commit Message Guidelines](#commit-message-guidelines) - [Deployment](#deployment) -- [Questions?](#questions) --- @@ -100,9 +99,6 @@ npm run build native ``` monochrome/ β”œβ”€β”€ πŸ“ js/ # Application source code -β”‚ β”œβ”€β”€ components/ # UI components -β”‚ β”œβ”€β”€ utils/ # Utility functions -β”‚ β”œβ”€β”€ api/ # API integration β”‚ └── ... β”œβ”€β”€ πŸ“ public/ # Static assets β”‚ β”œβ”€β”€ assets/ # Images, icons, fonts @@ -207,7 +203,7 @@ Follow our [commit message guidelines](#commit-message-guidelines). ```bash git add . -git commit -m "feat(player): add keyboard shortcut for loop toggle" +git commit -m "feat(player): add keyboard shortcut for loop toggle" # example commit message ``` ### 5. Push and Create a Pull Request @@ -309,7 +305,7 @@ Deployment is fully automated via **Cloudflare Pages**. 1. Push changes to the `main` branch 2. Cloudflare automatically builds and deploys -3. Changes are live within minutes +3. Changes are live a minute ### Configuration Notes diff --git a/Dockerfile b/Dockerfile index 381ed9268..ba64b418f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Node Alpine -- multi-arch (amd64 + arm64) -FROM node:lts-alpine +FROM oven/bun:1.3.10-alpine AS builder WORKDIR /app @@ -7,11 +7,13 @@ WORKDIR /app RUN apk add --no-cache wget curl bash RUN apk add --no-cache python3 make g++ && ln -sf python3 /usr/bin/python -# Install Bun -RUN curl -fsSL https://bun.sh/install | bash - -# Add Bun to PATH so it can be used in subsequent steps -ENV PATH="/root/.bun/bin:${PATH}" +# Accept build arguments for environment variables +ARG AUTH_ENABLED +ARG AUTH_SECRET +ARG APPWRITE_ENDPOINT +ARG APPWRITE_PROJECT_ID +ARG POCKETBASE_URL +ARG SESSION_MAX_AGE # Copy package files first for caching COPY package.json package-lock.json ./ @@ -25,8 +27,14 @@ COPY . . # Build the project RUN bun run build -# Expose Vite preview port +# Serve with nginx +FROM nginx:1.28.2-alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Expose the nginx port EXPOSE 4173 -# Run the built project -CMD ["bun", "run", "preview", "--", "--host", "0.0.0.0"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/INSTANCES.md b/INSTANCES.md index 1e92790ab..3fac04f17 100644 --- a/INSTANCES.md +++ b/INSTANCES.md @@ -12,69 +12,36 @@ The official Monochrome instance maintained by the core team: | ------------------------------------------------------ | -------- | ---------------- | | [monochrome.tf](https://monochrome.tf) | Official | Primary instance | | [monochrome.samidy.com](https://monochrome.samidy.com) | Official | Secondary mirror | +| [lossless.wtf](https://lossless.wtf) | Official | Failover mirror | --- ## Community Instances -### Community Monochrome Instances - -These instances are community instances of Monochrome & its WebUI: - -| Provider | URL | Status | -| ------------- | ---------------------------------------- | --------- | -| **Squid.WTF** | [mono.squid.wtf](https://mono.squid.wtf) | Community | - -### UI-Only Instances - -These instances provide the tidal-ui web interface, not monochrome: - -| Provider | URL | Status | -| ------------------- | ---------------------------------------------- | --------- | -| **bini (tidal-ui)** | [music.binimum.org](https://music.binimum.org) | Community | -| **squid.wtf** | [tidal.squid.wtf](https://tidal.squid.wtf) | Community | -| **QQDL** | [tidal.qqdl.site](https://tidal.qqdl.site/) | Community | - ---- +PLEASE do not use any rehost of monochrome and complain to us about features not working. They are usually out of date, and do not provide the latest features, and accounts are always broken. ## API Instances Monochrome uses the Hi-Fi API under the hood. Live, up-to-date status trackers (which return JSON) can be found below: -- https://tidal-uptime.jiffy-puffs-1j.workers.dev/ -- https://tidal-uptime.props-76styles.workers.dev/ +- [https://tidal-uptime.jiffy-puffs-1j.workers.dev](https://tidal-uptime.jiffy-puffs-1j.workers.dev/) +- [https://tidal-uptime.props-76styles.workers.dev](https://tidal-uptime.props-76styles.workers.dev/) These are available API endpoints that can be used with Monochrome or other Hi-Fi based applications: ### Official & Community APIs -| Provider | URL | Notes | -| ----------------- | ----------------------------------- | ---------------- | -| **Monochrome** | `https://monochrome-api.samidy.com` | Official API | -| | `https://api.monochrome.tf` | Official API | -| | `https://arran.monochrome.tf` | Official API | -| **squid.wtf** | `https://triton.squid.wtf` | Community hosted | -| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted | -| | `https://maus.qqdl.site` | Community hosted | -| | `https://vogel.qqdl.site` | Community hosted | -| | `https://katze.qqdl.site` | Community hosted | -| | `https://hund.qqdl.site` | Community hosted | -| **Spotisaver** | `https://hifi-one.spotisaver.net` | Community hosted | -| | `https://hifi-two.spotisaver.net` | Community hosted | -| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted | -| **Binimum** | `https://tidal-api.binimum.org` | Community hosted | - ---- - -## Instance Health - -To check the current status of instances: - -1. Visit the instance URL in your browser -2. Check if the page loads correctly -3. Try playing a track to verify API connectivity - -> **Note:** Community instances may have varying uptime and performance. If one doesn't work, try another. +| Provider | URL | Notes | +| ----------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------ | +| **Monochrome** | `https://monochrome-api.samidy.com` | Official API | +| | `https://api.monochrome.tf` | Official API | +| **geeked.wtf** | `https://hifi.geeked.wtf` | Community hosted - uses the [TypeScript Rewrite](https://github.com/monochrome-music/hifi-api-workers) | +| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted | +| | `https://maus.qqdl.site` | Community hosted | +| | `https://vogel.qqdl.site` | Community hosted | +| | `https://katze.qqdl.site` | Community hosted | +| | `https://hund.qqdl.site` | Community hosted | +| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted - [Limited/No-Sub](https://rentry.co/limitedtidalaccs) | --- @@ -103,5 +70,5 @@ Want to add your instance to this list? ## Related Resources -- [Contributing Guide](CONTRIBUTE.md) - Contribute to the project +- [Contributing Guide](CONTRIBUTING.md) - Contribute to the project - [Main Repository](https://github.com/monochrome-music/monochrome) - Source code diff --git a/README.md b/README.md index fe3982c26..fc9c41ffc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

Monochrome Logo @@ -41,7 +41,7 @@ Build instructions will be coming soon ## What is Monochrome? -**Monochrome** is an open-source, privacy-respecting, ad-free [TIDAL](https://tidal.com) web UI, built on top of [Hi-Fi](https://github.com/binimum/hifi-api). It provides a beautiful, minimalist interface for streaming high-quality music without the clutter of traditional streaming platforms. +**Monochrome** is an open-source, privacy-respecting, ad-free [TIDAL](https://tidal.com) web UI, built on top of Hi-Fi. It provides a beautiful, minimalist interface for streaming high-quality music without the clutter of traditional streaming platforms.

@@ -80,6 +80,7 @@ Build instructions will be coming soon - Recently Played tracking for easy history access - Comprehensive Personal Library for favorites - Queue management with shuffle and repeat modes +- Native Podcast support & organization - Playlist import from other platforms - Public playlists for social sharing - Smart recommendations for new songs, albums & artists @@ -114,7 +115,7 @@ Build instructions will be coming soon Our Recommended way to use monochrome is through our official instance: -**[monochrome.tf](https://monochrome.tf)** +**[monochrome.tf](https://monochrome.tf)** / **[monochrome.samidy.com](https://monochrome.samidy.com)** For alternative instances, check [INSTANCES.md](INSTANCES.md). @@ -283,6 +284,12 @@ We welcome contributions from the community! Please see our [Contributing Guide]

+

+ + Developed by Humans + +

+

Made with ❀️ by the Monochrome team

diff --git a/assets/icon-background.png b/assets/icon-background.png new file mode 100644 index 000000000..f60a68c04 Binary files /dev/null and b/assets/icon-background.png differ diff --git a/assets/icon-foreground.png b/assets/icon-foreground.png new file mode 100644 index 000000000..25c310043 Binary files /dev/null and b/assets/icon-foreground.png differ diff --git a/assets/icon-only.png b/assets/icon-only.png new file mode 100644 index 000000000..57e94e29f Binary files /dev/null and b/assets/icon-only.png differ diff --git a/assets/splash-dark.png b/assets/splash-dark.png new file mode 100644 index 000000000..2856aa51c Binary files /dev/null and b/assets/splash-dark.png differ diff --git a/assets/splash.png b/assets/splash.png new file mode 100644 index 000000000..855d85b04 Binary files /dev/null and b/assets/splash.png differ diff --git a/capacitor.config.ts b/capacitor.config.ts new file mode 100644 index 000000000..53c5d736d --- /dev/null +++ b/capacitor.config.ts @@ -0,0 +1,15 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'tf.monochrome.music', + appName: 'Monochrome Music', + webDir: 'dist', + assets: { + iconBackgroundColor: '#000000', + iconBackgroundColorDark: '#000000', + splashBackgroundColor: '#000000', + splashBackgroundColorDark: '#000000', + }, +}; + +export default config; diff --git a/docker-compose.yml b/docker-compose.yml index 02fe95e56..7bb5cdd12 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,21 +4,21 @@ services: build: context: . dockerfile: Dockerfile + args: + - AUTH_ENABLED=${AUTH_ENABLED} + - AUTH_SECRET=${AUTH_SECRET} + - APPWRITE_ENDPOINT=${APPWRITE_ENDPOINT} + - APPWRITE_PROJECT_ID=${APPWRITE_PROJECT_ID} + - POCKETBASE_URL=${POCKETBASE_URL} + - SESSION_MAX_AGE=${SESSION_MAX_AGE} container_name: monochrome ports: - '${MONOCHROME_PORT:-3000}:4173' - environment: - AUTH_ENABLED: ${AUTH_ENABLED:-false} - AUTH_SECRET: ${AUTH_SECRET:-} - APPWRITE_ENDPOINT: ${APPWRITE_ENDPOINT:-https://auth.yourdomain.com/v1} - APPWRITE_PROJECT_ID: ${APPWRITE_PROJECT_ID:-auth-for-monochrome} - POCKETBASE_URL: ${POCKETBASE_URL:-} - SESSION_MAX_AGE: ${SESSION_MAX_AGE:-604800000} restart: unless-stopped networks: - monochrome-network healthcheck: - test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:4173/health'] + test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:4173/'] interval: 30s timeout: 3s retries: 3 diff --git a/functions/album/[id].js b/functions/album/[id].js index 8a5e2a961..b75c0bf91 100644 --- a/functions/album/[id].js +++ b/functions/album/[id].js @@ -1,5 +1,50 @@ // functions/album/[id].js +class TidalAPI { + static CLIENT_ID = 'txNoH4kkV41MfH25'; + static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98='; + + async getToken() { + const params = new URLSearchParams({ + client_id: TidalAPI.CLIENT_ID, + client_secret: TidalAPI.CLIENT_SECRET, + grant_type: 'client_credentials', + }); + const res = await fetch('https://auth.tidal.com/v1/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`), + }, + body: params, + }); + if (!res.ok) throw new Error(`Token request failed: ${res.status}`); + const data = await res.json(); + return data.access_token; + } + + async fetchJson(url, params = {}) { + const token = await this.getToken(); + const u = new URL(url); + Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v))); + const res = await fetch(u.toString(), { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!res.ok) throw new Error(`Tidal API error: ${res.status}`); + return res.json(); + } + + async getAlbumMetadata(id) { + return await this.fetchJson(`https://api.tidal.com/v1/albums/${id}`, { countryCode: 'US' }); + } + + getCoverUrl(id, size = '1280') { + if (!id) return ''; + const formattedId = String(id).replace(/-/g, '/'); + return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`; + } +} + class ServerAPI { constructor() { this.INSTANCES_URLS = [ @@ -29,16 +74,16 @@ class ServerAPI { if (data) { this.apiInstances = (data.api || []) .map((item) => item.url || item) - .filter((url) => !url.includes('spotisaver.net')); + .filter((url) => !/\.squid\.wtf/i.test(url)); return this.apiInstances; } console.error('Failed to load instances from all uptime APIs'); return [ + 'https://hifi.geeked.wtf', 'https://eu-central.monochrome.tf', 'https://us-west.monochrome.tf', 'https://arran.monochrome.tf', - 'https://triton.squid.wtf', 'https://api.monochrome.tf', 'https://monochrome-api.samidy.com', 'https://maus.qqdl.site', @@ -92,19 +137,33 @@ class ServerAPI { export async function onRequest(context) { const { request, params, env } = context; const userAgent = request.headers.get('User-Agent') || ''; - const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test( - userAgent - ); + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); const albumId = params.id; if (isBot && albumId) { + let api; + let album; + let tracks = []; try { - const api = new ServerAPI(); - const data = await api.getAlbumMetadata(albumId); - const album = data.data || data.album || data; - const tracks = album.items || data.tracks || []; + api = new TidalAPI(); + album = await api.getAlbumMetadata(albumId); + } catch (directError) { + console.warn(`Direct Tidal API failed for album ${albumId}, falling back to proxies:`, directError); + try { + api = new ServerAPI(); + const data = await api.getAlbumMetadata(albumId); + album = data.data || data.album || data; + tracks = album.items || data.tracks || []; + } catch (fallbackError) { + console.error(`All methods failed for album ${albumId}:`, fallbackError); + } + } - if (album && (album.title || album.name)) { + if (album && (album.title || album.name)) { + try { const title = album.title || album.name; const artist = album.artist?.name || 'Unknown Artist'; const year = album.releaseDate ? new Date(album.releaseDate).getFullYear() : ''; @@ -124,7 +183,7 @@ export async function onRequest(context) { ${title} - + @@ -133,7 +192,7 @@ export async function onRequest(context) { - + @@ -148,9 +207,9 @@ export async function onRequest(context) { `; return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } catch (error) { + console.error(`Error generating meta tags for album ${albumId}:`, error); } - } catch (error) { - console.error(`Error for album ${albumId}:`, error); } } diff --git a/functions/artist/[id].js b/functions/artist/[id].js index 985e2f87b..1c625913f 100644 --- a/functions/artist/[id].js +++ b/functions/artist/[id].js @@ -1,5 +1,50 @@ // functions/artist/[id].js +class TidalAPI { + static CLIENT_ID = 'txNoH4kkV41MfH25'; + static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98='; + + async getToken() { + const params = new URLSearchParams({ + client_id: TidalAPI.CLIENT_ID, + client_secret: TidalAPI.CLIENT_SECRET, + grant_type: 'client_credentials', + }); + const res = await fetch('https://auth.tidal.com/v1/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`), + }, + body: params, + }); + if (!res.ok) throw new Error(`Token request failed: ${res.status}`); + const data = await res.json(); + return data.access_token; + } + + async fetchJson(url, params = {}) { + const token = await this.getToken(); + const u = new URL(url); + Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v))); + const res = await fetch(u.toString(), { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!res.ok) throw new Error(`Tidal API error: ${res.status}`); + return res.json(); + } + + async getArtistMetadata(id) { + return await this.fetchJson(`https://api.tidal.com/v1/artists/${id}`, { countryCode: 'US' }); + } + + getArtistPictureUrl(id, size = '750') { + if (!id) return ''; + const formattedId = id.replace(/-/g, '/'); + return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`; + } +} + class ServerAPI { constructor() { this.INSTANCES_URLS = [ @@ -27,9 +72,7 @@ class ServerAPI { } if (data) { - this.apiInstances = (data.api || []) - .map((item) => item.url || item) - .filter((url) => !url.includes('spotisaver.net')); + this.apiInstances = (data.api || []).map((item) => item.url || item); return this.apiInstances; } @@ -92,18 +135,31 @@ class ServerAPI { export async function onRequest(context) { const { request, params, env } = context; const userAgent = request.headers.get('User-Agent') || ''; - const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test( - userAgent - ); + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); const artistId = params.id; if (isBot && artistId) { + let api; + let artist; try { - const api = new ServerAPI(); - const data = await api.getArtistMetadata(artistId); - const artist = data.artist || data.data || data; + api = new TidalAPI(); + artist = await api.getArtistMetadata(artistId); + } catch (directError) { + console.warn(`Direct Tidal API failed for artist ${artistId}, falling back to proxies:`, directError); + try { + api = new ServerAPI(); + const data = await api.getArtistMetadata(artistId); + artist = data.artist || data.data || data; + } catch (fallbackError) { + console.error(`All methods failed for artist ${artistId}:`, fallbackError); + } + } - if (artist && (artist.name || artist.title)) { + if (artist && (artist.name || artist.title)) { + try { const name = artist.name || artist.title; const description = `Listen to ${name} on Monochrome`; const imageUrl = artist.picture @@ -119,14 +175,14 @@ export async function onRequest(context) { ${name} - + - + @@ -140,9 +196,9 @@ export async function onRequest(context) { `; return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } catch (error) { + console.error(`Error generating meta tags for artist ${artistId}:`, error); } - } catch (error) { - console.error(`Error for artist ${artistId}:`, error); } } diff --git a/functions/playlist/[id].js b/functions/playlist/[id].js index c20a6acb6..15fe6f632 100644 --- a/functions/playlist/[id].js +++ b/functions/playlist/[id].js @@ -1,5 +1,50 @@ // functions/playlist/[id].js +class TidalAPI { + static CLIENT_ID = 'txNoH4kkV41MfH25'; + static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98='; + + async getToken() { + const params = new URLSearchParams({ + client_id: TidalAPI.CLIENT_ID, + client_secret: TidalAPI.CLIENT_SECRET, + grant_type: 'client_credentials', + }); + const res = await fetch('https://auth.tidal.com/v1/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`), + }, + body: params, + }); + if (!res.ok) throw new Error(`Token request failed: ${res.status}`); + const data = await res.json(); + return data.access_token; + } + + async fetchJson(url, params = {}) { + const token = await this.getToken(); + const u = new URL(url); + Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v))); + const res = await fetch(u.toString(), { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!res.ok) throw new Error(`Tidal API error: ${res.status}`); + return res.json(); + } + + async getPlaylistMetadata(id) { + return await this.fetchJson(`https://api.tidal.com/v1/playlists/${id}`, { countryCode: 'US' }); + } + + getCoverUrl(id, size = '1080') { + if (!id) return ''; + const formattedId = String(id).replace(/-/g, '/'); + return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`; + } +} + class ServerAPI { constructor() { this.INSTANCES_URLS = [ @@ -29,7 +74,7 @@ class ServerAPI { if (data) { this.apiInstances = (data.api || []) .map((item) => item.url || item) - .filter((url) => !url.includes('spotisaver.net')); + .filter((url) => !/\.squid\.wtf/i.test(url)); return this.apiInstances; } @@ -38,7 +83,6 @@ class ServerAPI { 'https://eu-central.monochrome.tf', 'https://us-west.monochrome.tf', 'https://arran.monochrome.tf', - 'https://triton.squid.wtf', 'https://api.monochrome.tf', 'https://monochrome-api.samidy.com', 'https://maus.qqdl.site', @@ -77,7 +121,6 @@ class ServerAPI { const response = await this.fetchWithRetry(`/playlist/${id}`); return await response.json(); } catch { - // Fallback to query param style const response = await this.fetchWithRetry(`/playlist?id=${id}`); return await response.json(); } @@ -93,18 +136,31 @@ class ServerAPI { export async function onRequest(context) { const { request, params, env } = context; const userAgent = request.headers.get('User-Agent') || ''; - const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test( - userAgent - ); + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); const playlistId = params.id; if (isBot && playlistId) { + let api; + let playlist; try { - const api = new ServerAPI(); - const data = await api.getPlaylistMetadata(playlistId); - const playlist = data.playlist || data.data || data; + api = new TidalAPI(); + playlist = await api.getPlaylistMetadata(playlistId); + } catch (directError) { + console.warn(`Direct Tidal API failed for playlist ${playlistId}, falling back to proxies:`, directError); + try { + api = new ServerAPI(); + const data = await api.getPlaylistMetadata(playlistId); + playlist = data.playlist || data.data || data; + } catch (fallbackError) { + console.error(`All methods failed for playlist ${playlistId}:`, fallbackError); + } + } - if (playlist && (playlist.title || playlist.name)) { + if (playlist && (playlist.title || playlist.name)) { + try { const title = playlist.title || playlist.name; const trackCount = playlist.numberOfTracks; const description = `Playlist β€’ ${trackCount} Tracks\nListen on Monochrome`; @@ -122,7 +178,7 @@ export async function onRequest(context) { ${title} - + @@ -130,7 +186,7 @@ export async function onRequest(context) { - + @@ -145,9 +201,9 @@ export async function onRequest(context) { `; return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } catch (error) { + console.error(`Error generating meta tags for playlist ${playlistId}:`, error); } - } catch (error) { - console.error(`Error for playlist ${playlistId}:`, error); } } diff --git a/functions/podcasts/[id].js b/functions/podcasts/[id].js new file mode 100644 index 000000000..25586fef2 --- /dev/null +++ b/functions/podcasts/[id].js @@ -0,0 +1,99 @@ +// functions/podcasts/[id].js + +const PODCASTINDEX_API_BASE = 'https://api.podcastindex.org/api/1.0'; +const PODCAST_API_KEY = 'YU5HMSDYBQQVYDF6QN4P'; +const PODCAST_API_SECRET = '8hCvpjSL7T$S7^5ftnf5MhqQwYUYVjM^fmUL3Ld$'; + +async function sha1(str) { + const encoder = new TextEncoder(); + const data = encoder.encode(str); + const hashBuffer = await crypto.subtle.digest('SHA-1', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); +} + +async function getAuthHeaders() { + const apiHeaderTime = Math.floor(Date.now() / 1000).toString(); + const combined = PODCAST_API_KEY + PODCAST_API_SECRET + apiHeaderTime; + const authHeader = await sha1(combined); + return { + 'User-Agent': 'MonochromeMusic/1.0', + 'X-Auth-Key': PODCAST_API_KEY, + 'X-Auth-Date': apiHeaderTime, + Authorization: authHeader, + }; +} + +export async function onRequest(context) { + const { request, params, env } = context; + const userAgent = request.headers.get('User-Agent') || ''; + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); + const podcastId = params.id; + + if (isBot && podcastId) { + try { + const headers = await getAuthHeaders(); + const response = await fetch(`${PODCASTINDEX_API_BASE}/podcasts/byfeedid?id=${podcastId}&pretty`, { + method: 'GET', + headers, + }); + + if (!response.ok) throw new Error(`PodcastIndex error: ${response.status}`); + + const data = await response.json(); + const feed = data.status === 'true' && data.feed ? data.feed : null; + + if (feed && feed.title) { + const title = feed.title; + const author = feed.author || feed.ownerName || ''; + const episodeCount = feed.episodeCount || 0; + const rawDescription = feed.description || ''; + const description = author + ? `Podcast by ${author} β€’ ${episodeCount} Episodes\nListen on Monochrome` + : `Podcast β€’ ${episodeCount} Episodes\nListen on Monochrome`; + const imageUrl = feed.image || feed.artwork || 'https://monochrome.tf/assets/appicon.png'; + const pageUrl = new URL(request.url).href; + + const metaHtml = ` + + + + + ${title} + + + + + + + + + + + + + + + + +

${title}

+

${description}

+ Podcast Cover + + + `; + + return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } + } catch (error) { + console.error(`Error for podcast ${podcastId}:`, error); + } + } + + const url = new URL(request.url); + url.pathname = '/'; + return env.ASSETS.fetch(new Request(url, request)); +} diff --git a/functions/track/[id].js b/functions/track/[id].js index e96fa9403..cf50d4488 100644 --- a/functions/track/[id].js +++ b/functions/track/[id].js @@ -12,6 +12,61 @@ function getTrackArtists(track = {}, { fallback = 'Unknown Artist' } = {}) { return fallback; } +class TidalAPI { + static CLIENT_ID = 'txNoH4kkV41MfH25'; + static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98='; + + async getToken() { + const params = new URLSearchParams({ + client_id: TidalAPI.CLIENT_ID, + client_secret: TidalAPI.CLIENT_SECRET, + grant_type: 'client_credentials', + }); + const res = await fetch('https://auth.tidal.com/v1/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`), + }, + body: params, + }); + if (!res.ok) throw new Error(`Token request failed: ${res.status}`); + const data = await res.json(); + return data.access_token; + } + + async fetchJson(url, params = {}) { + const token = await this.getToken(); + const u = new URL(url); + Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v))); + const res = await fetch(u.toString(), { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!res.ok) throw new Error(`Tidal API error: ${res.status}`); + return res.json(); + } + + async getTrackMetadata(id) { + return await this.fetchJson(`https://api.tidal.com/v1/tracks/${id}/`, { countryCode: 'US' }); + } + + async getStreamUrl(id) { + const data = await this.fetchJson(`https://api.tidal.com/v1/tracks/${id}/playbackinfo`, { + audioquality: 'LOW', + playbackmode: 'STREAM', + assetpresentation: 'FULL', + countryCode: 'US', + }); + return data.url || data.streamUrl; + } + + getCoverUrl(id, size = '1280') { + if (!id) return ''; + const formattedId = String(id).replace(/-/g, '/'); + return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`; + } +} + class ServerAPI { constructor() { this.INSTANCES_URLS = [ @@ -39,9 +94,7 @@ class ServerAPI { } if (data) { - this.apiInstances = (data.api || []) - .map((item) => item.url || item) - .filter((url) => !url.includes('spotisaver.net')); + this.apiInstances = (data.api || []).map((item) => item.url || item); return this.apiInstances; } @@ -112,17 +165,31 @@ class ServerAPI { export async function onRequest(context) { const { request, params, env } = context; const userAgent = request.headers.get('User-Agent') || ''; - const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test( - userAgent - ); + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); const trackId = params.id; if (isBot && trackId) { + // Try direct Tidal API first, fall back to proxy instances + let api; + let track; try { - const api = new ServerAPI(); - const track = await api.getTrackMetadata(trackId); + api = new TidalAPI(); + track = await api.getTrackMetadata(trackId); + } catch (directError) { + console.warn(`Direct Tidal API failed for track ${trackId}, falling back to proxies:`, directError); + try { + api = new ServerAPI(); + track = await api.getTrackMetadata(trackId); + } catch (fallbackError) { + console.error(`All methods failed for track ${trackId}:`, fallbackError); + } + } - if (track) { + if (track) { + try { const title = getTrackTitle(track); const artist = getTrackArtists(track); const description = `${artist} - ${track.album.title}`; @@ -138,7 +205,7 @@ export async function onRequest(context) { console.error('Failed to fetch stream fallback:', e); } } - // this prob wont work im js winging it + const audioMeta = audioUrl ? ` @@ -155,7 +222,7 @@ export async function onRequest(context) { ${title} by ${artist} - + @@ -164,9 +231,9 @@ export async function onRequest(context) { - + ${audioMeta} - + @@ -184,9 +251,9 @@ export async function onRequest(context) { return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' }, }); + } catch (error) { + console.error(`Error generating meta tags for track ${trackId}:`, error); } - } catch (error) { - console.error(`Error generating meta tags for track ${trackId}:`, error); } } diff --git a/functions/upload.js b/functions/upload.js deleted file mode 100644 index 31a11838b..000000000 --- a/functions/upload.js +++ /dev/null @@ -1,195 +0,0 @@ -const API_URL = 'https://catbox.moe/user/api.php'; -const R2_PUBLIC_URL = 'https://cucks.qzz.io'; - -const R2_ENDPOINT = 'https://faae2f5c0a232c7f3733ef597c55bd69.r2.cloudflarestorage.com'; -const R2_BUCKET = 'monochrome-image-uploads'; - -async function hmac(key, data) { - const cryptoKey = await crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']); - return new Uint8Array(await crypto.subtle.sign('HMAC', cryptoKey, data)); -} - -async function sha256(data) { - return new Uint8Array(await crypto.subtle.digest('SHA-256', data)); -} - -function buf2hex(buffer) { - return Array.from(buffer) - .map((b) => b.toString(16).padStart(2, '0')) - .join(''); -} - -async function signature(secretKey, dateStamp, region, service, stringToSign) { - const kDate = await hmac(new TextEncoder().encode('AWS4' + secretKey), new TextEncoder().encode(dateStamp)); - const kRegion = await hmac(kDate, new TextEncoder().encode(region)); - const kService = await hmac(kRegion, new TextEncoder().encode(service)); - const kSigning = await hmac(kService, new TextEncoder().encode('aws4_request')); - const sig = await hmac(kSigning, new TextEncoder().encode(stringToSign)); - return buf2hex(sig); -} - -async function createSignature(method, path, headers, payloadHash, accessKeyId, secretAccessKey, amzDate, dateStamp) { - const region = 'auto'; - const service = 's3'; - - const signedHeaders = Object.keys(headers).sort().join(';'); - const canonicalHeaders = - Object.entries(headers) - .sort((a, b) => a[0].localeCompare(b[0])) - .map(([k, v]) => `${k.toLowerCase()}:${v}`) - .join('\n') + '\n'; - - const canonicalRequest = `${method}\n${path}\n\n${canonicalHeaders}\n${signedHeaders}\n${payloadHash}`; - const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`; - const stringToSign = `AWS4-HMAC-SHA256\n${amzDate}\n${credentialScope}\n${buf2hex(await sha256(new TextEncoder().encode(canonicalRequest)))}`; - - const sig = await signature(secretAccessKey, dateStamp, region, service, stringToSign); - return `AWS4-HMAC-SHA256 Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${sig}`; -} - -export async function onRequest(context) { - const { request, env } = context; - - if (request.method === 'OPTIONS') { - return new Response(null, { status: 204, headers: corsHeaders() }); - } - - if (request.method !== 'POST') { - return jsonError('Method not allowed', 405); - } - - const useR2 = env.R2_ENABLED === 'true'; - - try { - const contentType = request.headers.get('content-type') || ''; - let file; - let fileName; - let fileType; - - if (contentType.includes('application/json')) { - const body = await request.json(); - if (!body.fileUrl) return jsonError('No fileUrl provided', 400); - - const res = await fetch(body.fileUrl); - if (!res.ok) throw new Error('Failed to fetch remote file'); - - file = await res.arrayBuffer(); - fileName = body.fileName || body.fileUrl.split('/').pop(); - fileType = res.headers.get('content-type') || 'application/octet-stream'; - } else { - const form = await request.formData(); - const uploaded = form.get('file'); - if (!uploaded) return jsonError('No file provided', 400); - - if (uploaded.size > 10 * 1024 * 1024) { - return jsonError('File exceeds 10MB', 400); - } - - file = await uploaded.arrayBuffer(); - fileName = uploaded.name; - fileType = uploaded.type || 'application/octet-stream'; - } - - let url; - - if (useR2) { - try { - const key = `${Date.now()}-${fileName}`; - const now = new Date(); - const amzDate = - now - .toISOString() - .replace(/[:-]|\.\d{3}/g, '') - .slice(0, 15) + 'Z'; - const dateStamp = now - .toISOString() - .replace(/[:-]|\.\d{3}/g, '') - .slice(0, 8); - const payloadHash = buf2hex(await sha256(file)); - - const host = new URL(R2_ENDPOINT).host; - const headers = { - 'Content-Type': fileType, - 'Content-Length': file.byteLength, - 'x-amz-date': amzDate, - 'x-amz-content-sha256': payloadHash, - Host: host, - }; - - const auth = await createSignature( - 'PUT', - `/${R2_BUCKET}/${key}`, - headers, - payloadHash, - env.R2_ACCESS_KEY_ID, - env.R2_SECRET_ACCESS_KEY, - amzDate, - dateStamp - ); - headers['Authorization'] = auth; - - const res = await fetch(`${R2_ENDPOINT}/${R2_BUCKET}/${key}`, { - method: 'PUT', - headers, - body: new Uint8Array(file), - }); - - if (!res.ok) { - const err = await res.text(); - throw new Error(`R2 error: ${res.status} - ${err}`); - } - - url = `${R2_PUBLIC_URL}/${key}`; - } catch (r2Err) { - console.error('R2 upload error:', r2Err); - return jsonError(`R2 upload failed: ${r2Err.message}`, 500); - } - } else { - const formData = new FormData(); - formData.append('reqtype', 'fileupload'); - formData.append('fileToUpload', new Blob([file], { type: fileType }), fileName); - - const response = await fetch(API_URL, { - method: 'POST', - body: formData, - }); - - const responseText = await response.text(); - - if (!response.ok) { - throw new Error(`Upload failed: ${responseText}`); - } - - url = responseText.trim(); - } - - return jsonResponse({ - success: true, - url: url, - }); - } catch (err) { - return jsonError(err.message, 500); - } -} - -function jsonResponse(obj, status = 200) { - return new Response(JSON.stringify(obj), { - status, - headers: { - 'Content-Type': 'application/json', - ...corsHeaders(), - }, - }); -} - -function jsonError(message, status) { - return jsonResponse({ success: false, error: message }, status); -} - -function corsHeaders() { - return { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'POST, OPTIONS', - 'Access-Control-Allow-Headers': '*', - }; -} diff --git a/functions/user/@[username].js b/functions/user/@[username].js new file mode 100644 index 000000000..a603acf88 --- /dev/null +++ b/functions/user/@[username].js @@ -0,0 +1,82 @@ +// functions/user/@[username].js + +export async function onRequest(context) { + const { request, params, env } = context; + const userAgent = request.headers.get('User-Agent') || ''; + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); + const username = params.username; + + if (isBot && username) { + try { + const POCKETBASE_URL = 'https://data.samidy.xyz'; + const filter = `username="${username}"`; + const profileUrl = `${POCKETBASE_URL}/api/collections/DB_users/records?filter=${encodeURIComponent(filter)}&fields=username,display_name,avatar_url,banner,about,status`; + + const response = await fetch(profileUrl); + if (!response.ok) throw new Error(`PocketBase error: ${response.status}`); + + const data = await response.json(); + const profile = data.items && data.items.length > 0 ? data.items[0] : null; + + if (profile) { + const displayName = profile.display_name || profile.username; + const title = `${displayName} (@${profile.username})`; + let description = profile.about || `View ${displayName}'s profile on Monochrome.`; + + if (profile.status) { + try { + const statusObj = JSON.parse(profile.status); + description = `Listening to: ${statusObj.text}\n\n${description}`; + } catch { + description = `Listening to: ${profile.status}\n\n${description}`; + } + } + + const imageUrl = profile.avatar_url || 'https://monochrome.tf/assets/appicon.png'; + const bannerUrl = profile.banner || ''; + const pageUrl = new URL(request.url).href; + + const metaHtml = ` + + + + + ${title} + + + + + + + + + + + + + + + + +

${title}

+

${description}

+ Profile Avatar + ${bannerUrl ? `Profile Banner` : ''} + + + `; + + return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } + } catch (error) { + console.error(`Error for user profile ${username}:`, error); + } + } + + const url = new URL(request.url); + url.pathname = '/'; + return env.ASSETS.fetch(new Request(url, request)); +} diff --git a/functions/userplaylist/[id].js b/functions/userplaylist/[id].js new file mode 100644 index 000000000..631b4c96c --- /dev/null +++ b/functions/userplaylist/[id].js @@ -0,0 +1,116 @@ +// functions/userplaylist/[id].js + +const POCKETBASE_URL = 'https://data.samidy.xyz'; +const PUBLIC_COLLECTION = 'public_playlists'; + +export async function onRequest(context) { + const { request, params, env } = context; + const userAgent = request.headers.get('User-Agent') || ''; + const isBot = + /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( + userAgent + ); + const playlistId = params.id; + + if (isBot && playlistId) { + try { + const filter = `uuid="${playlistId}"`; + const apiUrl = `${POCKETBASE_URL}/api/collections/${PUBLIC_COLLECTION}/records?filter=${encodeURIComponent(filter)}&perPage=1`; + + const response = await fetch(apiUrl); + if (!response.ok) throw new Error(`PocketBase error: ${response.status}`); + + const result = await response.json(); + const record = result.items && result.items.length > 0 ? result.items[0] : null; + + if (record) { + let extraData = {}; + try { + extraData = record.data ? JSON.parse(record.data) : {}; + } catch { + extraData = {}; + } + + const title = + record.title || + record.name || + (extraData && (extraData.title || extraData.name)) || + 'Untitled Playlist'; + + let tracks = []; + try { + tracks = record.tracks ? JSON.parse(record.tracks) : []; + } catch { + tracks = []; + } + + const trackCount = tracks.length; + + let rawCover = record.image || record.cover || record.playlist_cover || ''; + if (!rawCover && extraData && typeof extraData === 'object') { + rawCover = extraData.cover || extraData.image || ''; + } + + let imageUrl = ''; + if (rawCover && (rawCover.startsWith('http') || rawCover.startsWith('data:'))) { + imageUrl = rawCover; + } else if (rawCover) { + imageUrl = `${POCKETBASE_URL}/api/files/${PUBLIC_COLLECTION}/${record.id}/${rawCover}`; + } + + if (!imageUrl && tracks.length > 0) { + const firstCover = tracks.find((t) => t.album?.cover)?.album?.cover; + if (firstCover) { + const formattedId = String(firstCover).replace(/-/g, '/'); + imageUrl = `https://resources.tidal.com/images/${formattedId}/1080x1080.jpg`; + } + } + + if (!imageUrl) { + imageUrl = 'https://monochrome.tf/assets/appicon.png'; + } + + const description = `Playlist β€’ ${trackCount} Tracks\nListen on Monochrome`; + const pageUrl = new URL(request.url).href; + + const metaHtml = ` + + + + + ${title} + + + + + + + + + + + + + + + + + +

${title}

+

${description}

+ Playlist Cover + + + `; + + return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } }); + } + } catch (error) { + console.error(`Error for user playlist ${playlistId}:`, error); + } + } + + const url = new URL(request.url); + url.pathname = '/'; + return env.ASSETS.fetch(new Request(url, request)); +} diff --git a/images/animate-spin.svg b/images/animate-spin.svg new file mode 100644 index 000000000..e85f924c0 --- /dev/null +++ b/images/animate-spin.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/images/apple.svg b/images/apple.svg new file mode 100644 index 000000000..19452c474 --- /dev/null +++ b/images/apple.svg @@ -0,0 +1,20 @@ + + + + + apple [#9E9E9E173] + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/images/atmos.svg b/images/atmos.svg new file mode 100644 index 000000000..b55e3c311 --- /dev/null +++ b/images/atmos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/discord.svg b/images/discord.svg new file mode 100644 index 000000000..829e5247a --- /dev/null +++ b/images/discord.svg @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/images/facebook.svg b/images/facebook.svg new file mode 100644 index 000000000..c54c0b183 --- /dev/null +++ b/images/facebook.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/images/genius-active.svg b/images/genius-active.svg new file mode 100644 index 000000000..988d65e1f --- /dev/null +++ b/images/genius-active.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/images/genius-inactive.svg b/images/genius-inactive.svg new file mode 100644 index 000000000..c984e154f --- /dev/null +++ b/images/genius-inactive.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/images/github.svg b/images/github.svg new file mode 100644 index 000000000..1b41c06eb --- /dev/null +++ b/images/github.svg @@ -0,0 +1 @@ +GitHub diff --git a/images/gitlab.svg b/images/gitlab.svg new file mode 100644 index 000000000..ab1286a21 --- /dev/null +++ b/images/gitlab.svg @@ -0,0 +1 @@ +GitLab diff --git a/images/google.svg b/images/google.svg new file mode 100644 index 000000000..5eaf7064c --- /dev/null +++ b/images/google.svg @@ -0,0 +1 @@ + diff --git a/images/instagram.svg b/images/instagram.svg new file mode 100644 index 000000000..b8a0a85e0 --- /dev/null +++ b/images/instagram.svg @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/images/linux.svg b/images/linux.svg new file mode 100644 index 000000000..2479f272a --- /dev/null +++ b/images/linux.svg @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/images/mic.svg b/images/mic.svg new file mode 100644 index 000000000..fa2c7213c --- /dev/null +++ b/images/mic.svg @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/images/mix.svg b/images/mix.svg new file mode 100644 index 000000000..1a3153b14 --- /dev/null +++ b/images/mix.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/images/monochrome-logo.svg b/images/monochrome-logo.svg new file mode 100644 index 000000000..2313e279c --- /dev/null +++ b/images/monochrome-logo.svg @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/images/pause-large.svg b/images/pause-large.svg new file mode 100644 index 000000000..228b7094d --- /dev/null +++ b/images/pause-large.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/images/pause.svg b/images/pause.svg new file mode 100644 index 000000000..1a2b240d0 --- /dev/null +++ b/images/pause.svg @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/images/play-large.svg b/images/play-large.svg new file mode 100644 index 000000000..91358b35f --- /dev/null +++ b/images/play-large.svg @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/images/play.svg b/images/play.svg new file mode 100644 index 000000000..567557296 --- /dev/null +++ b/images/play.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/images/recent.svg b/images/recent.svg new file mode 100644 index 000000000..3d60f6f59 --- /dev/null +++ b/images/recent.svg @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/images/side-menu.svg b/images/side-menu.svg new file mode 100644 index 000000000..64dde4b55 --- /dev/null +++ b/images/side-menu.svg @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/images/sort.svg b/images/sort.svg new file mode 100644 index 000000000..c962f18b2 --- /dev/null +++ b/images/sort.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/soundcloud.svg b/images/soundcloud.svg new file mode 100644 index 000000000..1f55321e8 --- /dev/null +++ b/images/soundcloud.svg @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/images/spotify.svg b/images/spotify.svg new file mode 100644 index 000000000..d4f5e5ce9 --- /dev/null +++ b/images/spotify.svg @@ -0,0 +1 @@ +Spotify diff --git a/images/squares.svg b/images/squares.svg new file mode 100644 index 000000000..f57e71d5e --- /dev/null +++ b/images/squares.svg @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/images/twitter.svg b/images/twitter.svg new file mode 100644 index 000000000..a56b86602 --- /dev/null +++ b/images/twitter.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/images/windows.svg b/images/windows.svg new file mode 100644 index 000000000..3fb994e0d --- /dev/null +++ b/images/windows.svg @@ -0,0 +1,4 @@ + + windows [#FFF174] + + \ No newline at end of file diff --git a/images/youtube.svg b/images/youtube.svg new file mode 100644 index 000000000..c9fb8b1e1 --- /dev/null +++ b/images/youtube.svg @@ -0,0 +1,20 @@ + + + + + youtube [#9E9E9E168] + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index b4e38df55..c4406d54e 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=contain" /> Monochrome Music + @@ -17,13 +18,9 @@ - - - - @@ -54,14 +51,11 @@
  • Add to queue
  • Like
  • @@ -116,6 +110,7 @@
    +

    Panel

    @@ -128,10 +123,10 @@

    Panel

    + +
    + +
    @@ -1273,12 +1080,7 @@

    Custom Database/Auth

    - +
    @@ -1347,19 +1149,7 @@

    Theme Store

    gap: 0.5rem; " > - - - + Back
    @@ -1417,21 +1207,7 @@

    Description

    style="flex: 1; overflow-y: auto; min-height: 0" >
    - - - - + Description
    @@ -1650,21 +1414,7 @@

    - - - - @@ -2566,19 +1991,7 @@

    Favorites

    Local Files >

    Recently played

    @@ -2649,6 +2046,46 @@

    Recently played

    +
    +
    + +
    +
    Podcast
    +

    +
    +
    + +
    +
    +
    +
    +

    Episodes

    +
    +
    +
    + +
    +

    Browse Podcasts

    +
    + + +
    + +
    +
    +
    +
    +
    @@ -2712,84 +2127,23 @@

    @@ -2897,53 +2222,15 @@

    - - - - + Recommended Songs class="btn-secondary" title="Refresh Recommendations" > - - - - +
    @@ -3078,33 +2324,11 @@

    @@ -3154,69 +2363,19 @@

    @@ -3251,6 +2395,36 @@

    Popular Tracks

    +

    Albums

    @@ -3297,52 +2471,15 @@

    @@ -3475,21 +2583,7 @@

    Settings

    onsubmit="return false;" style="margin: 1rem 0" > - - - - + Custom Theme -
    -
    - Smooth Scrolling - Provides a smoother scrolling experience with Lenis (Experimental) -
    - -
    Album Cover Background @@ -3859,7 +2941,6 @@

    Custom Theme

    >
    -
    @@ -4614,24 +3707,15 @@

    Custom Theme

    -
    -
    - Music Provider - Default service for searching and streaming -
    - -
    Streaming Quality - Quality for streaming playback + Default playback quality for streams
    @@ -4664,7 +3748,7 @@

    Custom Theme

    Play audio without interruption between tracks
    @@ -4718,7 +3802,6 @@

    Custom Theme

    -
    Playback Speed @@ -4754,7 +3837,6 @@

    Custom Theme

    -
    Preserve Pitch @@ -4766,7 +3848,6 @@

    Custom Theme

    -
    Equalizer @@ -4822,20 +3903,7 @@

    Custom Theme

    class="btn-secondary" title="Reset to Flat" > - - - - +
    @@ -5029,14 +4082,60 @@

    Custom Theme

    - Zipped Bulk Downloads + Bulk Download Method + Choose how multiple tracks are downloaded together +
    + +
    +
    +
    + Remember Last Folder + Re-use the last chosen directory for Folder Picker downloads +
    + +
    +
    +
    + Reset Saved Folder + Clear the remembered Folder Picker directory +
    + +
    +
    +
    + Single Downloads to Folder + Save individual track downloads directly to the configured folder instead + of triggering a browser download +
    + +
    +
    +
    + Force ZIP as Blob Download multiple tracks as a single ZIP file (requires browser - support)Download ZIP in memory instead of streaming to disk (use if ZIP streaming + causes issues)
    @@ -5064,18 +4163,28 @@

    Custom Theme

    -
    -
    - Download Quality - Quality for track downloads +
    +
    +
    + Download Quality + Quality for track downloads +
    + +
    + -
    @@ -5083,8 +4192,6 @@

    Custom Theme

    Container format for lossless downloads
    @@ -5105,8 +4212,8 @@

    Custom Theme

    Filename Template Customize download filenames. Available: {trackNumber}, {artist}, {title}, - {album}Customize download filenames. Available: {discNumber}, {trackNumber}, + {artist}, {title}, {album}
    Custom Theme
    - ZIP Folder Template + Folder Template Customize album folder names. Available: {albumTitle}, {albumArtist}, - {year}Customize album folder names. Use / for nested folders. + Available: {albumTitle}, {albumArtist}, {year}
    Custom Theme
    - Separate Discs in ZIP + Separate Discs Put tracks in Disc folders when a release has multiple discs @@ -5215,6 +4322,16 @@

    Custom Theme

    +
    +
    + Include Cover File + Include cover.jpg in downloads +
    + +
    @@ -5373,6 +4490,15 @@

    Custom Theme

    +

    @@ -5410,9 +4536,7 @@

    Support Monochrome

    " > Support Monochrome

    made with β€ͺβ€ͺβ€οΈŽβ€¬ by - Edideaur, - Samidy & - Julien + Edideaur & + Samidy

    -
    -

    Monochrome Official App

    -
    - -

    - -
    -
    - - - - - windows [#FFF174] - Created with Sketch. - - - - - - - - - - -
    -
    - -
    -
    - - - - - - - -
    -
    - -
    -
    -
    -

    - The App is still in Beta. Please report any issues in our - Discord server. -

    -
    -
    -

    Donate to Monochrome

    - @@ -5652,80 +4701,17 @@

    Donate to Monochrome

    @@ -5745,21 +4731,13 @@

    Donate to Monochrome

    title="Save to Favorites" style="display: none" > - - -
    @@ -5878,20 +4777,7 @@

    Donate to Monochrome

    diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 000000000..f47029973 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,13 @@ +App/build +App/Pods +App/output +App/App/public +DerivedData +xcuserdata + +# Cordova plugins for Capacitor +capacitor-cordova-ios-plugins + +# Generated Config files +App/App/capacitor.config.json +App/App/config.xml diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2654b3671 --- /dev/null +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -0,0 +1,378 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D22ABE82AF431CB00220026 /* CapApp-SPM */; }; + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; + 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; + 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; + 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 504EC3011FED79650016851F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 504EC2FB1FED79650016851F = { + isa = PBXGroup; + children = ( + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */, + 504EC3061FED79650016851F /* App */, + 504EC3051FED79650016851F /* Products */, + ); + sourceTree = ""; + }; + 504EC3051FED79650016851F /* Products */ = { + isa = PBXGroup; + children = ( + 504EC3041FED79650016851F /* App.app */, + ); + name = Products; + sourceTree = ""; + }; + 504EC3061FED79650016851F /* App */ = { + isa = PBXGroup; + children = ( + 50379B222058CBB4000EE86E /* capacitor.config.json */, + 504EC3071FED79650016851F /* AppDelegate.swift */, + 504EC30B1FED79650016851F /* Main.storyboard */, + 504EC30E1FED79650016851F /* Assets.xcassets */, + 504EC3101FED79650016851F /* LaunchScreen.storyboard */, + 504EC3131FED79650016851F /* Info.plist */, + 2FAD9762203C412B000D30F8 /* config.xml */, + 50B271D01FEDC1A000F3C39B /* public */, + ); + path = App; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 504EC3031FED79650016851F /* App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */; + buildPhases = ( + 504EC3001FED79650016851F /* Sources */, + 504EC3011FED79650016851F /* Frameworks */, + 504EC3021FED79650016851F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = App; + packageProductDependencies = ( + 4D22ABE82AF431CB00220026 /* CapApp-SPM */, + ); + productName = App; + productReference = 504EC3041FED79650016851F /* App.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 504EC2FC1FED79650016851F /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 920; + LastUpgradeCheck = 920; + TargetAttributes = { + 504EC3031FED79650016851F = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 504EC2FB1FED79650016851F; + packageReferences = ( + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */, + ); + productRefGroup = 504EC3051FED79650016851F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 504EC3031FED79650016851F /* App */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 504EC3021FED79650016851F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */, + 50B271D11FEDC1A000F3C39B /* public in Resources */, + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */, + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */, + 504EC30D1FED79650016851F /* Main.storyboard in Resources */, + 2FAD9763203C412B000D30F8 /* config.xml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 504EC3001FED79650016851F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 504EC30B1FED79650016851F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC30C1FED79650016851F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 504EC3101FED79650016851F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC3111FED79650016851F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 504EC3141FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 504EC3151FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 504EC3171FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6KK6V7WSG6; + INFOPLIST_FILE = App/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; + PRODUCT_BUNDLE_IDENTIFIER = tf.monochrome.music; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 504EC3181FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6KK6V7WSG6; + INFOPLIST_FILE = App/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = tf.monochrome.music; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3141FED79650016851F /* Debug */, + 504EC3151FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3171FED79650016851F /* Debug */, + 504EC3181FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "CapApp-SPM"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 4D22ABE82AF431CB00220026 /* CapApp-SPM */ = { + isa = XCSwiftPackageProductDependency; + package = D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */; + productName = "CapApp-SPM"; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 504EC2FC1FED79650016851F /* Project object */; +} diff --git a/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..2d5c82bfc --- /dev/null +++ b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "52b8f5ad81945242b71e7fa9d492392d601fa6f5525d16cba3e68e55cab9b529", + "pins" : [ + { + "identity" : "capacitor-swift-pm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ionic-team/capacitor-swift-pm.git", + "state" : { + "revision" : "0e862e6ff13852a710c8a484180ca4d6a2cc9761", + "version" : "8.2.0" + } + } + ], + "version" : 3 +} diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift new file mode 100644 index 000000000..c3cd83b5c --- /dev/null +++ b/ios/App/App/AppDelegate.swift @@ -0,0 +1,49 @@ +import UIKit +import Capacitor + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + // Called when the app was launched with a url. Feel free to add additional processing here, + // but if you want the App API to support tracking app url opens, make sure to keep this call + return ApplicationDelegateProxy.shared.application(app, open: url, options: options) + } + + func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { + // Called when the app was launched with an activity, including Universal Links. + // Feel free to add additional processing here, but if you want the App API to support + // tracking app url opens, make sure to keep this call + return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) + } + +} diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 000000000..8ddb86c66 Binary files /dev/null and b/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..fa7dcdd8f --- /dev/null +++ b/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images": [ + { + "idiom": "universal", + "size": "1024x1024", + "filename": "AppIcon-512@2x.png", + "platform": "ios" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/ios/App/App/Assets.xcassets/Contents.json b/ios/App/App/Assets.xcassets/Contents.json new file mode 100644 index 000000000..9e0da7c5a --- /dev/null +++ b/ios/App/App/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json b/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json new file mode 100644 index 000000000..5c8a45c2c --- /dev/null +++ b/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json @@ -0,0 +1,56 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "Default@1x~universal~anyany.png", + "scale": "1x" + }, + { + "idiom": "universal", + "filename": "Default@2x~universal~anyany.png", + "scale": "2x" + }, + { + "idiom": "universal", + "filename": "Default@3x~universal~anyany.png", + "scale": "3x" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "idiom": "universal", + "scale": "1x", + "filename": "Default@1x~universal~anyany-dark.png" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "idiom": "universal", + "scale": "2x", + "filename": "Default@2x~universal~anyany-dark.png" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "idiom": "universal", + "scale": "3x", + "filename": "Default@3x~universal~anyany-dark.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany-dark.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany-dark.png new file mode 100644 index 000000000..c137b7076 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany-dark.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany.png new file mode 100644 index 000000000..1717f80f1 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@1x~universal~anyany.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany-dark.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany-dark.png new file mode 100644 index 000000000..c137b7076 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany-dark.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany.png new file mode 100644 index 000000000..1717f80f1 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@2x~universal~anyany.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany-dark.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany-dark.png new file mode 100644 index 000000000..c137b7076 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany-dark.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany.png b/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany.png new file mode 100644 index 000000000..1717f80f1 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/Default@3x~universal~anyany.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png differ diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png new file mode 100644 index 000000000..33ea6c970 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png differ diff --git a/ios/App/App/Base.lproj/LaunchScreen.storyboard b/ios/App/App/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..e7ae5d780 --- /dev/null +++ b/ios/App/App/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/App/App/Base.lproj/Main.storyboard b/ios/App/App/Base.lproj/Main.storyboard new file mode 100644 index 000000000..b44df7be8 --- /dev/null +++ b/ios/App/App/Base.lproj/Main.storyboard @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist new file mode 100644 index 000000000..ef1bec358 --- /dev/null +++ b/ios/App/App/Info.plist @@ -0,0 +1,51 @@ + + + + + CAPACITOR_DEBUG + $(CAPACITOR_DEBUG) + CFBundleDevelopmentRegion + en + CFBundleDisplayName + monochrome + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/App/CapApp-SPM/.gitignore b/ios/App/CapApp-SPM/.gitignore new file mode 100644 index 000000000..3b2981208 --- /dev/null +++ b/ios/App/CapApp-SPM/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/ios/App/CapApp-SPM/Package.swift b/ios/App/CapApp-SPM/Package.swift new file mode 100644 index 000000000..80f1c8fea --- /dev/null +++ b/ios/App/CapApp-SPM/Package.swift @@ -0,0 +1,29 @@ +// swift-tools-version: 5.9 +import PackageDescription + +// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands +let package = Package( + name: "CapApp-SPM", + platforms: [.iOS(.v15)], + products: [ + .library( + name: "CapApp-SPM", + targets: ["CapApp-SPM"]) + ], + dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.2.0"), + .package(name: "CapacitorApp", path: "../../../node_modules/@capacitor/app"), + .package(name: "CapacitorHaptics", path: "../../../node_modules/@capacitor/haptics") + ], + targets: [ + .target( + name: "CapApp-SPM", + dependencies: [ + .product(name: "Capacitor", package: "capacitor-swift-pm"), + .product(name: "Cordova", package: "capacitor-swift-pm"), + .product(name: "CapacitorApp", package: "CapacitorApp"), + .product(name: "CapacitorHaptics", package: "CapacitorHaptics") + ] + ) + ] +) diff --git a/ios/App/CapApp-SPM/README.md b/ios/App/CapApp-SPM/README.md new file mode 100644 index 000000000..03964db90 --- /dev/null +++ b/ios/App/CapApp-SPM/README.md @@ -0,0 +1,5 @@ +# CapApp-SPM + +This package is used to host SPM dependencies for your Capacitor project + +Do not modify the contents of it or there may be unintended consequences. diff --git a/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift b/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift new file mode 100644 index 000000000..945afec8c --- /dev/null +++ b/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift @@ -0,0 +1 @@ +public let isCapacitorApp = true diff --git a/ios/debug.xcconfig b/ios/debug.xcconfig new file mode 100644 index 000000000..53ce18dea --- /dev/null +++ b/ios/debug.xcconfig @@ -0,0 +1 @@ +CAPACITOR_DEBUG = true diff --git a/js/HiFi.ts b/js/HiFi.ts new file mode 100644 index 000000000..85dced6de --- /dev/null +++ b/js/HiFi.ts @@ -0,0 +1,1025 @@ +import { EventEmitter } from 'events'; + +const API_VERSION = '2.7'; +const BROWSER_CLIENT_ID = 'txNoH4kkV41MfH25'; +const BROWSER_CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98='; + +type Params = Record; + +class ResponseError extends Error { + status: number; + constructor(status: number, message: string) { + super(message); + this.status = status; + } +} + +export class TidalResponse extends Response { + constructor(response: Response); + constructor(body: BodyInit, init?: ResponseInit); + constructor(body: BodyInit | Response, init?: ResponseInit) { + if (body instanceof Response) { + super(body.body, { + headers: body.headers, + status: body.status, + statusText: body.statusText, + }); + } else { + super(body, init); + } + } +} + +export enum HiFiClientEvents { + TokenUpdate, + TokenExpiryUpdate, + RefreshTokenUpdate, +} + +class HiFiClient { + static #instance: HiFiClient | null = null; + static get instance() { + if (!HiFiClient.#instance) { + throw new Error('HiFiClient is not initialized. Call HiFiClient.initialize(options) first.'); + } + return HiFiClient.#instance; + } + + /** + * The base URL to use for adjusting widevine license URLs. + */ + #baseUrl: string | null = null; + #token: string | null = null; + #refreshToken: string | null = null; + #appTokenExpiry = 0; + #tokenPromise: Promise | null = null; + #albumTracksActive = 0; + readonly #albumTracksMax = 20; + readonly #albumTracksQueue: Array<() => void> = []; + readonly #countryCode: string; + readonly #clientId: string; + readonly #clientSecret: string; + readonly #emitter = new EventEmitter(); + + on(event: HiFiClientEvents.TokenUpdate, listener: (token: string | null) => void): void; + on(event: HiFiClientEvents.TokenExpiryUpdate, listener: (expiry: number) => void): void; + on(event: HiFiClientEvents.RefreshTokenUpdate, listener: (refreshToken: string | null) => void): void; + on(event: HiFiClientEvents, listener: (...args: any[]) => void) { + this.#emitter.addListener(HiFiClientEvents[event], listener); + } + + off(event: HiFiClientEvents, listener: (...args: any[]) => void) { + this.#emitter.removeListener(HiFiClientEvents[event], listener); + } + + #emit(event: HiFiClientEvents.TokenUpdate, token: string | null): void; + #emit(event: HiFiClientEvents.TokenExpiryUpdate, expiry: number): void; + #emit(event: HiFiClientEvents.RefreshTokenUpdate, refreshToken: string | null): void; + #emit(event: HiFiClientEvents, data: any) { + this.#emitter.emit(HiFiClientEvents[event], data); + } + + get token(): string | null { + return this.#token; + } + + private set token(value: string | null) { + this.#emit(HiFiClientEvents.TokenUpdate, (this.#token = value || null)); + } + + get refreshToken(): string | null { + return this.#refreshToken || null; + } + + private set refreshToken(value: string | null) { + this.#emit(HiFiClientEvents.RefreshTokenUpdate, (this.#refreshToken = value || null)); + } + + get appTokenExpiry() { + return this.#appTokenExpiry; + } + + private set appTokenExpiry(value: number) { + this.#emit(HiFiClientEvents.TokenExpiryUpdate, (this.#appTokenExpiry = value)); + + if (value >= 0 && value < Date.now()) { + this.token = null; + } + } + + #useStorage(storage: Pick) { + this.on(HiFiClientEvents.TokenUpdate, (token) => { + if (token) { + storage.setItem('hifi_token', token); + } else { + storage.removeItem('hifi_token'); + } + }); + this.on(HiFiClientEvents.TokenExpiryUpdate, (expiry) => { + if (expiry) { + storage.setItem('hifi_token_expiry', String(expiry)); + } else { + storage.removeItem('hifi_token_expiry'); + } + }); + } + + static #jsonResponse(data: any) { + return new Response(JSON.stringify(data), { + headers: { + 'Content-Type': 'application/json', + }, + }); + } + + static #buildUrl(base: string, params?: Params | URLSearchParams) { + if (!params) return base; + if (params instanceof URLSearchParams) { + const u = new URL(base); + u.search = params.toString(); + return u.toString(); + } + + const u = new URL(base); + Object.entries(params) + .filter(([, v]) => v !== undefined && v !== null && v !== '') + .forEach(([k, v]) => u.searchParams.set(k, String(v))); + return u.toString(); + } + + setToken({ token, tokenExpiry, refreshToken }: HiFiClient.TokenOptions & HiFiClient.RefreshTokenOptions) { + this.token = token; + this.appTokenExpiry = this.appTokenExpiry; + this.refreshToken = refreshToken; + } + + static #basicAuth(username: string, password: string) { + return 'Basic ' + btoa(`${username}:${password}`); + } + + async #fetchAppToken({ + clientId = BROWSER_CLIENT_ID, + clientSecret = BROWSER_CLIENT_SECRET, + refreshToken, + scope = 'r_usr+w_usr+w_sub', + signal = new AbortController().signal, + force = false, + }: HiFiClient.ClientOptions & + HiFiClient.RefreshTokenOptions & { + scope?: string; + signal?: AbortSignal; + force?: boolean; + }) { + if (!force && this.token && (this.appTokenExpiry < 0 || Date.now() < this.appTokenExpiry)) return this.token; + + return await (this.#tokenPromise ??= (async () => { + try { + const params = new URLSearchParams({ + client_id: clientId, + client_secret: clientSecret, + }); + + if (refreshToken) { + params.set('refresh_token', refreshToken); + params.set('grant_type', 'refresh_token'); + params.set('scope', scope); + } else { + params.set('grant_type', 'client_credentials'); + } + + const res = await fetch('https://auth.tidal.com/v1/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: HiFiClient.#basicAuth(clientId, clientSecret), + }, + body: params, + signal, + }); + + if (!res.ok) { + const txt = await res.text().catch(() => ''); + throw new Error(`Failed to obtain app token: ${res.status} ${txt}`); + } + + const json = await res.json(); + const token = json.access_token; + const expires_in = json.expires_in ?? 3600; + this.token = token; + this.appTokenExpiry = Date.now() + (expires_in - 60) * 1000; + + return token; + } finally { + this.#tokenPromise = null; + } + })()); + } + + static #getOptions({ + countryCode = 'US', + baseUrl = null, + clientId = BROWSER_CLIENT_ID, + clientSecret = BROWSER_CLIENT_SECRET, + token, + tokenExpiry, + refreshToken: tokenRefresh, + storage = [], + }: HiFiClient.ConstructorOptions = {}) { + return { countryCode, baseUrl, clientId, clientSecret, token, tokenExpiry, tokenRefresh, storage }; + } + + async #fetchAuthenticated( + url: string, + params?: Params | URLSearchParams, + signal: AbortSignal = new AbortController().signal + ): Promise { + const final = HiFiClient.#buildUrl(url, params); + let res: Response | undefined; + + while (true) { + const unauthorized = res?.status === 401; + const previousResponse = res; + const token = await await this.#fetchAppToken({ + clientId: this.#clientId, + clientSecret: this.#clientSecret, + signal, + refreshToken: this.refreshToken || undefined, + force: unauthorized, + }); + + res = await fetch(final, { + headers: { + authorization: `Bearer ${token}`, + }, + signal, + }); + + if (previousResponse && unauthorized && res.status === 401) { + throw new ResponseError(401, 'Unauthorized: Invalid or expired token'); + } + + if (res.status !== 401) break; + } + + if (!res.ok) { + throw new ResponseError(res.status, res.statusText); + } + + return res; + } + + async #fetchJson( + url: string, + params?: Params | URLSearchParams, + signal: AbortSignal = new AbortController().signal + ): Promise { + const res = await this.#fetchAuthenticated(url, params, signal); + + return res.json(); + } + + constructor(options: HiFiClient.ConstructorOptions = {}) { + const { countryCode, baseUrl, clientId, clientSecret, token, tokenExpiry, tokenRefresh, storage } = + HiFiClient.#getOptions(options); + this.#countryCode = countryCode; + this.#baseUrl = baseUrl; + this.#clientId = clientId; + this.#clientSecret = clientSecret; + this.token = token; + this.appTokenExpiry = tokenExpiry; + this.refreshToken = tokenRefresh; + + for (const store of !Array.isArray(storage) ? [storage] : storage) { + this.#useStorage(store); + } + } + + static async initialize(options: HiFiClient.ConstructorOptions & { signal?: AbortSignal } = {}) { + if (HiFiClient.#instance) { + throw new Error('HiFiClient is already initialized'); + } + + const instance = (HiFiClient.#instance = new HiFiClient(options)); + + if (!options.token && !options.clientId && !options.clientSecret) { + await instance.#fetchAppToken({ + ...options, + signal: options.signal || new AbortController().signal, + }); + } + + return (HiFiClient.#instance = instance); + } + + static #extractUuidFromTidalUrl(href?: string | null) { + if (!href) return null; + const parts = href.split('/'); + return parts.length >= 9 ? parts.slice(4, 9).join('-') : null; + } + + async #withAlbumTrackSlot(fn: () => Promise) { + if (this.#albumTracksActive >= this.#albumTracksMax) { + await new Promise((res) => this.#albumTracksQueue.push(res)); + } + this.#albumTracksActive++; + try { + return await fn(); + } finally { + this.#albumTracksActive--; + const next = this.#albumTracksQueue.shift(); + if (next) next(); + } + } + + async getInfo(id: number, signal?: AbortSignal) { + const url = `https://api.tidal.com/v1/tracks/${id}/`; + const data = await this.#fetchJson(url, { countryCode: this.#countryCode }, signal); + return HiFiClient.#jsonResponse({ version: API_VERSION, data }); + } + + async getTrack(id: number, quality = 'HI_RES_LOSSLESS', immersiveAudio: boolean = false, signal?: AbortSignal) { + const url = `https://api.tidal.com/v1/tracks/${id}/playbackinfo`; + const params = { + audioquality: quality, + playbackmode: 'STREAM', + assetpresentation: 'FULL', + countryCode: this.#countryCode, + immersiveAudio: String(immersiveAudio), + }; + const data = await this.#fetchJson(url, params, signal); + return HiFiClient.#jsonResponse({ version: API_VERSION, data }); + } + + async getTrackManifest( + id: number, + { + formats = ['HEAACV1', 'AACLC', 'FLAC', 'FLAC_HIRES', 'EAC3_JOC'], + adaptive = true, + manifestType = 'MPEG_DASH', + uriScheme = 'HTTPS', + usage = 'PLAYBACK', + }: HiFiClient.GetTrackManifestOptions = {}, + signal?: AbortSignal + ) { + const url = `https://openapi.tidal.com/v2/trackManifests/${id}`; + const params = new URLSearchParams({ + adaptive: String(adaptive), + manifestType, + uriScheme, + usage, + }); + + for (const format of formats) { + params.append('formats', format); + } + + const res = await this.#fetchJson(url, params, signal); + const drmData = res.data.attributes.drmData; + + if (drmData && this.#baseUrl) { + const url = `${this.#baseUrl.replace(/\/+$/g, '')}/widevine`; + drmData.licenseUrl = url; + drmData.certificateUrl = url; + } + + return HiFiClient.#jsonResponse({ version: API_VERSION, data: res }); + } + + async getWidevine() { + return await this.#fetchAuthenticated('https://api.tidal.com/v2/widevine'); + } + + async getRecommendations(id: number, signal?: AbortSignal) { + const url = `https://api.tidal.com/v1/tracks/${id}/recommendations`; + const data = await this.#fetchJson(url, { limit: '20', countryCode: this.#countryCode }, signal); + return HiFiClient.#jsonResponse({ version: API_VERSION, data }); + } + + async getSimilarArtists(id: number, cursor?: string | number | null, signal?: AbortSignal) { + const url = `https://openapi.tidal.com/v2/artists/${id}/relationships/similarArtists`; + const params: Params = { + 'page[cursor]': cursor ?? undefined, + countryCode: this.#countryCode, + include: 'similarArtists,similarArtists.profileArt', + }; + + const payload = await this.#fetchJson(url, params, signal); + const included = Array.isArray(payload?.included) ? payload.included : []; + const artists_map: Record = {}; + const artworks_map: Record = {}; + for (const i of included) { + if (i.type === 'artists') artists_map[i.id] = i; + if (i.type === 'artworks') artworks_map[i.id] = i; + } + + const resolveArtist = (entry: any) => { + const aid = entry.id; + const inc = artists_map[aid] || {}; + const attr = inc.attributes || {}; + + let pic_id: string | null = null; + const art_data = inc.relationships?.profileArt?.data; + if (Array.isArray(art_data) && art_data.length > 0) { + const artwork = artworks_map[art_data[0].id]; + const files = artwork?.attributes?.files; + if (Array.isArray(files) && files[0]?.href) { + pic_id = HiFiClient.#extractUuidFromTidalUrl(files[0].href); + } + } + + return { + ...attr, + id: String(aid).match(/^\d+$/) ? Number(aid) : aid, + picture: pic_id || attr.selectedAlbumCoverFallback, + url: `http://www.tidal.com/artist/${aid}`, + relationType: 'SIMILAR_ARTIST', + }; + }; + + return HiFiClient.#jsonResponse({ version: API_VERSION, artists: (payload?.data || []).map(resolveArtist) }); + } + + async getSimilarAlbums(id: number, cursor?: string | number | null, signal?: AbortSignal) { + const url = `https://openapi.tidal.com/v2/albums/${id}/relationships/similarAlbums`; + const params: Params = { + 'page[cursor]': cursor ?? undefined, + countryCode: this.#countryCode, + include: 'similarAlbums,similarAlbums.coverArt,similarAlbums.artists', + }; + + const payload = await this.#fetchJson(url, params, signal); + const included = Array.isArray(payload?.included) ? payload.included : []; + const albums_map: Record = {}; + const artworks_map: Record = {}; + const artists_map: Record = {}; + for (const i of included) { + if (i.type === 'albums') albums_map[i.id] = i; + if (i.type === 'artworks') artworks_map[i.id] = i; + if (i.type === 'artists') artists_map[i.id] = i; + } + + const resolveAlbum = (entry: any) => { + const aid = entry.id; + const inc = albums_map[aid] || {}; + const attr = inc.attributes || {}; + + let cover_id: string | null = null; + const art_data = inc.relationships?.coverArt?.data; + if (Array.isArray(art_data) && art_data.length > 0) { + const artwork = artworks_map[art_data[0].id]; + const files = artwork?.attributes?.files; + if (Array.isArray(files) && files[0]?.href) { + cover_id = HiFiClient.#extractUuidFromTidalUrl(files[0].href); + } + } + + const artist_list: any[] = []; + const artists_data = inc.relationships?.artists?.data; + if (Array.isArray(artists_data)) { + for (const a_entry of artists_data) { + const a_obj = artists_map[a_entry.id]; + if (a_obj) { + const a_id = a_obj.id; + artist_list.push({ + id: String(a_id).match(/^\d+$/) ? Number(a_id) : a_id, + name: a_obj.attributes?.name, + }); + } + } + } + + return { + ...attr, + id: String(aid).match(/^\d+$/) ? Number(aid) : aid, + cover: cover_id, + artists: artist_list, + url: `http://www.tidal.com/album/${aid}`, + }; + }; + + return HiFiClient.#jsonResponse({ version: API_VERSION, albums: (payload?.data || []).map(resolveAlbum) }); + } + + async getArtist( + id?: number | null, + f?: number | null, + skip_tracks = false, + signal?: AbortSignal, + options?: { offset?: number; limit?: number } + ) { + if (!id && !f) throw new ResponseError(400, 'Provide id or f query param'); + + if (id) { + const artist_url = `https://api.tidal.com/v1/artists/${id}`; + const artist_data = await this.#fetchJson(artist_url, { countryCode: this.#countryCode }, signal); + + let picture = artist_data.picture; + const fallback = artist_data.selectedAlbumCoverFallback; + if (!picture && fallback) { + artist_data.picture = fallback; + picture = fallback; + } + + let cover = null; + if (picture) { + const slug = picture.replace(/-/g, '/'); + cover = { + id: artist_data.id, + name: artist_data.name, + '750': `https://resources.tidal.com/images/${slug}/750x750.jpg`, + }; + } + + return HiFiClient.#jsonResponse({ version: API_VERSION, artist: artist_data, cover }); + } + + // f provided -> gather albums and optionally tracks + const albums_url = `https://api.tidal.com/v1/artists/${f}/albums`; + const common_params: Params = { countryCode: this.#countryCode, limit: 50 }; + + const tasks: Promise[] = [ + this.#fetchJson(albums_url, common_params, signal), + this.#fetchJson(albums_url, { ...common_params, filter: 'EPSANDSINGLES' }, signal), + ]; + + if (skip_tracks) { + const offset = options?.offset; + const limit = options?.limit; + const toptracks_params: Params = { countryCode: this.#countryCode, limit: limit || 15 }; + if (offset !== undefined) { + toptracks_params.offset = offset; + } + tasks.push(this.#fetchJson(`https://api.tidal.com/v1/artists/${f}/toptracks`, toptracks_params, signal)); + } + + const results = await Promise.all(tasks.map((p) => p.catch((e) => e))); + + const unique_releases: any[] = []; + const seen_ids = new Set(); + + for (const res of results.slice(0, 2)) { + if (res && !(res instanceof Error)) { + const data = res; + const items = Array.isArray(data?.items) ? data.items : data || []; + if (Array.isArray(items)) { + for (const item of items) { + if (item && item.id && !seen_ids.has(item.id)) { + unique_releases.push(item); + seen_ids.add(item.id); + } + } + } + } + } + + const album_ids: number[] = unique_releases.map((i) => i.id).filter(Boolean); + const page_data = { items: unique_releases }; + + if (skip_tracks) { + let top_tracks: any[] = []; + if (results.length > 2) { + const res = results[2]; + if (res && !(res instanceof Error)) { + top_tracks = Array.isArray(res.items) ? res.items : res || []; + } + } + + return HiFiClient.#jsonResponse({ version: API_VERSION, albums: page_data, tracks: top_tracks }); + } + + if (!album_ids.length) return HiFiClient.#jsonResponse({ version: API_VERSION, albums: page_data, tracks: [] }); + + const fetchAlbumTracks = async (album_id: number) => { + return await this.#withAlbumTrackSlot(async () => { + const album_data = await this.#fetchJson( + 'https://api.tidal.com/v1/pages/album', + { albumId: album_id, countryCode: this.#countryCode, deviceType: 'BROWSER' }, + signal + ); + const rows = Array.isArray(album_data?.rows) ? album_data.rows : []; + if (rows.length < 2) return []; + const modules = rows[1].modules || []; + if (!modules || modules.length === 0) return []; + const paged_list = modules[0].pagedList || {}; + const items = paged_list.items || []; + const tracks = items.map((t: any) => (t.item ? t.item : t)); + return tracks; + }); + }; + + const trackResults = await Promise.all(album_ids.map((aid) => fetchAlbumTracks(aid).catch(() => []))); + const tracks: any[] = []; + for (const t of trackResults) { + if (Array.isArray(t)) tracks.push(...t); + } + + return HiFiClient.#jsonResponse({ version: API_VERSION, albums: page_data, tracks }); + } + + #buildCoverEntry(cover_slug: string, name?: string | null, track_id?: number | null) { + const slug = cover_slug.replace(/-/g, '/'); + return { + id: track_id, + name, + '1280': `https://resources.tidal.com/images/${slug}/1280x1280.jpg`, + '640': `https://resources.tidal.com/images/${slug}/640x640.jpg`, + '80': `https://resources.tidal.com/images/${slug}/80x80.jpg`, + }; + } + + async getCover(id?: number | null, q?: string | null, signal?: AbortSignal) { + if (!id && !q) throw new ResponseError(400, 'Provide id or q query param'); + + if (id) { + const track_data = await this.#fetchJson( + `https://api.tidal.com/v1/tracks/${id}/`, + { countryCode: this.#countryCode }, + signal + ); + const album = track_data.album || {}; + const cover_slug = album.cover; + if (!cover_slug) throw new ResponseError(404, 'Cover not found'); + const entry = this.#buildCoverEntry(cover_slug, album.title || track_data.title, album.id || id); + return HiFiClient.#jsonResponse({ version: API_VERSION, covers: [entry] }); + } + + const search_data = await this.#fetchJson( + 'https://api.tidal.com/v1/search/tracks', + { countryCode: this.#countryCode, query: q, limit: 10 }, + signal + ); + const items = Array.isArray(search_data?.items) ? search_data.items.slice(0, 10) : []; + if (!items.length) throw new ResponseError(404, 'Cover not found'); + const covers: any[] = []; + for (const track of items) { + const album = track.album || {}; + const cover_slug = album.cover; + if (!cover_slug) continue; + covers.push(this.#buildCoverEntry(cover_slug, track.title, track.id)); + } + if (!covers.length) throw new ResponseError(404, 'Cover not found'); + return HiFiClient.#jsonResponse({ version: API_VERSION, covers }); + } + + async search( + options: { + q?: string; + s?: string; + a?: string; + al?: string; + v?: string; + p?: string; + i?: string; + offset?: number; + limit?: number; + }, + signal?: AbortSignal + ) { + const { q, s, a, al, v, p, i, offset = 0, limit = 25 } = options; + + if (i) { + // try filtered track search first + try { + const res = await this.#fetchJson( + 'https://api.tidal.com/v1/tracks', + { + 'filter[isrc]': i, + limit, + offset, + countryCode: this.#countryCode, + }, + signal + ); + return HiFiClient.#jsonResponse({ version: API_VERSION, data: res }); + } catch (err: any) { + if (err.status && ![400, 404].includes(err.status)) throw err; + // fallback to text search + } + const fallback = await this.#fetchJson( + 'https://api.tidal.com/v1/search/tracks', + { + query: i, + limit, + offset, + countryCode: this.#countryCode, + }, + signal + ); + return HiFiClient.#jsonResponse({ version: API_VERSION, data: fallback }); + } + + const mapping: Array<[string | undefined, string, Params]> = [ + [ + q, + 'https://api.tidal.com/v1/search', + { + query: q, + limit, + offset, + types: 'ARTISTS,ALBUMS,TRACKS,VIDEOS,PLAYLISTS', + countryCode: this.#countryCode, + }, + ], + [s, 'https://api.tidal.com/v1/search/tracks', { query: s, limit, offset, countryCode: this.#countryCode }], + [ + a, + 'https://api.tidal.com/v1/search/top-hits', + { query: a, limit, offset, types: 'ARTISTS,TRACKS', countryCode: this.#countryCode }, + ], + [ + al, + 'https://api.tidal.com/v1/search/top-hits', + { query: al, limit, offset, types: 'ALBUMS', countryCode: this.#countryCode }, + ], + [ + v, + 'https://api.tidal.com/v1/search/top-hits', + { query: v, limit, offset, types: 'VIDEOS', countryCode: this.#countryCode }, + ], + [ + p, + 'https://api.tidal.com/v1/search/top-hits', + { query: p, limit, offset, types: 'PLAYLISTS', countryCode: this.#countryCode }, + ], + ]; + + for (const [val, url, params] of mapping) { + if (val) { + const data = await this.#fetchJson(url, params, signal); + return HiFiClient.#jsonResponse({ version: API_VERSION, data }); + } + } + + throw new Error('Provide one of s, a, al, v, p, or i'); + } + + async getAlbum(id: number, limit = 100, offset = 0, signal?: AbortSignal) { + const albumUrl = `https://api.tidal.com/v1/albums/${id}`; + const itemsUrl = `https://api.tidal.com/v1/albums/${id}/items`; + const tasks: Promise[] = [this.#fetchJson(albumUrl, { countryCode: this.#countryCode }, signal)]; + + let remaining = limit; + let currentOffset = offset; + const maxChunk = 100; + while (remaining > 0) { + const chunk = Math.min(remaining, maxChunk); + tasks.push( + this.#fetchJson( + itemsUrl, + { countryCode: this.#countryCode, limit: chunk, offset: currentOffset }, + signal + ) + ); + currentOffset += chunk; + remaining -= chunk; + } + + const results = await Promise.all(tasks); + const albumData = results[0]; + const pages = results.slice(1); + const allItems: any[] = []; + for (const p of pages) { + const pageItems = (p && p.items) || p; + if (Array.isArray(pageItems)) allItems.push(...pageItems); + } + albumData.items = allItems; + return HiFiClient.#jsonResponse({ version: API_VERSION, data: albumData }); + } + + async getMix(id: string, signal?: AbortSignal) { + const url = 'https://api.tidal.com/v1/pages/mix'; + const data = await this.#fetchJson( + url, + { mixId: id, countryCode: this.#countryCode, deviceType: 'BROWSER' }, + signal + ); + let header = {}, + items: any[] = []; + const rows = data.rows || []; + for (const row of rows) { + for (const module of row.modules || []) { + if (module.type === 'MIX_HEADER') header = module.mix || {}; + if (module.type === 'TRACK_LIST') items = (module.pagedList || {}).items || []; + } + } + return HiFiClient.#jsonResponse({ + version: API_VERSION, + mix: header, + items: items.map((it: any) => (it.item ? it.item : it)), + }); + } + + async getPlaylist(id: string, limit = 100, offset = 0, signal?: AbortSignal) { + const playlistUrl = `https://api.tidal.com/v1/playlists/${id}`; + const itemsUrl = `https://api.tidal.com/v1/playlists/${id}/items`; + const [playlistData, itemsData] = await Promise.all([ + this.#fetchJson(playlistUrl, { countryCode: this.#countryCode }, signal), + this.#fetchJson(itemsUrl, { countryCode: this.#countryCode, limit, offset }, signal), + ]); + const items = (itemsData && itemsData.items) || itemsData; + return HiFiClient.#jsonResponse({ version: API_VERSION, playlist: playlistData, items }); + } + + // simplified artist/cover/lyrics/video/topvideos/similar methods (same pattern) + async getLyrics(id: number, signal?: AbortSignal) { + const url = `https://api.tidal.com/v1/tracks/${id}/lyrics`; + const data = await this.#fetchJson( + url, + { countryCode: this.#countryCode, locale: 'en_US', deviceType: 'BROWSER' }, + signal + ); + if (!data) { + const err: any = new Error('Lyrics not found'); + err.status = 404; + throw err; + } + return HiFiClient.#jsonResponse({ version: API_VERSION, lyrics: data }); + } + + async getVideo(id: number, quality = 'HIGH', mode = 'STREAM', presentation = 'FULL', signal?: AbortSignal) { + const url = `https://api.tidal.com/v1/videos/${id}/playbackinfo`; + const data = await this.#fetchJson( + url, + { videoquality: quality, playbackmode: mode, assetpresentation: presentation }, + signal + ); + return HiFiClient.#jsonResponse({ version: API_VERSION, video: data }); + } + + async getTopVideos( + { countryCode = 'US', locale = 'en_US', deviceType = 'BROWSER', limit = 25, offset = 0 } = {}, + signal?: AbortSignal + ) { + const url = 'https://api.tidal.com/v1/pages/mymusic_recommended_videos'; + const data = await this.#fetchJson(url, { countryCode, locale, deviceType }, signal); + const rows = data.rows || []; + const videos: any[] = []; + for (const row of rows) { + for (const module of row.modules || []) { + const mt = module.type; + if (['VIDEO_PLAYLIST', 'VIDEO_ROW', 'PAGED_LIST'].includes(mt)) { + const items = (module.pagedList || {}).items || []; + for (const item of items) videos.push(item.item || item); + } else if (mt === 'VIDEO' || (mt && mt.toLowerCase().includes('video'))) { + const it = module.item || module; + if (typeof it === 'object') videos.push(it); + } + } + } + return HiFiClient.#jsonResponse({ + version: API_VERSION, + videos: videos.slice(offset, offset + limit), + total: videos.length, + }); + } + + // generic helper that accepts local route strings like "/info/?id=123" or full URLs + async query(pathOrUrl: string, signal?: AbortSignal) { + // normalize: if starts with http use as-is, else treat as local route + try { + const u = new URL(pathOrUrl, 'http://localhost'); + const pathname = u.pathname.replace(/\/+$/, '') || '/'; + const qp: Record = {}; + u.searchParams.forEach((v, k) => (qp[k] = v)); + const formats = u.searchParams.getAll('formats'); + + switch (pathname) { + case '/': + return new TidalResponse( + HiFiClient.#jsonResponse({ version: API_VERSION, Repo: 'https://github.com/binimum/hifi-api' }) + ); + case '/info': + return new TidalResponse(await this.getInfo(Number(qp.id))); + case '/track': + return new TidalResponse(await this.getTrack(Number(qp.id), qp.quality || undefined)); + case '/recommendations': + return new TidalResponse(await this.getRecommendations(Number(qp.id))); + case '/artist/similar': + return new TidalResponse( + await this.getSimilarArtists(Number(qp.id), qp.cursor ?? undefined, signal) + ); + case '/album/similar': + return new TidalResponse( + await this.getSimilarAlbums(Number(qp.id), qp.cursor ?? undefined, signal) + ); + case '/artist': + return new TidalResponse( + await this.getArtist( + qp.id ? Number(qp.id) : undefined, + qp.f ? Number(qp.f) : undefined, + qp.skip_tracks === 'true' || qp.skip_tracks === '1' || qp.skip_tracks === 'True', + signal, + { + offset: qp.offset !== undefined ? Number(qp.offset) : undefined, + limit: qp.limit !== undefined ? Number(qp.limit) : undefined, + } + ) + ); + case '/cover': + return new TidalResponse( + await this.getCover(qp.id ? Number(qp.id) : undefined, qp.q ?? undefined, signal) + ); + case '/search': + return new TidalResponse( + await this.search({ + q: qp.q, + s: qp.s, + a: qp.a, + al: qp.al, + v: qp.v, + p: qp.p, + i: qp.i, + offset: qp.offset ? Number(qp.offset) : undefined, + limit: qp.limit ? Number(qp.limit) : undefined, + }) + ); + case '/album': + return new TidalResponse( + await this.getAlbum( + Number(qp.id), + qp.limit ? Number(qp.limit) : undefined, + qp.offset ? Number(qp.offset) : undefined + ) + ); + case '/playlist': + return new TidalResponse( + await this.getPlaylist( + qp.id || '', + qp.limit ? Number(qp.limit) : undefined, + qp.offset ? Number(qp.offset) : undefined + ) + ); + case '/mix': + return new TidalResponse(await this.getMix(qp.id || '')); + case '/lyrics': + return new TidalResponse(await this.getLyrics(Number(qp.id))); + case '/video': + return new TidalResponse( + await this.getVideo( + Number(qp.id), + qp.quality || undefined, + qp.mode || undefined, + qp.presentation || undefined + ) + ); + case '/topvideos': + return new TidalResponse( + await this.getTopVideos({ + countryCode: qp.countryCode || undefined, + locale: qp.locale || undefined, + deviceType: qp.deviceType || undefined, + limit: qp.limit ? Number(qp.limit) : undefined, + offset: qp.offset ? Number(qp.offset) : undefined, + }) + ); + case '/trackManifests': + return new TidalResponse( + await this.getTrackManifest(Number(qp.id), { + ...qp, + formats: formats.length > 0 ? formats : undefined, + adaptive: Boolean(qp.adaptive?.toLowerCase()) || undefined, + }) + ); + case '/widevine': + return new TidalResponse(await this.getWidevine()); + default: + throw new Error(`Unknown route: ${pathname}`); + } + } catch (err) { + console.error(err?.message || err, err?.message ? err : undefined); + throw err; + } + } +} + +namespace HiFiClient { + export interface RefreshTokenOptions { + refreshToken?: string; + } + + export interface TokenOptions { + token?: string; + tokenExpiry?: number; + } + + export interface ClientOptions { + clientId?: string; + clientSecret?: string; + } + + export interface ConstructorOptions extends ClientOptions, TokenOptions, RefreshTokenOptions { + countryCode?: string; + baseUrl?: string; + storage?: Pick[] | Pick; + } + + export interface GetTrackManifestOptions { + formats?: string[]; + adaptive?: boolean; + manifestType?: string; + uriScheme?: 'HTTPS' | 'HTTP'; + usage?: string; + } +} + +export { HiFiClient }; diff --git a/js/METADATA_STRINGS.js b/js/METADATA_STRINGS.js new file mode 100644 index 000000000..5b8aa2558 --- /dev/null +++ b/js/METADATA_STRINGS.js @@ -0,0 +1,6 @@ +export const METADATA_STRINGS = { + VENDOR_STRING: 'Monochrome', + DEFAULT_TITLE: 'Unknown Title', + DEFAULT_ARTIST: 'Unknown Artist', + DEFAULT_ALBUM: 'Unknown Album', +}; diff --git a/js/ModernSettings.ts b/js/ModernSettings.ts new file mode 100644 index 000000000..de90cdc2a --- /dev/null +++ b/js/ModernSettings.ts @@ -0,0 +1,289 @@ +import { db } from './db'; + +/** + * A dynamically typed settings container that lazily loads and persists values. + * + * Properties are registered using {@link addProperty}. Each property becomes a real + * getter/setter on the instance and is automatically persisted through the backing + * `db` implementation. + * + * All asynchronous reads/writes are tracked internally. Use {@link waitPending} + * to await completion of any pending operations. + * + * @template C The accumulated shape of the settings object. + */ +class ModernSettings { + /** Internal map of pending async operations keyed by unique symbols. */ + #pending: Record> = {}; + + /** Whether new properties are prevented from being added. */ + #finalized: boolean = false; + + constructor() {} + + /** + * Waits until all pending asynchronous operations complete. + * + * This includes: + * - Initial property loading + * - Any pending writes triggered by property setters + * + * This method loops until the pending operation list is empty, ensuring + * that operations scheduled during awaiting are also handled. + */ + public async waitPending() { + while (true) { + const promises = Object.getOwnPropertySymbols(this.#pending).map((s) => this.#pending[s]); + + if (promises.length) { + await Promise.all(promises); + } else { + break; + } + } + } + + /** + * Registers a promise as a pending operation. + * + * The promise is automatically removed from the pending list once settled. + * + * @param callback Function producing the promise to track. + * @returns The created promise. + */ + #addPending>(callback: () => C): C { + const sym = Symbol(); + + return (this.#pending[sym] = callback().finally(() => { + delete this.#pending[sym]; + }) as C); + } + + #checkKey(key: string) { + if (this.#finalized) { + throw new Error("Can't add a key after finalization."); + } + + if (Object.keys(this).includes(key)) { + throw new Error("Can't add a key that already exists."); + } + } + + /** + * Adds a new dynamically typed property to the settings instance. + * + * The property will: + * - Load its value asynchronously from the backing database. + * - Fall back to `defaultValue` if no value exists. + * - Persist any updates automatically when set. + * + * The method returns the same instance but **with the new property added to + * the TypeScript type**, allowing fluent chaining with full type safety. + * + * Example: + * ```ts + * const settings = new ModernSettings() + * .addProperty("darkMode", false) + * .addProperty("username", "") + * .finalize(); + * + * await settings.waitPending(); + * + * settings.darkMode = true; + * console.log(settings.username); + * ``` + * + * @template T Property value type. + * @template K Property key name. + * + * @param key The property name to define on the settings object. + * @param defaultValue Value used if the setting is not present in storage. + * @param options Optional configuration. + * + * @param options.backingKey + * Optional storage key. Defaults to the property name. + * + * @param options.legacy + * Optional migration configuration for moving a value from `localStorage` + * into the database-backed settings store. + * + * @param options.legacy.key + * Legacy key to read from `localStorage`. Defaults to the same key used for storage. + * + * @param options.legacy.transformer + * Function used to convert the legacy string value into the correct type. + * + * @returns The same instance typed with the new property included. + * + * @throws If called after {@link finalize}. + * @throws If a property with the same name already exists. + */ + public addProperty( + key: K, + defaultValue: T, + options?: { + backingKey?: string; + getter?: (value: T, settings: C & Record) => T; + setter?: (value: T, settings: C & Record) => T; + legacy?: { + key?: string; + transformer: (value: string) => T; + }; + } + ) { + const { backingKey, legacy, getter, setter } = options ?? {}; + + this.#checkKey(key); + + const typed = this as unknown as ModernSettings>; + + let value: T; + + this.#addPending(async () => { + if (legacy?.key != null || legacy?.transformer != null) { + { + const legacyValue = localStorage.getItem(legacy?.key ?? backingKey ?? key); + + if (legacyValue !== null) { + db.saveSetting(backingKey ?? key, legacy.transformer!(legacyValue)); + localStorage.removeItem(legacy?.key ?? backingKey ?? key); + } + } + } + + try { + value = (await db.getSetting(backingKey ?? key)) ?? defaultValue; + } catch { + value = defaultValue; + } + }).catch(console.trace); + + Object.defineProperty(this, key, { + get: () => (getter ? getter(value, typed as ModernSettings & C & Record) : value), + set: (newValue: T) => { + value = setter ? setter(newValue, typed as ModernSettings & C & Record) : newValue; + this.#addPending(() => db.saveSetting(backingKey ?? key, value)); + }, + enumerable: true, + }); + + return typed; + } + + public addGetter(key: K, getter: (settings: ModernSettings) => R) { + this.#checkKey(key); + const typed = this as unknown as ModernSettings>> & C & Readonly>; + + Object.defineProperty(this, key, { + get: () => getter(typed), + enumerable: true, + }); + + return typed; + } + + /** + * Prevents further properties from being added. + * + * This is typically called once all `addProperty` calls are complete, + * ensuring the settings schema is fixed. + * + * @returns The settings instance. + */ + public finalize() { + this.#finalized = true; + return this; + } +} + +export enum BulkDownloadMethod { + Zip = 'zip', + Folder = 'folder', + Individual = 'individual', + LocalMedia = 'local', +} + +export const modernSettings = new ModernSettings() + .addProperty('bulkDownloadFolder', null as FileSystemDirectoryHandle | null) + .addProperty('forceZipBlob', false, { + legacy: { + key: 'bulk-download-force-zip-blob', + transformer: Boolean, + }, + }) + .addProperty('rememberBulkDownloadFolder', false, { + legacy: { + key: 'bulk-download-remember-folder', + transformer: Boolean, + }, + }) + .addProperty('downloadSinglesToFolder', false, { + legacy: { + key: 'bulk-download-single-to-folder', + transformer: Boolean, + }, + }) + .addProperty('force-individual-downloads', false, { + legacy: { + transformer: Boolean, + }, + }) + .addProperty('bulkDownloadMethod', 'zip' as BulkDownloadMethod, { + getter: (stored, settings) => { + try { + if (stored && Object.values(BulkDownloadMethod).includes(stored)) { + return stored; + } + + const legacy = settings['force-individual-downloads']; + if (legacy) { + settings['force-individual-downloads'] = false; + return (settings.bulkDownloadMethod = BulkDownloadMethod.Individual); + } + + return BulkDownloadMethod.Zip; + } catch { + return BulkDownloadMethod.Zip; + } + }, + }) + .addProperty('folderTemplate', '', { + getter: (stored) => stored || '{albumTitle} - {albumArtist}', + legacy: { + key: 'zip-folder-template', + transformer: String, + }, + }) + .addProperty('filenameTemplate', '', { + getter: (stored) => stored || '{trackNumber} - {artist} - {title}', + legacy: { + key: 'filename-template', + transformer: String, + }, + }) + .finalize() as ModernSettings & { + /** The last used directory handle for bulk downloads */ + bulkDownloadFolder: FileSystemDirectoryHandle | null; + + /** Force ZIP blobs for bulk downloads even if file system APIs are available */ + forceZipBlob: boolean; + + /** Whether the Folder Picker should remember the last-used directory handle */ + rememberBulkDownloadFolder: boolean; + + /** + * Whether single-track downloads should be routed to the configured + * folder (saved Folder Picker handle or Local Media Folder path) + * instead of triggering a browser download. + */ + downloadSinglesToFolder: boolean; + + /** The selected bulk download method */ + bulkDownloadMethod: BulkDownloadMethod; + + /** Path template for bulk downloads */ + folderTemplate: string; + + /** Filename template for downloads */ + filenameTemplate: string; +}; diff --git a/js/accounts/auth.js b/js/accounts/auth.js index a5df058db..8fd23df93 100644 --- a/js/accounts/auth.js +++ b/js/accounts/auth.js @@ -58,6 +58,45 @@ export class AuthManager { } } + async signInWithGitHub() { + try { + auth.createOAuth2Session( + 'github', + window.location.origin + '/index.html?oauth=1', + window.location.origin + '/login.html' + ); + } catch (error) { + console.error('Login failed:', error); + alert(`Login failed: ${error.message}`); + } + } + + async signInWithSpotify() { + try { + auth.createOAuth2Session( + 'spotify', + window.location.origin + '/index.html?oauth=1', + window.location.origin + '/login.html' + ); + } catch (error) { + console.error('Login failed:', error); + alert(`Login failed: ${error.message}`); + } + } + + async signInWithDiscord() { + try { + auth.createOAuth2Session( + 'discord', + window.location.origin + '/index.html?oauth=1', + window.location.origin + '/login.html' + ); + } catch (error) { + console.error('Login failed:', error); + alert(`Login failed: ${error.message}`); + } + } + async signInWithEmail(email, password) { try { await auth.createEmailPasswordSession(email, password); @@ -89,7 +128,7 @@ export class AuthManager { async sendPasswordReset(email) { try { - await auth.createRecovery(email, window.location.origin + '/reset-password.html'); + await auth.createRecovery(email, window.location.origin + '/reset-password'); alert(`Password reset email sent to ${email}`); } catch (error) { console.error('Password reset failed:', error); @@ -122,6 +161,8 @@ export class AuthManager { const statusText = document.getElementById('auth-status'); const emailContainer = document.getElementById('email-auth-container'); const emailToggleBtn = document.getElementById('toggle-email-auth-btn'); + const githubBtn = document.getElementById('auth-github-btn'); + const discordBtn = document.getElementById('auth-discord-btn'); if (!connectBtn) return; @@ -132,6 +173,8 @@ export class AuthManager { if (clearDataBtn) clearDataBtn.style.display = 'none'; if (emailContainer) emailContainer.style.display = 'none'; if (emailToggleBtn) emailToggleBtn.style.display = 'none'; + if (githubBtn) githubBtn.style.display = 'none'; + if (discordBtn) discordBtn.style.display = 'none'; if (statusText) statusText.textContent = user ? `Signed in as ${user.email}` : 'Signed in'; const accountPage = document.getElementById('page-account'); @@ -165,6 +208,8 @@ export class AuthManager { if (clearDataBtn) clearDataBtn.style.display = 'block'; if (emailContainer) emailContainer.style.display = 'none'; if (emailToggleBtn) emailToggleBtn.style.display = 'none'; + if (githubBtn) githubBtn.style.display = 'none'; + if (discordBtn) discordBtn.style.display = 'none'; if (statusText) statusText.textContent = `Signed in as ${user.email}`; } else { connectBtn.textContent = 'Connect with Google'; @@ -173,6 +218,14 @@ export class AuthManager { if (clearDataBtn) clearDataBtn.style.display = 'none'; if (emailToggleBtn) emailToggleBtn.style.display = 'inline-block'; + if (githubBtn) { + githubBtn.style.display = 'inline-block'; + githubBtn.onclick = () => this.signInWithGitHub(); + } + if (discordBtn) { + discordBtn.style.display = 'inline-block'; + discordBtn.onclick = () => this.signInWithDiscord(); + } if (statusText) statusText.textContent = 'Sync your library across devices'; } } diff --git a/js/accounts/pocketbase.js b/js/accounts/pocketbase.js index e70b86023..79c793c86 100644 --- a/js/accounts/pocketbase.js +++ b/js/accounts/pocketbase.js @@ -5,7 +5,8 @@ import { authManager } from './auth.js'; const PUBLIC_COLLECTION = 'public_playlists'; const DEFAULT_POCKETBASE_URL = 'https://data.samidy.xyz'; -const POCKETBASE_URL = localStorage.getItem('monochrome-pocketbase-url') || DEFAULT_POCKETBASE_URL; +const POCKETBASE_URL = + window.__POCKETBASE_URL__ || localStorage.getItem('monochrome-pocketbase-url') || DEFAULT_POCKETBASE_URL; console.log('[PocketBase] Using URL:', POCKETBASE_URL); @@ -224,6 +225,10 @@ const syncManager = { streamStartDate: item.streamStartDate || null, version: item.version || null, mixes: item.mixes || null, + isPodcast: item.isPodcast || (item.id && String(item.id).startsWith('podcast_')) || null, + enclosureUrl: item.enclosureUrl || null, + enclosureType: item.enclosureType || null, + enclosureLength: item.enclosureLength || null, }; } @@ -303,6 +308,13 @@ const syncManager = { await this._updateUserJSON(user.$id, 'history', newHistory); }, + async clearHistory() { + const user = authManager.user; + if (!user) return; + + await this._updateUserJSON(user.$id, 'history', []); + }, + async syncUserPlaylist(playlist, action) { const user = authManager.user; if (!user) return; diff --git a/js/api.js b/js/api.js index d1ed2557f..94bda75c0 100644 --- a/js/api.js +++ b/js/api.js @@ -5,17 +5,36 @@ import { delay, isTrackUnavailable, getExtensionFromBlob, + getTrackTitle, + getFullArtistString, + getTrackDiscNumber, + getMimeType, } from './utils.js'; -import { trackDateSettings, losslessContainerSettings } from './storage.js'; +import { trackDateSettings } from './storage.js'; import { APICache } from './cache.js'; -import { addMetadataToAudio, prefetchMetadataObjects } from './metadata.js'; -import { DashDownloader } from './dash-downloader.js'; +import { DashDownloader } from './dash-downloader.ts'; import { HlsDownloader } from './hls-downloader.js'; -import { encodeToMp3, MP3EncodingError } from './mp3-encoder.js'; -import { ffmpeg, loadFfmpeg } from './ffmpeg.js'; -import { rebuildFlacWithoutMetadata } from './metadata.flac.js'; +import { MP3EncodingError } from './mp3-encoder.js'; +import { loadFfmpeg, FfmpegError, ffmpeg } from './ffmpeg.js'; +import { triggerDownload, applyAudioPostProcessing } from './download-utils.ts'; +import { isCustomFormat } from './ffmpegFormats.ts'; +import { DownloadProgress } from './progressEvents.js'; +import { resolveDownloadTotalBytes } from './downloadProgressUtils.js'; +import { readableStreamIterator } from './readableStreamIterator.js'; +import { HiFiClient, TidalResponse } from './HiFi.ts'; +import { isIos, isSafari } from './platform-detection.js'; +import { + TrackAlbum, + EnrichedAlbum, + EnrichedTrack, + ReplayGain, + PlaybackInfo, + Track, + Album, +} from './container-classes.js'; export const DASH_MANIFEST_UNAVAILABLE_CODE = 'DASH_MANIFEST_UNAVAILABLE'; +export { resolveDownloadTotalBytes }; const TIDAL_V2_TOKEN = 'txNoH4kkV41MfH25'; function isCapacitorMode() { @@ -55,6 +74,30 @@ export class LosslessAPI { async fetchWithRetry(relativePath, options = {}) { const type = options.type || 'api'; + const instanceRoutes = [ + '/track', + '/album/similar', + '/artist/similar', + '/video', + '/recommendations', + '/trackManifests', + ]; + + if (window.allTidal == true || !instanceRoutes.some((route) => relativePath.startsWith(route))) { + try { + if (import.meta.env.DEV) { + console.log(relativePath); + } + + return await HiFiClient.instance.query(relativePath); + } catch (err) { + console.warn( + `Direct fetch failed for ${relativePath}. Falling back to configured API instances...`, + err + ); + } + } + let instances = await this.settings.getInstances(type); if (instances.length === 0) { throw new Error(`No API instances configured for type: ${type}`); @@ -181,7 +224,7 @@ export class LosslessAPI { if (track.type && typeof track.type === 'string') { const lowType = track.type.toLowerCase(); - if (lowType === 'video' || lowType === 'track') { + if (lowType.includes('video') || lowType.includes('track')) { normalized = { ...track, type: lowType }; } } @@ -404,6 +447,75 @@ export class LosslessAPI { return Array.from(unique.values()); } + async search(query, options = {}) { + const cached = await this.cache.get('search_all', query); + if (cached) return cached; + + try { + const response = await this.fetchWithRetry(`/search/?q=${encodeURIComponent(query)}`, options); + const data = await response.json(); + + // Check if backend returned an error or if this looks like individual fallback + if (data.error || (!data.tracks && !data.artists && !data.albums && (!data.data || !data.data.tracks))) { + throw new Error('Fallback to individual searches'); + } + + const extractSection = (key) => this.normalizeSearchResponse(data, key); + + const tracksData = extractSection('tracks'); + const artistsData = extractSection('artists'); + const albumsData = extractSection('albums'); + const playlistsData = extractSection('playlists'); + const videosData = extractSection('videos'); + + const results = { + tracks: { + ...tracksData, + items: tracksData.items.map((t) => this.prepareTrack(t)), + }, + artists: { + ...artistsData, + items: artistsData.items.map((a) => this.prepareArtist(a)), + }, + albums: { + ...albumsData, + items: albumsData.items.map((a) => this.prepareAlbum(a)), + }, + playlists: playlistsData + ? { + ...playlistsData, + items: playlistsData.items.map((p) => this.preparePlaylist(p)), + } + : { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, + videos: { + ...videosData, + items: videosData.items.map((v) => this.prepareTrack(v)), + }, + }; + + await this.cache.set('search_all', query, results); + + return results; + } catch (error) { + // Fallback to individual searches if the backend proxy doesn't support ?q= or throws + const [tracks, videos, artists, albums, playlists] = await Promise.all([ + this.searchTracks(query, options).catch(() => ({ items: [] })), + this.searchVideos(query, options).catch(() => ({ items: [] })), + this.searchArtists(query, options).catch(() => ({ items: [] })), + this.searchAlbums(query, options).catch(() => ({ items: [] })), + this.searchPlaylists(query, options).catch(() => ({ items: [] })), + ]); + + return { + tracks, + videos, + artists, + albums, + playlists, + }; + } + } + async searchTracks(query, options = {}) { const cached = await this.cache.get('search_tracks', query); if (cached) return cached; @@ -420,7 +532,9 @@ export class LosslessAPI { items: preparedTracks, }; - await this.cache.set('search_tracks', query, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('search_tracks', query, result); + } return result; } catch (error) { if (error.name === 'AbortError') throw error; @@ -442,7 +556,9 @@ export class LosslessAPI { items: normalized.items.map((a) => this.prepareArtist(a)), }; - await this.cache.set('search_artists', query, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('search_artists', query, result); + } return result; } catch (error) { if (error.name === 'AbortError') throw error; @@ -465,7 +581,9 @@ export class LosslessAPI { items: this.deduplicateAlbums(preparedItems), }; - await this.cache.set('search_albums', query, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('search_albums', query, result); + } return result; } catch (error) { if (error.name === 'AbortError') throw error; @@ -487,7 +605,9 @@ export class LosslessAPI { items: normalized.items.map((p) => this.preparePlaylist(p)), }; - await this.cache.set('search_playlists', query, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('search_playlists', query, result); + } return result; } catch (error) { if (error.name === 'AbortError') throw error; @@ -503,7 +623,6 @@ export class LosslessAPI { try { const response = await this.fetchWithRetry(`/search/?v=${encodeURIComponent(query)}`, { ...options, - allowedDomains: ['api.monochrome.tf', 'arran.monochrome.tf'], }); const data = await response.json(); const normalized = this.normalizeSearchResponse(data, 'videos'); @@ -512,7 +631,9 @@ export class LosslessAPI { items: normalized.items.map((v) => this.prepareVideo(v)), }; - await this.cache.set('search_videos', query, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('search_videos', query, result); + } return result; } catch (error) { if (error.name === 'AbortError') throw error; @@ -539,7 +660,9 @@ export class LosslessAPI { originalTrackUrl: data.OriginalTrackUrl || null, }; - await this.cache.set('video', id, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('video', id, result); + } return result; } @@ -666,9 +789,21 @@ export class LosslessAPI { }); } + tracks = tracks.map((t) => { + if (t.album) { + t.album = Object.assign(new TrackAlbum(), t.album); + } + + return Object.assign(new Track(), t); + }); + + album = Object.assign(new Album(), album); + const result = { album, tracks }; - await this.cache.set('album', id, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('album', id, result); + } return result; } @@ -776,9 +911,19 @@ export class LosslessAPI { // Removed to reduce API load. Playlists can be very large. // tracks = await this.enrichTracksWithAlbumDates(tracks); + tracks = tracks.map((t) => { + if (t.album) { + t.album = Object.assign(new TrackAlbum(), t.album); + } + + return Object.assign(new Track(), t); + }); + const result = { playlist, tracks }; - await this.cache.set('playlist', id, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('playlist', id, result); + } return result; } @@ -802,6 +947,14 @@ export class LosslessAPI { // Limited to reduce API load tracks = await this.enrichTracksWithAlbumDates(tracks, 10); + tracks = tracks.map((t) => { + if (t.album) { + t.album = Object.assign(new TrackAlbum(), t.album); + } + + return Object.assign(new Track(), t); + }); + const mix = { id: mixData.id, title: mixData.title, @@ -812,7 +965,9 @@ export class LosslessAPI { }; const result = { mix, tracks }; - await this.cache.set('mix', id, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('mix', id, result); + } return result; } @@ -902,7 +1057,7 @@ export class LosslessAPI { const isTrack = (v) => v?.id && v.duration; const isAlbum = (v) => v?.id && 'numberOfTracks' in v; - const isVideo = (v) => v?.id && v.type === 'VIDEO'; + const isVideo = (v) => v?.id && !!v.type?.toLowerCase().includes('video'); const scan = (value, visited) => { if (!value || typeof value !== 'object' || visited.has(value)) return; @@ -969,10 +1124,95 @@ export class LosslessAPI { const result = { ...artist, albums, eps, tracks, videos }; - await this.cache.set('artist', cacheKey, result); + if (!(primaryResponse instanceof TidalResponse) && !(contentResponse instanceof TidalResponse)) { + await this.cache.set('artist', cacheKey, result); + } return result; } + async getArtistTopTracks(artistId, options = {}) { + const offset = options.offset || 0; + const limit = options.limit || 15; + console.log('[getArtistTopTracks] Called:', { artistId, offset, limit, options }); + + const cacheKey = `artist_tracks_${artistId}_${offset}_${limit}`; + if (!options.skipCache) { + const cached = await this.cache.get('artist', cacheKey); + if (cached) return cached; + } + + try { + // Use f parameter with skip_tracks=true to get toptracks from the dedicated endpoint + const response = await this.fetchWithRetry( + `/artist/?f=${artistId}&skip_tracks=true&offset=${offset}&limit=${limit}` + ); + const jsonData = await response.json(); + + let data = jsonData.data || jsonData; + console.log( + '[getArtistTopTracks] Raw response data keys:', + Object.keys(data), + 'tracks:', + data.tracks?.length + ); + + // Extract tracks from the response + let tracks = []; + + // Check for tracks array directly (from toptracks endpoint) + if (Array.isArray(data.tracks)) { + tracks = data.tracks; + } + + // Also scan for tracks in the data structure + if (tracks.length === 0) { + const trackMap = new Map(); + const isTrack = (v) => v?.id && v.duration; + + const scan = (value, visited) => { + if (!value || typeof value !== 'object' || visited.has(value)) return; + visited.add(value); + + if (Array.isArray(value)) { + value.forEach((item) => scan(item, visited)); + return; + } + + const item = value.item || value; + if (isTrack(item)) { + trackMap.set(item.id, this.prepareTrack(item)); + } + + Object.values(value).forEach((nested) => scan(nested, visited)); + }; + + const visited = new Set(); + scan(data, visited); + tracks = Array.from(trackMap.values()); + } + + tracks = tracks.map((t) => this.prepareTrack(t)).sort((a, b) => (b.popularity || 0) - (a.popularity || 0)); + tracks = await this.enrichTracksWithAlbumDates(tracks); + + // Safeguard: If API ignores offset, it returns the same first tracks + const hasMore = tracks.length === limit && (offset === 0 || tracks[0]?.id !== options.firstTrackId); + const result = { + tracks, + offset, + limit, + hasMore, + }; + + if (!(response instanceof TidalResponse)) { + await this.cache.set('artist', cacheKey, result); + } + return result; + } catch (e) { + console.warn('Failed to fetch artist top tracks:', e); + return { tracks: [], offset, limit, hasMore: false }; + } + } + async getSimilarArtists(artistId) { const cached = await this.cache.get('similar_artists', artistId); if (cached) return cached; @@ -989,7 +1229,9 @@ export class LosslessAPI { const result = items.map((artist) => this.prepareArtist(artist)); - await this.cache.set('similar_artists', artistId, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('similar_artists', artistId, result); + } return result; } catch (e) { console.warn('Failed to fetch similar artists:', e); @@ -1017,7 +1259,9 @@ export class LosslessAPI { text: data.text, source: data.source || 'Tidal', }; - await this.cache.set('artist', cacheKey, bio); + if (!(response instanceof TidalResponse)) { + await this.cache.set('artist', cacheKey, bio); + } return bio; } } @@ -1042,7 +1286,9 @@ export class LosslessAPI { const result = items.map((album) => this.prepareAlbum(album)); - await this.cache.set('similar_albums', albumId, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('similar_albums', albumId, result); + } return result; } catch (e) { console.warn('Failed to fetch similar albums:', e); @@ -1111,7 +1357,6 @@ export class LosslessAPI { const artistPromises = artistsToProcess.map(async (artist) => { try { - console.log(`Fetching tracks for artist: ${artist.name} (ID: ${artist.id})`); const artistData = await this.getArtist(artist.id, { lightweight: true, skipCache: options.refresh }); if (artistData && artistData.tracks && artistData.tracks.length > 0) { const availableTracks = artistData.tracks.filter((track) => !seenTrackIds.has(track.id)); @@ -1140,9 +1385,11 @@ export class LosslessAPI { const results = await Promise.all(artistPromises); results.forEach((tracks) => { - if (tracks.length > 0) { - recommendedTracks.push(...tracks); - tracks.forEach((t) => seenTrackIds.add(t.id)); + for (const t of tracks) { + if (!seenTrackIds.has(t.id)) { + seenTrackIds.add(t.id); + recommendedTracks.push(t); + } } }); @@ -1205,7 +1452,9 @@ export class LosslessAPI { const items = data.items || []; const tracks = items.map((item) => this.prepareTrack(item.track || item)); - await this.cache.set('recommendations', id, tracks); + if (!(response instanceof TidalResponse)) { + await this.cache.set('recommendations', id, tracks); + } return tracks; } catch (error) { console.error('Failed to fetch recommendations:', error); @@ -1222,31 +1471,130 @@ export class LosslessAPI { const jsonResponse = await response.json(); const result = this.parseTrackLookup(this.normalizeTrackResponse(jsonResponse)); - await this.cache.set('track', cacheKey, result); + if (!(response instanceof TidalResponse)) { + await this.cache.set('track', cacheKey, result); + } return result; } async getStreamUrl(id, quality = 'HI_RES_LOSSLESS') { - const cacheKey = `stream_${id}_${quality}`; + const cacheKey = `stream_info_${id}_${quality}`; if (this.streamCache.has(cacheKey)) { return this.streamCache.get(cacheKey); } - const lookup = await this.getTrack(id, quality); - let streamUrl; - if (lookup.originalTrackUrl) { - streamUrl = lookup.originalTrackUrl; - } else { - streamUrl = this.extractStreamUrlFromManifest(lookup.info.manifest); - if (!streamUrl) { - throw new Error('Could not resolve stream URL'); + let manifestRgInfo = null; + let isUsingManifestEndpoint = false; + + try { + const manifestType = isIos || isSafari ? 'HLS' : 'MPEG_DASH'; + const isApple = isIos || isSafari; + + let canPlayAtmos = false; + try { + if (window.MediaSource && typeof window.MediaSource.isTypeSupported === 'function') { + canPlayAtmos = + MediaSource.isTypeSupported('audio/mp4; codecs="ec-3"') || + MediaSource.isTypeSupported('audio/mp4; codecs="eac3"'); + } + if (!canPlayAtmos && typeof document !== 'undefined') { + const a = document.createElement('audio'); + canPlayAtmos = !!( + a.canPlayType('audio/mp4; codecs="ec-3"') || a.canPlayType('audio/mp4; codecs="eac3"') + ); + } + } catch (e) {} + + const paramsArray = []; + + if (quality === 'LOW') { + paramsArray.push(['formats', 'HEAACV1']); + } else if (quality === 'HIGH') { + if (!isApple) paramsArray.push(['formats', 'HEAACV1']); + paramsArray.push(['formats', 'AACLC']); + } else if (quality === 'LOSSLESS') { + // For Safari to not auto-downgrade to AAC, only request FLAC + paramsArray.push(['formats', 'HEAACV1']); + paramsArray.push(['formats', 'AACLC']); + paramsArray.push(['formats', 'FLAC']); + } else if (quality === 'HI_RES_LOSSLESS') { + paramsArray.push(['formats', 'HEAACV1']); + paramsArray.push(['formats', 'AACLC']); + paramsArray.push(['formats', 'FLAC_HIRES']); + paramsArray.push(['formats', 'FLAC']); + } else if (quality === 'DOLBY_ATMOS' && canPlayAtmos) { + paramsArray.push(['formats', 'EAC3_JOC']); + } else { + // Default fallback or "auto" behavior + paramsArray.push(['formats', 'HEAACV1']); + paramsArray.push(['formats', 'AACLC']); + paramsArray.push(['formats', 'FLAC']); + paramsArray.push(['formats', 'FLAC_HIRES']); + if (canPlayAtmos) { + paramsArray.push(['formats', 'EAC3_JOC']); + } + } + + paramsArray.push( + ['adaptive', 'true'], + ['manifestType', manifestType], + ['uriScheme', 'HTTPS'], + ['usage', 'PLAYBACK'] + ); + + const params = new URLSearchParams(paramsArray); + + const response = await this.fetchWithRetry(`/trackManifests/?id=${id}&${params.toString()}`, { + type: 'streaming', + minVersion: '2.7', + }); + const jsonResponse = await response.json(); + const url = jsonResponse?.data?.data?.attributes?.uri; + if (url) { + streamUrl = url; + manifestRgInfo = { + trackReplayGain: jsonResponse?.data?.data?.attributes?.trackAudioNormalizationData?.replayGain, + trackPeakAmplitude: + jsonResponse?.data?.data?.attributes?.trackAudioNormalizationData?.peakAmplitude, + albumReplayGain: jsonResponse?.data?.data?.attributes?.albumAudioNormalizationData?.replayGain, + albumPeakAmplitude: + jsonResponse?.data?.data?.attributes?.albumAudioNormalizationData?.peakAmplitude, + }; + isUsingManifestEndpoint = true; + } else { + throw new Error('No URI in trackManifests response'); } + } catch (err) { + // Fallback to /track endpoint } - this.streamCache.set(cacheKey, streamUrl); - return streamUrl; + if (!isUsingManifestEndpoint) { + const lookup = await this.getTrack(id, quality); + + if (lookup.originalTrackUrl) { + streamUrl = lookup.originalTrackUrl; + } else { + streamUrl = this.extractStreamUrlFromManifest(lookup.info.manifest); + if (!streamUrl) { + throw new Error('Could not resolve stream URL'); + } + } + if (lookup.info) { + manifestRgInfo = { + trackReplayGain: lookup.info.trackReplayGain || lookup.info.replayGain, + trackPeakAmplitude: lookup.info.trackPeakAmplitude || lookup.info.peakAmplitude, + albumReplayGain: lookup.info.albumReplayGain, + albumPeakAmplitude: lookup.info.albumPeakAmplitude, + }; + } + } + + const result = { url: streamUrl, rgInfo: manifestRgInfo }; + this.streamCache.set(cacheKey, result); + + return result; } async getVideoStreamUrl(id) { @@ -1290,28 +1638,119 @@ export class LosslessAPI { throw new Error(`Could not resolve video stream URL for ID: ${id}`); } - this.streamCache.set(cacheKey, streamUrl); + if (!(lookup instanceof TidalResponse)) { + this.streamCache.set(cacheKey, streamUrl); + } return streamUrl; } + async enrichTrack(input, { downloadQuality = 'HI_RES_LOSSLESS' }) { + const id = input?.id || input; + const track = typeof input === 'object' ? input : await this.getTrack(id, downloadQuality); + const isVideo = track?.type?.toLowerCase().includes('video'); + downloadQuality = isCustomFormat(downloadQuality) ? 'LOSSLESS' : downloadQuality; + + let lookup; + if (isVideo) { + lookup = await this.getVideo(id); + } else { + lookup = Object.assign(new PlaybackInfo(), await this.getTrack(id, downloadQuality)); + } + + if (input instanceof EnrichedTrack) { + return { + lookup, + enrichedTrack: input, + isVideo, + }; + } + + const enrichedTrack = { ...track }; + if (lookup.info) { + enrichedTrack.replayGain = Object.assign(new ReplayGain(), { + trackReplayGain: lookup.info.trackReplayGain, + trackPeakAmplitude: lookup.info.trackPeakAmplitude, + albumReplayGain: lookup.info.albumReplayGain, + albumPeakAmplitude: lookup.info.albumPeakAmplitude, + }); + } + + if (track.album?.id && (track.album?.totalDiscs == null || track.album?.numberOfTracksOnDisc == null)) { + try { + const albumData = await this.getAlbum(track.album.id); + enrichedTrack.album = Object.assign(new EnrichedAlbum(), { + ...albumData.album, + ...enrichedTrack.album, + }); + + if (albumData.tracks?.length > 0) { + const discTrackCounts = new Map(); + let maxDiscNumber = 0; + for (const t of albumData.tracks) { + const dn = getTrackDiscNumber(t); + discTrackCounts.set(dn, (discTrackCounts.get(dn) || 0) + 1); + if (dn > maxDiscNumber) maxDiscNumber = dn; + } + const totalDiscs = maxDiscNumber || 1; + const discNumber = getTrackDiscNumber(track); + enrichedTrack.album = Object.assign(new EnrichedAlbum(), { + ...(enrichedTrack.album || {}), + + totalDiscs: track.album?.totalDiscs ?? totalDiscs, + numberOfTracksOnDisc: track.album?.numberOfTracksOnDisc ?? discTrackCounts.get(discNumber), + }); + } + } catch (e) { + console.warn('Failed to fetch album for disc info:', e); + } + } + + if (!(enrichedTrack.album instanceof EnrichedAlbum)) { + enrichedTrack.album = Object.assign(new TrackAlbum(), enrichedTrack.album); + } + + return { lookup, enrichedTrack: Object.assign(new EnrichedTrack(), enrichedTrack), isVideo }; + } + + /** + * Downloads a track or video from TIDAL in the specified quality. + * + * Handles multiple stream types (DASH, HLS, and direct HTTP), applies post-processing + * for audio tracks, adds metadata, and optionally triggers a browser download. + * + * @async + * @param {string} id - The TIDAL track or video ID + * @param {string} [quality='HI_RES_LOSSLESS'] - The desired audio quality (e.g., 'HI_RES_LOSSLESS', 'LOSSLESS', 'HIGH', 'NORMAL'). + * Custom FFMPEG formats are transcoded from LOSSLESS. + * @param {string} filename - The filename to save the downloaded content as + * @param {Object} [options={}] - Additional download options + * @param {Function} [options.onProgress] - Callback function for progress updates with signature: + * `(progressEvent) => void` + * @param {Object} [options.track] - Track metadata object to attach to the audio file + * @param {boolean} [options.calculateDashBytes=true] - Whether to calculate total bytes for DASH streams + * @param {AbortSignal} [options.signal] - AbortSignal to cancel the download + * @param {boolean} [options.triggerDownload=true] - Whether to trigger browser download after completion + * + * @returns {Promise} The downloaded content as a Blob object + * + * @throws {Error} If stream URL cannot be resolved, manifest is missing, or download fails + * @throws {AbortError} If the download is aborted via the signal + * @throws {MP3EncodingError|FfmpegError} If audio transcoding fails + */ async downloadTrack(id, quality = 'HI_RES_LOSSLESS', filename, options = {}) { // Load ffmpeg in the background. loadFfmpeg().catch(console.error); + const metadataModule = await import('./metadata.js'); + const { prefetchMetadataObjects, addMetadataToAudio } = metadataModule; - const { onProgress, track } = options; + const { onProgress, track, calculateDashBytes = true } = options; const prefetchPromises = prefetchMetadataObjects(track, this); - const isVideo = track?.type === 'video'; try { - // MP3_320 is not a native TIDAL quality, we download LOSSLESS and convert - const downloadQuality = quality === 'MP3_320' ? 'LOSSLESS' : quality; + // Custom FFMPEG formats are not native TIDAL qualities; download LOSSLESS and transcode + const downloadQuality = isCustomFormat(quality) ? 'LOSSLESS' : quality; - let lookup; - if (isVideo) { - lookup = await this.getVideo(id); - } else { - lookup = await this.getTrack(id, downloadQuality); - } + const { lookup, enrichedTrack, isVideo } = await this.enrichTrack(track, { downloadQuality }); let streamUrl; let blob; @@ -1351,7 +1790,8 @@ export class LosslessAPI { const downloader = new DashDownloader(); blob = await downloader.downloadDashStream(streamUrl, { signal: options.signal, - onProgress: options.onProgress, + onProgress, + calculateDashBytes: calculateDashBytes ?? true, }); } catch (dashError) { console.error('DASH download failed:', dashError); @@ -1369,13 +1809,29 @@ export class LosslessAPI { const downloader = new HlsDownloader(); blob = await downloader.downloadHlsStream(streamUrl, { signal: options.signal, - onProgress: options.onProgress, + onProgress, }); } catch (hlsError) { console.error('HLS download failed:', hlsError); throw hlsError; } } else { + // Try HEAD first to get Content-Length when GET uses chunked encoding (fixes #278) + let headContentLength = null; + try { + const headResponse = await fetch(streamUrl, { + method: 'HEAD', + cache: 'no-store', + signal: options.signal, + }); + if (headResponse.ok) { + const cl = headResponse.headers.get('Content-Length'); + if (cl) headContentLength = parseInt(cl, 10); + } + } catch (_) { + /* ignore HEAD failure; proceed with GET */ + } + const response = await fetch(streamUrl, { cache: 'no-store', signal: options.signal, @@ -1385,120 +1841,59 @@ export class LosslessAPI { throw new Error(`Fetch failed: ${response.status}`); } - const contentLength = response.headers.get('Content-Length'); - const totalBytes = contentLength ? parseInt(contentLength, 10) : 0; + const contentLengthHeader = response.headers.get('Content-Length'); + const totalBytes = resolveDownloadTotalBytes(contentLengthHeader, headContentLength); let receivedBytes = 0; - if (response.body && onProgress) { - const reader = response.body.getReader(); + if (response.body) { const chunks = []; - while (true) { - const { done, value } = await reader.read(); - if (done) break; + for await (const chunk of readableStreamIterator(response.body)) { + chunks.push(chunk); + receivedBytes += chunk.byteLength; - if (value) { - chunks.push(value); - receivedBytes += value.byteLength; - - onProgress({ - stage: 'downloading', - receivedBytes, - totalBytes: totalBytes || undefined, - }); - } + onProgress?.(new DownloadProgress(receivedBytes, totalBytes || undefined)); } const defaultMime = isVideo ? 'video/mp4' : 'audio/flac'; blob = new Blob(chunks, { type: response.headers.get('Content-Type') || defaultMime }); } else { + onProgress?.(new DownloadProgress(0, undefined)); blob = await response.blob(); - if (onProgress) { - onProgress({ - stage: 'downloading', - receivedBytes: blob.size, - totalBytes: blob.size, - }); - } + onProgress?.(new DownloadProgress(blob.size, blob.size)); } } if (!isVideo) { - // Convert to MP3 320kbps if requested - if (quality === 'MP3_320') { - try { - blob = await encodeToMp3(blob, onProgress, options.signal); - } catch (encodingError) { - if (onProgress) { - onProgress({ - stage: 'error', - message: `Encoding failed: ${encodingError.message}`, - }); - } - throw encodingError; - } - } - - if (quality.endsWith('LOSSLESS')) { - try { - switch (losslessContainerSettings.getContainer()) { - case 'flac': - if ((await getExtensionFromBlob(blob)) != 'flac') { - blob = await ffmpeg( - blob, - { args: ['-vn', '-map_metadata', '-1', '-map', '0:a', '-c:a', 'flac'] }, - 'output.flac', - 'audio/flac', - onProgress, - options.signal - ); - } else { - blob = await rebuildFlacWithoutMetadata(blob); - } - break; - case 'alac': - blob = await ffmpeg( - blob, - { args: ['-c:a', 'alac'] }, - 'output.m4a', - 'audio/mp4', - onProgress, - options.signal - ); - break; - default: - break; - } - } catch (error) { - if (error?.name === 'AbortError') { - throw error; - } - - console.error('Lossless container conversion failed:', error); - } - } + blob = await applyAudioPostProcessing( + blob, + quality, + onProgress, + options.signal, + track?.audioQuality ?? null + ); + } - // Add metadata if track information is provided - if (track) { - if (onProgress) { - onProgress({ - stage: 'processing', - message: 'Adding metadata...', - }); - } + // Add metadata if track information is provided + if (track) { + onProgress?.({ + stage: 'processing', + message: 'Adding metadata...', + }); - const enrichedTrack = { ...track }; - if (lookup.info) { - enrichedTrack.replayGain = { - trackReplayGain: lookup.info.trackReplayGain, - trackPeakAmplitude: lookup.info.trackPeakAmplitude, - albumReplayGain: lookup.info.albumReplayGain, - albumPeakAmplitude: lookup.info.albumPeakAmplitude, - }; + onProgress?.(new DownloadProgress('Adding metadata')); + try { + if (isVideo) { + blob = new File( + [await ffmpeg(blob, ['-c', 'copy'], 'output.mp4', 'video/mp4', onProgress, options.signal)], + 'output.mp4', + { type: 'video/mp4' } + ); } - blob = await addMetadataToAudio(blob, enrichedTrack, this, quality, prefetchPromises); + } catch (err) { + console.error(err); } } @@ -1522,7 +1917,11 @@ export class LosslessAPI { throw error; } console.error('Download failed:', error); - if (error instanceof MP3EncodingError || error.code === 'MP3_ENCODING_FAILED') { + if ( + error instanceof MP3EncodingError || + error instanceof FfmpegError || + error.code === 'MP3_ENCODING_FAILED' + ) { throw error; } if (error.message === RATE_LIMIT_ERROR_MESSAGE) { diff --git a/js/app.js b/js/app.js index 21da531f0..5c285c119 100644 --- a/js/app.js +++ b/js/app.js @@ -1,4 +1,10 @@ //js/app.js +import discordSvg from '../images/discord.svg?svg&size=22'; +import googleSvg from '../images/google.svg?svg&size=22'; +import githubSvg from '../images/github.svg?svg&size=22'; +import spotifySvg from '../images/spotify.svg?svg&size=22'; +import { isIos, isSafari } from './platform-detection.js'; +import { hapticLight } from './haptics.js'; import { MusicAPI } from './music-api.js'; import { apiSettings, @@ -18,18 +24,16 @@ import { LyricsManager, openLyricsPanel, clearLyricsPanelSync } from './lyrics.j import { createRouter, updateTabTitle, navigate } from './router.js'; import { initializePlayerEvents, initializeTrackInteractions, handleTrackAction } from './events.js'; import { initializeUIInteractions } from './ui-interactions.js'; -import { debounce, SVG_PLAY, getShareUrl } from './utils.js'; +import { debounce, getShareUrl } from './utils.js'; import { sidePanelManager } from './side-panel.js'; import { db } from './db.js'; import { showNotification } from './downloads.js'; import { syncManager } from './accounts/pocketbase.js'; import { authManager } from './accounts/auth.js'; import { registerSW } from 'virtual:pwa-register'; -import './smooth-scrolling.js'; import { openEditProfile } from './profile.js'; import { ThemeStore } from './themeStore.js'; import './commandPalette.js'; - import { initTracker } from './tracker.js'; import { initAnalytics, @@ -62,12 +66,21 @@ import { parseDynamicCSV, importToLibrary, } from './playlist-importer.js'; +import { modernSettings } from './ModernSettings.js'; +import { + SVG_OFFLINE, + SVG_RIGHT_ARROW, + SVG_LEFT_ARROW, + SVG_ANIMATE_SPIN, + SVG_PLAY, + SVG_CLOSE, + SVG_RESET, +} from './icons.js'; +import { HiFiClient } from './HiFi.js'; // Capture real iOS state before spoofing (needed for background audio) if (typeof window !== 'undefined') { const _ua = navigator.userAgent.toLowerCase(); - window.__IS_IOS__ = /iphone|ipad|ipod/.test(_ua) || (_ua.includes('mac') && navigator.maxTouchPoints > 1); - // Spoof User-Agent to bypass Google's embedded browser check Object.defineProperty(navigator, 'userAgent', { get: function () { @@ -99,8 +112,6 @@ let settingsModule = null; let downloadsModule = null; let metadataModule = null; -export const managers = {}; - async function loadSettingsModule() { if (!settingsModule) { settingsModule = await import('./settings.js'); @@ -258,23 +269,20 @@ function initializeKeyboardShortcuts(player, _audioPlayer) { }, visualizerNext: () => { trackKeyboardShortcut('VisualizerNext'); - const ui = window.monochromeUi; - if (ui?.visualizer?.presets?.['butterchurn']) { - ui.visualizer.presets['butterchurn'].nextPreset(); + if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) { + UIRenderer.instance.visualizer.presets['butterchurn'].nextPreset(); } }, visualizerPrev: () => { trackKeyboardShortcut('VisualizerPrev'); - const ui = window.monochromeUi; - if (ui?.visualizer?.presets?.['butterchurn']) { - ui.visualizer.presets['butterchurn'].prevPreset(); + if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) { + UIRenderer.instance.visualizer.presets['butterchurn'].prevPreset(); } }, visualizerCycle: () => { trackKeyboardShortcut('VisualizerCycle'); - const ui = window.monochromeUi; - if (ui?.visualizer?.presets?.['butterchurn']) { - ui.visualizer.presets['butterchurn'].toggleCycle(); + if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) { + UIRenderer.instance.visualizer.presets['butterchurn'].toggleCycle(); } }, }; @@ -313,11 +321,7 @@ function showOfflineNotification() { const notification = document.createElement('div'); notification.className = 'offline-notification'; notification.innerHTML = ` - - - - - + ${SVG_OFFLINE(20)} You are offline. Some features may not work. `; document.body.appendChild(notification); @@ -358,21 +362,21 @@ async function disablePwaForAuthGate() { async function uploadCoverImage(file) { try { - const formData = new FormData(); - formData.append('file', file); - - const response = await fetch('/upload', { - method: 'POST', - body: formData, + const response = await fetch(`https://worker.uploads.monochrome.qzz.io/${file.name}`, { + method: 'PUT', + headers: { + 'x-api-key': 'if_youre_reading_this_fuck_off', + 'Content-Type': file.type || 'application/octet-stream', + }, + body: file, }); if (!response.ok) { - const error = await response.json(); - throw new Error(error.error || `Upload failed: ${response.status}`); + if (response.status === 413) throw new Error('File exceeds 10MB'); + throw new Error(`Upload failed: ${response.status}`); } - const data = await response.json(); - return data.url; + return `https://images.monochrome.qzz.io/${await response.text()}`; } catch (error) { console.error('Cover upload error:', error); throw error; @@ -380,24 +384,66 @@ async function uploadCoverImage(file) { } document.addEventListener('DOMContentLoaded', async () => { + await modernSettings.waitPending(); + + if (import.meta.env.DEV) { + window.monochrome = { + HiFiClient, + LyricsManager, + MusicAPI, + Player, + UIRenderer, + }; + } + + // Haptic feedback on every click + document.addEventListener('click', () => hapticLight(), { capture: true }); + // Initialize analytics initAnalytics(); + // Populate commit info + { + const repo = 'https://github.com/monochrome-music/monochrome'; + const hash = typeof __COMMIT_HASH__ !== 'undefined' ? __COMMIT_HASH__ : 'dev'; + const commitLink = + hash !== 'dev' && hash !== 'unknown' + ? `${hash}` + : hash; + const repoLink = `monochrome-music/monochrome`; + const html = `Commit ${commitLink} Β· ${repoLink}`; + const aboutEl = document.getElementById('about-commit-info'); + const settingsEl = document.getElementById('settings-commit-info'); + if (aboutEl) aboutEl.innerHTML = html; + if (settingsEl) settingsEl.innerHTML = html; + } + new ThemeStore(); + await HiFiClient.initialize({ + storage: [ + localStorage, + ...(import.meta.env.DEV + ? [ + { + setItem: (key, value) => console.debug(`HiFiClient storage set: ${key} = ${value}`), + removeItem: (key) => console.debug(`HiFiClient storage remove: ${key}`), + }, + ] + : []), + ], + token: localStorage.getItem('hifi_token') || undefined, + tokenExpiry: parseInt(localStorage.getItem('hifi_token_expiry') || '0'), + }); - const api = new MusicAPI(apiSettings); - const audioPlayer = document.getElementById('audio-player'); + await MusicAPI.initialize(apiSettings); - // i love ios and macos!!!! webkit fucking SUCKS BULLSHIT sorry ios/macos heads yall getting lossless only - // Use window.__IS_IOS__ (set before UA spoof in index.html) so detection works on real iOS. - const isIOS = typeof window !== 'undefined' && window.__IS_IOS__ === true; - const ua = navigator.userAgent.toLowerCase(); - const isSafari = - ua.includes('safari') && !ua.includes('chrome') && !ua.includes('crios') && !ua.includes('android'); + const audioPlayer = document.getElementById('audio-player'); - if (isIOS || isSafari) { + // i love ios and macos!!!! webkit fucking SUCKS BULLSHIT sorry ios/macos heads yall getting lossless only playback + // Use isIos from platform-detection (set before UA spoof in index.html) so detection works on real iOS. + if (isIos || isSafari) { const qualitySelect = document.getElementById('streaming-quality-setting'); - const downloadSelect = document.getElementById('download-quality-setting'); + const downloadQualitySelect = document.getElementById('download-quality-setting'); const removeHiRes = (select) => { if (!select) return; @@ -406,7 +452,11 @@ document.addEventListener('DOMContentLoaded', async () => { }; removeHiRes(qualitySelect); - removeHiRes(downloadSelect); + removeHiRes(downloadQualitySelect); + + if (isIos) { + document.querySelector('#hi-res-download-warning').style.display = ''; + } const currentQualitySetting = localStorage.getItem('playback-quality'); if (!currentQualitySetting || currentQualitySetting === 'HI_RES_LOSSLESS') { @@ -415,11 +465,10 @@ document.addEventListener('DOMContentLoaded', async () => { } const currentQuality = localStorage.getItem('playback-quality') || 'HI_RES_LOSSLESS'; - const player = new Player(audioPlayer, api, currentQuality); - window.monochromePlayer = player; + await Player.initialize(audioPlayer, MusicAPI.instance, currentQuality); // Initialize tracker - initTracker(player); + initTracker(); const isCapacitorMode = typeof window !== 'undefined' && @@ -444,7 +493,7 @@ document.addEventListener('DOMContentLoaded', async () => { player.handlePlayPause(); }); events.on('mediaStop', () => { - const el = player.activeElement; + const el = Player.instance.activeElement; el.pause(); el.currentTime = 0; }); @@ -471,13 +520,165 @@ document.addEventListener('DOMContentLoaded', async () => { const castBtn = document.getElementById('cast-btn'); initializeCasting(audioPlayer, castBtn); - const ui = new UIRenderer(api, player); - window.monochromeUi = ui; + await UIRenderer.initialize(MusicAPI.instance, Player.instance); + + /** + * Scans the configured local media folder and refreshes `window.localFilesCache`. + * Called by the folder-select button handler and by downloads.js after a + * successful write to the local media folder. + * + * @param {boolean} [onlyIfAlreadyScanned=false] When true, skips the scan if + * `window.localFilesCache` has never been populated (i.e. the user hasn't + * visited the local tab yet). + */ + async function scanLocalMediaFolder(onlyIfAlreadyScanned = false) { + // Skip the scan if the user has never visited the local tab – they'll + // get a fresh scan when they navigate there for the first time. + if (onlyIfAlreadyScanned && !window.localFilesCache) return; + + // Prevent concurrent scans. + if (window.localFilesScanInProgress) return; + window.localFilesScanInProgress = true; + + try { + const handle = await db.getSetting('local_folder_handle'); + if (!handle) return; + + const isNeutralino = + window.Neutralino && (window.NL_MODE || window.location.search.includes('mode=neutralino')); + const tracks = (window.localFilesCache = []); + let idCounter = 0; + const { readTrackMetadata } = await loadMetadataModule(); + + if (isNeutralino) { + async function scanNeu(dirPath) { + const entries = await window.Neutralino.filesystem.readDirectory(dirPath); + for (const entry of entries) { + if (entry.entry === '.' || entry.entry === '..') continue; + const fullPath = `${dirPath}/${entry.entry}`; + if (entry.type === 'FILE') { + const name = entry.entry.toLowerCase(); + if ( + name.endsWith('.flac') || + name.endsWith('.mp3') || + name.endsWith('.m4a') || + name.endsWith('.wav') || + name.endsWith('.ogg') + ) { + try { + const buffer = await window.Neutralino.filesystem.readBinaryFile(fullPath); + const stats = await window.Neutralino.filesystem.getStats(fullPath); + const file = new File([buffer], entry.entry, { lastModified: stats.mtime }); + const metadata = await readTrackMetadata(file); + metadata.id = `local-${idCounter++}-${entry.entry}`; + tracks.push(metadata); + UIRenderer.instance.renderLocalFiles( + document.getElementById('library-local-container') + ); + } catch (e) { + console.error('Failed to read file:', fullPath, e); + } + } + } else if (entry.type === 'DIRECTORY') { + await scanNeu(fullPath); + } + } + } + await scanNeu(handle.path); + } else { + // Request read permission before iterating. When the browser has + // already granted it (e.g. within the same session or via a + // persistent grant) this succeeds without a user gesture. + if (typeof handle.requestPermission === 'function') { + const permission = await handle.requestPermission({ mode: 'read' }); + if (permission !== 'granted') return; + } + + async function scanBrowser(dirHandle) { + for await (const entry of dirHandle.values()) { + if (entry.kind === 'file') { + const name = entry.name.toLowerCase(); + if ( + name.endsWith('.flac') || + name.endsWith('.mp3') || + name.endsWith('.m4a') || + name.endsWith('.wav') || + name.endsWith('.ogg') + ) { + const file = await entry.getFile(); + const metadata = await readTrackMetadata(file); + metadata.id = `local-${idCounter++}-${file.name}`; + tracks.push(metadata); + UIRenderer.instance.renderLocalFiles( + document.getElementById('library-local-container') + ); + } + } else if (entry.kind === 'directory') { + await scanBrowser(entry); + } + } + } + await scanBrowser(handle); + } + + tracks.sort((a, b) => (a.artist.name || '').localeCompare(b.artist.name || '')); + // Update only the local-files section without navigating to the library page. + UIRenderer.instance.renderLocalFiles(document.getElementById('library-local-container')); + } finally { + window.localFilesScanInProgress = false; + } + + return window.localFilesCache; + } + + /** + * Called by downloads.js (via window) after a successful write to the local + * media folder so the track appears in Library > Local without the user + * having to manually re-scan. + * + * When called with a `blob` and `filename` (single-track download case) it + * performs a cheap partial update β€” reading metadata only from that one file + * and inserting it into the existing cache β€” so the full folder does not need + * to be re-walked. When called with no arguments (bulk download case, or when + * `localFilesCache` has never been populated) it falls back to a full rescan. + */ + window.refreshLocalMediaFolder = async (blob = null, filename = null) => { + if (blob && filename) { + try { + /** @type {import("./metadata.js")} */ + const { readTrackMetadata } = await loadMetadataModule(); + const baseName = filename.split('/').pop(); + const metadata = await readTrackMetadata(new Uint8Array(await blob.arrayBuffer()), { + filename: baseName, + }); + const existing = window.localFilesCache || []; + metadata.id = `local-${existing.length}-${baseName}`; + window.localFilesCache = [...existing, metadata].sort((a, b) => + (a.artist.name || '').localeCompare(b.artist.name || '') + ); + UIRenderer.instance.renderLocalFiles(document.getElementById('library-local-container')); + } catch { + // Fall back to a full rescan if metadata extraction fails. + await scanLocalMediaFolder(true); + } + } else { + await scanLocalMediaFolder(!!window.localFilesCache); + } + }; + + // Kick off a background scan of the saved local media folder on startup so + // that the Library > Local tab is populated without requiring the user to + // manually press "Load [folder]" every session. The function internally + // checks for a saved handle and (in browser mode) requests read permission, + // so this is a silent no-op when no folder is configured or permission is not + // yet granted. + scanLocalMediaFolder(); + const scrobbler = new MultiScrobbler(); window.monochromeScrobbler = scrobbler; - const lyricsManager = new LyricsManager(api); - ui.lyricsManager = lyricsManager; - managers.lyricsManager = lyricsManager; + + const lyricsManager = await LyricsManager.initialize(MusicAPI.instance); + UIRenderer.instance.lyricsManager = lyricsManager; // Check browser support for local files const selectLocalBtn = document.getElementById('select-local-folder-btn'); @@ -510,11 +711,11 @@ document.addEventListener('DOMContentLoaded', async () => { sidebarSettings.restoreState(); // Render pinned items - await ui.renderPinnedItems(); + await UIRenderer.instance.renderPinnedItems(); // Load settings module and initialize const { initializeSettings } = await loadSettingsModule(); - initializeSettings(scrobbler, player, api, ui); + await initializeSettings(scrobbler, Player.instance, MusicAPI.instance, UIRenderer.instance); // Track sidebar navigation clicks document.querySelectorAll('.sidebar-nav a').forEach((link) => { @@ -527,28 +728,28 @@ document.addEventListener('DOMContentLoaded', async () => { }); }); - initializePlayerEvents(player, audioPlayer, scrobbler, ui); + initializePlayerEvents(Player.instance, audioPlayer, scrobbler, UIRenderer.instance); initializeTrackInteractions( - player, - api, + Player.instance, + MusicAPI.instance, document.querySelector('.main-content'), document.getElementById('context-menu'), lyricsManager, - ui, + UIRenderer.instance, scrobbler ); - initializeUIInteractions(player, api, ui); - initializeKeyboardShortcuts(player, audioPlayer); + initializeUIInteractions(Player.instance, MusicAPI.instance, UIRenderer.instance); + initializeKeyboardShortcuts(Player.instance, audioPlayer); // Restore UI state for the current track (like button, theme) - if (player.currentTrack) { - ui.setCurrentTrack(player.currentTrack); + if (Player.instance.currentTrack) { + UIRenderer.instance.setCurrentTrack(Player.instance.currentTrack); } document.querySelector('.now-playing-bar').addEventListener('click', async (e) => { if (!e.target.closest('.cover')) return; - if (!player.currentTrack) { + if (!Player.instance.currentTrack) { alert('No track is currently playing'); return; } @@ -559,16 +760,16 @@ document.addEventListener('DOMContentLoaded', async () => { const isActive = sidePanelManager.isActive('lyrics'); if (isActive) { - trackCloseLyrics(player.currentTrack); + trackCloseLyrics(Player.instance.currentTrack); } else { - trackOpenLyrics(player.currentTrack); + trackOpenLyrics(Player.instance.currentTrack); } } else if (mode === 'cover') { const overlay = document.getElementById('fullscreen-cover-overlay'); if (overlay && overlay.style.display === 'flex') { trackCloseFullscreenCover(); } else { - trackOpenFullscreenCover(player.currentTrack); + trackOpenFullscreenCover(Player.instance.currentTrack); } } @@ -577,9 +778,9 @@ document.addEventListener('DOMContentLoaded', async () => { if (isActive) { sidePanelManager.close(); - clearLyricsPanelSync(player.activeElement, sidePanelManager.panel); + clearLyricsPanelSync(Player.instance.activeElement, sidePanelManager.panel); } else { - openLyricsPanel(player.currentTrack, player.activeElement, lyricsManager); + openLyricsPanel(Player.instance.currentTrack, Player.instance.activeElement, lyricsManager); } } else if (mode === 'cover') { const overlay = document.getElementById('fullscreen-cover-overlay'); @@ -587,16 +788,21 @@ document.addEventListener('DOMContentLoaded', async () => { if (window.location.hash === '#fullscreen') { window.history.back(); } else { - ui.closeFullscreenCover(); + UIRenderer.instance.closeFullscreenCover(); } } else { - const nextTrack = player.getNextTrack(); - ui.showFullscreenCover(player.currentTrack, nextTrack, lyricsManager, player.activeElement); + const nextTrack = Player.instance.getNextTrack(); + UIRenderer.instance.showFullscreenCover( + Player.instance.currentTrack, + nextTrack, + lyricsManager, + Player.instance.activeElement + ); } } else { // Default to 'album' mode - navigate to album - if (player.currentTrack.album?.id) { - navigate(`/album/${player.currentTrack.album.id}`); + if (Player.instance.currentTrack.album?.id) { + navigate(`/album/${Player.instance.currentTrack.album.id}`); } } }); @@ -612,7 +818,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (window.location.hash === '#fullscreen') { window.history.back(); } else { - ui.closeFullscreenCover(); + UIRenderer.instance.closeFullscreenCover(); } }); @@ -624,14 +830,14 @@ document.addEventListener('DOMContentLoaded', async () => { const action = fullscreenCoverClickSettings.getAction(); const overlay = document.getElementById('fullscreen-cover-overlay'); - const playerInstance = window.monochromePlayer; + const playerInstance = Player.instance; switch (action) { case 'exit': if (window.location.hash === '#fullscreen') { window.history.back(); } else { - ui.closeFullscreenCover(); + UIRenderer.instance.closeFullscreenCover(); } break; case 'hide-ui': @@ -654,11 +860,11 @@ document.addEventListener('DOMContentLoaded', async () => { toggleBtn.title = 'Show UI'; } } - if (ui && typeof ui.setupUIToggleButton === 'function') { - if (ui.uiToggleCleanup) { - ui.uiToggleCleanup(); + if (UIRenderer.instance && typeof UIRenderer.instance.setupUIToggleButton === 'function') { + if (UIRenderer.instance.uiToggleCleanup) { + UIRenderer.instance.uiToggleCleanup(); } - ui.setupUIToggleButton(overlay); + UIRenderer.instance.setupUIToggleButton(overlay); } } break; @@ -677,7 +883,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (window.location.hash === '#fullscreen') { window.history.back(); } else { - ui.closeFullscreenCover(); + UIRenderer.instance.closeFullscreenCover(); } } }); @@ -687,9 +893,7 @@ document.addEventListener('DOMContentLoaded', async () => { const isCollapsed = document.body.classList.contains('sidebar-collapsed'); const toggleBtn = document.getElementById('sidebar-toggle'); if (toggleBtn) { - toggleBtn.innerHTML = isCollapsed - ? '' - : ''; + toggleBtn.innerHTML = isCollapsed ? SVG_RIGHT_ARROW(20) : SVG_LEFT_ARROW(20); } // Save sidebar state to localStorage sidebarSettings.setCollapsed(isCollapsed); @@ -870,7 +1074,7 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('toggle-lyrics-btn')?.addEventListener('click', async (e) => { e.stopPropagation(); - if (!player.currentTrack) { + if (!Player.instance.currentTrack) { alert('No track is currently playing'); return; } @@ -879,44 +1083,57 @@ document.addEventListener('DOMContentLoaded', async () => { if (isActive) { sidePanelManager.close(); - clearLyricsPanelSync(player.activeElement, sidePanelManager.panel); + clearLyricsPanelSync(Player.instance.activeElement, sidePanelManager.panel); } else { - openLyricsPanel(player.currentTrack, player.activeElement, lyricsManager); + openLyricsPanel(Player.instance.currentTrack, Player.instance.activeElement, lyricsManager); } }); document.getElementById('download-current-btn')?.addEventListener('click', () => { - if (player.currentTrack) { - handleTrackAction('download', player.currentTrack, player, api, lyricsManager, 'track', ui); + if (Player.instance.currentTrack) { + handleTrackAction( + 'download', + Player.instance.currentTrack, + Player.instance, + MusicAPI.instance, + lyricsManager, + 'track', + UIRenderer.instance + ); } }); // Auto-update lyrics when track changes let previousTrackId = null; audioPlayer.addEventListener('play', async () => { - if (!player.currentTrack) return; + if (!Player.instance.currentTrack) return; // Update UI with current track info for theme - ui.setCurrentTrack(player.currentTrack); + UIRenderer.instance.setCurrentTrack(Player.instance.currentTrack); // Update Media Session with new track - player.updateMediaSession(player.currentTrack); + Player.instance.updateMediaSession(Player.instance.currentTrack); - const currentTrackId = player.currentTrack.id; + const currentTrackId = Player.instance.currentTrack.id; if (currentTrackId === previousTrackId) return; previousTrackId = currentTrackId; // Update lyrics panel if it's open if (sidePanelManager.isActive('lyrics')) { // Re-open forces update/refresh of content and sync - openLyricsPanel(player.currentTrack, player.activeElement, lyricsManager, true); + openLyricsPanel(Player.instance.currentTrack, Player.instance.activeElement, lyricsManager, true); } // Update Fullscreen if it's open const fullscreenOverlay = document.getElementById('fullscreen-cover-overlay'); if (fullscreenOverlay && getComputedStyle(fullscreenOverlay).display !== 'none') { - const nextTrack = player.getNextTrack(); - ui.showFullscreenCover(player.currentTrack, nextTrack, lyricsManager, player.activeElement); + const nextTrack = Player.instance.getNextTrack(); + UIRenderer.instance.showFullscreenCover( + Player.instance.currentTrack, + nextTrack, + lyricsManager, + Player.instance.activeElement + ); } // DEV: Auto-open fullscreen mode if ?fullscreen=1 in URL @@ -926,8 +1143,13 @@ document.addEventListener('DOMContentLoaded', async () => { fullscreenOverlay && getComputedStyle(fullscreenOverlay).display === 'none' ) { - const nextTrack = player.getNextTrack(); - ui.showFullscreenCover(player.currentTrack, nextTrack, lyricsManager, player.activeElement); + const nextTrack = Player.instance.getNextTrack(); + UIRenderer.instance.showFullscreenCover( + Player.instance.currentTrack, + nextTrack, + lyricsManager, + Player.instance.activeElement + ); } }); @@ -947,7 +1169,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (!albumId) return; try { - const { tracks } = await api.getAlbum(albumId); + const { tracks } = await MusicAPI.instance.getAlbum(albumId); if (tracks && tracks.length > 0) { // Sort tracks by disc and track number for consistent playback const sortedTracks = [...tracks].sort((a, b) => { @@ -957,11 +1179,11 @@ document.addEventListener('DOMContentLoaded', async () => { return a.trackNumber - b.trackNumber; }); - player.setQueue(sortedTracks, 0); + Player.instance.setQueue(sortedTracks, 0); const shuffleBtn = document.getElementById('shuffle-btn'); if (shuffleBtn) shuffleBtn.classList.remove('active'); - player.shuffleActive = false; - player.playTrackFromQueue(); + Player.instance.shuffleActive = false; + await Player.instance.playTrackFromQueue(); } } catch (error) { console.error('Failed to play album:', error); @@ -985,14 +1207,14 @@ document.addEventListener('DOMContentLoaded', async () => { if (!albumId) return; try { - const { tracks } = await api.getAlbum(albumId); + const { tracks } = await MusicAPI.instance.getAlbum(albumId); if (tracks && tracks.length > 0) { const shuffledTracks = [...tracks].sort(() => Math.random() - 0.5); - player.setQueue(shuffledTracks, 0); + Player.instance.setQueue(shuffledTracks, 0); const shuffleBtn = document.getElementById('shuffle-btn'); if (shuffleBtn) shuffleBtn.classList.remove('active'); - player.shuffleActive = false; - player.playTrackFromQueue(); + Player.instance.shuffleActive = false; + await Player.instance.playTrackFromQueue(); const { showNotification } = await loadDownloadsModule(); showNotification('Shuffling album'); @@ -1012,11 +1234,10 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - 'Shuffling...'; + btn.innerHTML = `${SVG_ANIMATE_SPIN(18)}Shuffling...`; try { - const artist = await api.getArtist(artistId); + const artist = await MusicAPI.instance.getArtist(artistId); const allReleases = [...(artist.albums || []), ...(artist.eps || [])]; const trackSet = new Set(); const allTracks = []; @@ -1028,7 +1249,7 @@ document.addEventListener('DOMContentLoaded', async () => { await Promise.all( chunk.map(async (album) => { try { - const { tracks } = await api.getAlbum(album.id); + const { tracks } = await MusicAPI.instance.getAlbum(album.id); tracks.forEach((track) => { if (!trackSet.has(track.id)) { trackSet.add(track.id); @@ -1057,11 +1278,11 @@ document.addEventListener('DOMContentLoaded', async () => { } const shuffledTracks = [...allTracks].sort(() => Math.random() - 0.5); - player.setQueue(shuffledTracks, 0); + Player.instance.setQueue(shuffledTracks, 0); const shuffleBtn = document.getElementById('shuffle-btn'); if (shuffleBtn) shuffleBtn.classList.remove('active'); - player.shuffleActive = false; - player.playTrackFromQueue(); + Player.instance.shuffleActive = false; + await Player.instance.playTrackFromQueue(); const { showNotification } = await loadDownloadsModule(); showNotification('Shuffling artist discography'); @@ -1085,13 +1306,18 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - 'Downloading...'; + btn.innerHTML = `${SVG_ANIMATE_SPIN(20)}Downloading...`; try { - const { mix, tracks } = await api.getMix(mixId); + const { mix, tracks } = await MusicAPI.instance.getMix(mixId); const { downloadPlaylistAsZip } = await loadDownloadsModule(); - await downloadPlaylistAsZip(mix, tracks, api, downloadQualitySettings.getQuality(), lyricsManager); + await downloadPlaylistAsZip( + mix, + tracks, + MusicAPI.instance, + downloadQualitySettings.getQuality(), + lyricsManager + ); } catch (error) { console.error('Mix download failed:', error); alert('Failed to download mix: ' + error.message); @@ -1110,8 +1336,7 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - 'Downloading...'; + btn.innerHTML = `${SVG_ANIMATE_SPIN(20)}Downloading...`; try { let playlist, tracks; @@ -1129,13 +1354,19 @@ document.addEventListener('DOMContentLoaded', async () => { playlist = { ...userPlaylist, title: userPlaylist.name || userPlaylist.title }; tracks = userPlaylist.tracks || []; } else { - const data = await api.getPlaylist(playlistId); + const data = await MusicAPI.instance.getPlaylist(playlistId); playlist = data.playlist; tracks = data.tracks; } const { downloadPlaylistAsZip } = await loadDownloadsModule(); - await downloadPlaylistAsZip(playlist, tracks, api, downloadQualitySettings.getQuality(), lyricsManager); + await downloadPlaylistAsZip( + playlist, + tracks, + MusicAPI.instance, + downloadQualitySettings.getQuality(), + lyricsManager + ); } catch (error) { console.error('Playlist download failed:', error); alert('Failed to download playlist: ' + error.message); @@ -1145,7 +1376,7 @@ document.addEventListener('DOMContentLoaded', async () => { } } - if (e.target.closest('#create-playlist-btn')) { + if (e.target.closest('#create-playlist-btn') || e.target.closest('#library-create-playlist-card')) { trackOpenModal('Create Playlist'); const modal = document.getElementById('playlist-modal'); document.getElementById('playlist-modal-title').textContent = 'Create Playlist'; @@ -1199,7 +1430,7 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('playlist-name-input').focus(); } - if (e.target.closest('#create-folder-btn')) { + if (e.target.closest('#create-folder-btn') || e.target.closest('#library-create-folder-card')) { trackOpenModal('Create Folder'); const modal = document.getElementById('folder-modal'); document.getElementById('folder-name-input').value = ''; @@ -1216,7 +1447,7 @@ document.addEventListener('DOMContentLoaded', async () => { const folder = await db.createFolder(name, cover); trackCreateFolder(folder); await syncManager.syncUserFolder(folder, 'create'); - ui.renderLibraryPage(); + UIRenderer.instance.renderLibraryPage(); document.getElementById('folder-modal').classList.remove('active'); trackCloseModal('Create Folder'); } else { @@ -1228,6 +1459,19 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('folder-modal').classList.remove('active'); } + if (e.target.closest('#library-liked-tracks-view-list')) { + localStorage.setItem('libraryLikedTracksView', 'list'); + if (window.location.pathname.split('/').filter(Boolean)[0] === 'library') { + await UIRenderer.instance.renderLibraryPage(); + } + } + if (e.target.closest('#library-liked-tracks-view-grid')) { + localStorage.setItem('libraryLikedTracksView', 'grid'); + if (window.location.pathname.split('/').filter(Boolean)[0] === 'library') { + await UIRenderer.instance.renderLibraryPage(); + } + } + if (e.target.closest('#delete-folder-btn')) { const folderId = window.location.pathname.split('/')[2]; if (folderId && confirm('Are you sure you want to delete this folder?')) { @@ -1242,6 +1486,7 @@ document.addEventListener('DOMContentLoaded', async () => { let name = document.getElementById('playlist-name-input').value.trim(); let description = document.getElementById('playlist-description-input').value.trim(); const isPublic = document.getElementById('playlist-public-toggle')?.checked; + const isStrictAlbumMatch = document.getElementById('strict-album-match-toggle')?.checked; if (name) { const modal = document.getElementById('playlist-modal'); @@ -1277,10 +1522,10 @@ document.addEventListener('DOMContentLoaded', async () => { await handlePublicStatus(playlist); await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); syncManager.syncUserPlaylist(playlist, 'update'); - ui.renderLibraryPage(); + UIRenderer.instance.renderLibraryPage(); // Also update current page if we are on it if (window.location.pathname === `/userplaylist/${editingId}`) { - ui.renderPlaylistPage(editingId, 'user'); + UIRenderer.instance.renderPlaylistPage(editingId, 'user'); } modal.classList.remove('active'); delete modal.dataset.editingId; @@ -1294,7 +1539,7 @@ document.addEventListener('DOMContentLoaded', async () => { const xmlFileInput = document.getElementById('xml-file-input'); const m3uFileInput = document.getElementById('m3u-file-input'); - const importOptions = { strictArtistMatch: true, albumMatch: true }; + const importOptions = { strictArtistMatch: true, strictAlbumMatch: isStrictAlbumMatch }; let tracks = []; let importSource = 'manual'; @@ -1371,7 +1616,7 @@ document.addEventListener('DOMContentLoaded', async () => { const result = await parseCSV( csvText, - api, + MusicAPI.instance, (progress) => { const percentage = totalTracks > 0 ? (progress.current / totalTracks) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; @@ -1397,7 +1642,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (err) { @@ -1432,7 +1677,7 @@ document.addEventListener('DOMContentLoaded', async () => { const jspfText = await file.text(); - const result = await parseJSPF(jspfText, api, (progress) => { + const result = await parseJSPF(jspfText, MusicAPI.instance, (progress) => { const percentage = progress.total > 0 ? (progress.current / progress.total) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; progressCurrent.textContent = progress.current.toString(); @@ -1482,7 +1727,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (error) { @@ -1520,7 +1765,7 @@ document.addEventListener('DOMContentLoaded', async () => { const result = await parseDynamicCSV( csvText, - api, + MusicAPI.instance, (progress) => { const percentage = totalItems > 0 ? (progress.current / totalItems) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; @@ -1535,19 +1780,30 @@ document.addEventListener('DOMContentLoaded', async () => { importOptions ); - const hasMultipleTypes = - result.tracks.length > 0 && (result.albums.length > 0 || result.artists.length > 0); + const isLibraryImport = + result.albums.length > 0 || + result.artists.length > 0 || + Object.keys(result.playlists).length > 1; - if (hasMultipleTypes) { + if (isLibraryImport) { currentTrackElement.textContent = 'Adding to library...'; - const importResults = await importToLibrary(result, db, (progress) => { - if (progress.action === 'playlist') { - currentTrackElement.textContent = `Creating playlist: ${progress.item}`; - } else { - currentTrackElement.textContent = `Adding ${progress.action}: ${progress.item}`; + const importResults = await importToLibrary( + result, + db, + (progress) => { + if (progress.action === 'playlist') { + currentTrackElement.textContent = `Creating playlist: ${progress.item}`; + } else { + currentTrackElement.textContent = `Adding ${progress.action}: ${progress.item}`; + } + }, + { + favoriteTracks: false, + favoriteAlbums: false, + favoriteArtists: false, } - }); + ); console.log('Import results:', importResults); @@ -1569,7 +1825,6 @@ document.addEventListener('DOMContentLoaded', async () => { }` ); progressElement.style.display = 'none'; - return; } tracks = result.tracks; @@ -1586,7 +1841,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (error) { @@ -1621,7 +1876,7 @@ document.addEventListener('DOMContentLoaded', async () => { const xspfText = await file.text(); - const result = await parseXSPF(xspfText, api, (progress) => { + const result = await parseXSPF(xspfText, MusicAPI.instance, (progress) => { const percentage = progress.total > 0 ? (progress.current / progress.total) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; progressCurrent.textContent = progress.current.toString(); @@ -1645,7 +1900,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (error) { @@ -1680,7 +1935,7 @@ document.addEventListener('DOMContentLoaded', async () => { const xmlText = await file.text(); - const result = await parseXML(xmlText, api, (progress) => { + const result = await parseXML(xmlText, MusicAPI.instance, (progress) => { const percentage = progress.total > 0 ? (progress.current / progress.total) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; progressCurrent.textContent = progress.current.toString(); @@ -1704,7 +1959,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (error) { @@ -1739,7 +1994,7 @@ document.addEventListener('DOMContentLoaded', async () => { const m3uText = await file.text(); - const result = await parseM3U(m3uText, api, (progress) => { + const result = await parseM3U(m3uText, MusicAPI.instance, (progress) => { const percentage = progress.total > 0 ? (progress.current / progress.total) * 100 : 0; progressFill.style.width = `${Math.min(percentage, 100)}%`; progressCurrent.textContent = progress.current.toString(); @@ -1763,7 +2018,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (missingTracks.length > 0) { setTimeout(() => { - showMissingTracksNotification(missingTracks); + showMissingTracksNotification(missingTracks, name || 'Untitled'); }, 500); } } catch (error) { @@ -1793,7 +2048,7 @@ document.addEventListener('DOMContentLoaded', async () => { await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); await syncManager.syncUserPlaylist(playlist, 'create'); trackCreatePlaylist(playlist, importSource); - ui.renderLibraryPage(); + UIRenderer.instance.renderLibraryPage(); modal.classList.remove('active'); trackCloseModal('Create Playlist'); }); @@ -1871,7 +2126,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (confirm('Are you sure you want to delete this playlist?')) { db.deletePlaylist(playlistId).then(() => { syncManager.syncUserPlaylist({ id: playlistId }, 'delete'); - ui.renderLibraryPage(); + UIRenderer.instance.renderLibraryPage(); }); } } @@ -1965,7 +2220,7 @@ document.addEventListener('DOMContentLoaded', async () => { const updatedPlaylist = await db.removeTrackFromPlaylist(playlistId, trackId, trackType); syncManager.syncUserPlaylist(updatedPlaylist, 'update'); const scrollTop = document.querySelector('.main-content').scrollTop; - await ui.renderPlaylistPage(playlistId, 'user'); + await UIRenderer.instance.renderPlaylistPage(playlistId, 'user'); document.querySelector('.main-content').scrollTop = scrollTop; } }); @@ -1986,7 +2241,7 @@ document.addEventListener('DOMContentLoaded', async () => { } else { // Try API, if fail, try Public Pocketbase try { - const { tracks: apiTracks } = await api.getPlaylist(playlistId); + const { tracks: apiTracks } = await MusicAPI.instance.getPlaylist(playlistId); tracks = apiTracks; } catch (e) { const publicPlaylist = await syncManager.getPublicPlaylist(playlistId); @@ -1998,9 +2253,9 @@ document.addEventListener('DOMContentLoaded', async () => { } } if (tracks.length > 0) { - player.setQueue(tracks, 0); + Player.instance.setQueue(tracks, 0); document.getElementById('shuffle-btn').classList.remove('active'); - player.playTrackFromQueue(); + await Player.instance.playTrackFromQueue(); } } catch (error) { console.error('Failed to play playlist:', error); @@ -2017,13 +2272,18 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - 'Downloading...'; + btn.innerHTML = `${SVG_ANIMATE_SPIN(20)}Downloading...`; try { - const { album, tracks } = await api.getAlbum(albumId); + const { album, tracks } = await MusicAPI.instance.getAlbum(albumId); const { downloadAlbumAsZip } = await loadDownloadsModule(); - await downloadAlbumAsZip(album, tracks, api, downloadQualitySettings.getQuality(), lyricsManager); + await downloadAlbumAsZip( + album, + tracks, + MusicAPI.instance, + downloadQualitySettings.getQuality(), + lyricsManager + ); } catch (error) { console.error('Album download failed:', error); alert('Failed to download album: ' + error.message); @@ -2041,7 +2301,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (!albumId) return; try { - const { tracks } = await api.getAlbum(albumId); + const { tracks } = await MusicAPI.instance.getAlbum(albumId); if (!tracks || tracks.length === 0) { const { showNotification } = await loadDownloadsModule(); @@ -2141,11 +2401,10 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - 'Loading...'; + btn.innerHTML = `${SVG_ANIMATE_SPIN(20)}Loading...`; try { - const artist = await api.getArtist(artistId); + const artist = await MusicAPI.instance.getArtist(artistId); const allReleases = [...(artist.albums || []), ...(artist.eps || [])]; if (allReleases.length === 0) { @@ -2167,7 +2426,7 @@ document.addEventListener('DOMContentLoaded', async () => { await Promise.all( chunk.map(async (album) => { try { - const { tracks } = await api.getAlbum(album.id); + const { tracks } = await MusicAPI.instance.getAlbum(album.id); tracks.forEach((track) => { if (!trackSet.has(track.id)) { trackSet.add(track.id); @@ -2187,8 +2446,8 @@ document.addEventListener('DOMContentLoaded', async () => { [allTracks[i], allTracks[j]] = [allTracks[j], allTracks[i]]; } - player.setQueue(allTracks, 0); - player.playTrackFromQueue(); + Player.instance.setQueue(allTracks, 0); + await Player.instance.playTrackFromQueue(); } else { throw new Error('No tracks found across all albums'); } @@ -2215,9 +2474,9 @@ document.addEventListener('DOMContentLoaded', async () => { const j = Math.floor(Math.random() * (i + 1)); [likedTracks[i], likedTracks[j]] = [likedTracks[j], likedTracks[i]]; } - player.setQueue(likedTracks, 0); + Player.instance.setQueue(likedTracks, 0); document.getElementById('shuffle-btn').classList.remove('active'); - player.playTrackFromQueue(); + await Player.instance.playTrackFromQueue(); } } catch (error) { console.error('Failed to shuffle liked tracks:', error); @@ -2230,8 +2489,7 @@ document.addEventListener('DOMContentLoaded', async () => { btn.disabled = true; const originalHTML = btn.innerHTML; - btn.innerHTML = - ''; + btn.innerHTML = SVG_ANIMATE_SPIN(16); try { const likedTracks = await db.getFavorites('track'); @@ -2240,7 +2498,12 @@ document.addEventListener('DOMContentLoaded', async () => { return; } const { downloadLikedTracks } = await loadDownloadsModule(); - await downloadLikedTracks(likedTracks, api, downloadQualitySettings.getQuality(), lyricsManager); + await downloadLikedTracks( + likedTracks, + MusicAPI.instance, + downloadQualitySettings.getQuality(), + lyricsManager + ); } catch (error) { console.error('Liked tracks download failed:', error); alert('Failed to download liked tracks: ' + error.message); @@ -2258,8 +2521,14 @@ document.addEventListener('DOMContentLoaded', async () => { if (!artistId) return; try { - const artist = await api.getArtist(artistId); - showDiscographyDownloadModal(artist, api, downloadQualitySettings.getQuality(), lyricsManager, btn); + const artist = await MusicAPI.instance.getArtist(artistId); + showDiscographyDownloadModal( + artist, + MusicAPI.instance, + downloadQualitySettings.getQuality(), + lyricsManager, + btn + ); } catch (error) { console.error('Failed to load artist for discography download:', error); alert('Failed to load artist: ' + error.message); @@ -2394,7 +2663,7 @@ document.addEventListener('DOMContentLoaded', async () => { const searchForm = document.getElementById('search-form'); const searchInput = document.getElementById('search-input'); - ui.setupSearchClearButton(searchInput); + UIRenderer.instance.setupSearchClearButton(searchInput); const performSearch = (query) => { if (query) { @@ -2447,16 +2716,16 @@ document.addEventListener('DOMContentLoaded', async () => { searchInput.addEventListener('change', (e) => { const query = e.target.value.trim(); if (query) { - ui.addToSearchHistory(query); + UIRenderer.instance.addToSearchHistory(query); } }); searchInput.addEventListener('focus', () => { - ui.renderSearchHistory(); + UIRenderer.instance.renderSearchHistory(); }); searchInput.addEventListener('click', () => { - ui.renderSearchHistory(); + UIRenderer.instance.renderSearchHistory(); }); document.addEventListener('click', (e) => { @@ -2472,7 +2741,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (!query) return; if (!handleExternalLink(query)) { - ui.addToSearchHistory(query); + UIRenderer.instance.addToSearchHistory(query); performSearch(query); const historyEl = document.getElementById('search-history'); if (historyEl) historyEl.style.display = 'none'; @@ -2489,16 +2758,16 @@ document.addEventListener('DOMContentLoaded', async () => { console.log('Gone offline'); }); - document.querySelector('.now-playing-bar .play-pause-btn').innerHTML = SVG_PLAY; + document.querySelector('.now-playing-bar .play-pause-btn').innerHTML = SVG_PLAY(20); - const router = createRouter(ui); + const router = createRouter(UIRenderer.instance); const handleRouteChange = async (event) => { const overlay = document.getElementById('fullscreen-cover-overlay'); const isFullscreenOpen = overlay && getComputedStyle(overlay).display === 'flex'; if (isFullscreenOpen && window.location.hash !== '#fullscreen') { - ui.closeFullscreenCover(); + UIRenderer.instance.closeFullscreenCover(); } if (event && event.state && event.state.exitTrap) { @@ -2527,7 +2796,7 @@ document.addEventListener('DOMContentLoaded', async () => { } await router(); - updateTabTitle(player); + updateTabTitle(Player.instance); }; await handleRouteChange(); @@ -2549,7 +2818,7 @@ document.addEventListener('DOMContentLoaded', async () => { }); audioPlayer.addEventListener('play', () => { - updateTabTitle(player); + updateTabTitle(Player.instance); }); // PWA Update Logic @@ -2598,45 +2867,18 @@ document.addEventListener('DOMContentLoaded', async () => { }); } - // Donate Modal Logic - const donateModal = document.getElementById('donate-modal'); - const closeDonateModalBtn = document.getElementById('close-donate-modal-btn'); - const sidebarDonateLink = document.getElementById('sidebar-donate-link'); - const donateBtnAbout = document.getElementById('donate-btn'); - const donateBtnPage = document.getElementById('donate-btn-page'); - - const openDonateModal = (e) => { - if (e) e.preventDefault(); - trackOpenModal('Donate'); - donateModal.classList.add('active'); - }; - - const closeDonateModal = () => { - donateModal.classList.remove('active'); - trackCloseModal('Donate'); - }; - - if (donateModal) { - if (closeDonateModalBtn) closeDonateModalBtn.addEventListener('click', closeDonateModal); - donateModal.querySelector('.modal-overlay')?.addEventListener('click', closeDonateModal); - - if (sidebarDonateLink) sidebarDonateLink.addEventListener('click', openDonateModal); - if (donateBtnAbout) donateBtnAbout.addEventListener('click', openDonateModal); - if (donateBtnPage) donateBtnPage.addEventListener('click', openDonateModal); - } - // Listener for Pocketbase Sync updates window.addEventListener('library-changed', () => { const path = window.location.pathname; if (path === '/library') { - ui.renderLibraryPage(); + UIRenderer.instance.renderLibraryPage(); } else if (path === '/' || path === '/home') { - ui.renderHomePage(); + UIRenderer.instance.renderHomePage(); } else if (path.startsWith('/userplaylist/')) { const playlistId = path.split('/')[2]; const content = document.querySelector('.main-content'); const scroll = content ? content.scrollTop : 0; - ui.renderPlaylistPage(playlistId, 'user').then(() => { + UIRenderer.instance.renderPlaylistPage(playlistId, 'user').then(() => { if (content) content.scrollTop = scroll; }); } @@ -2644,7 +2886,7 @@ document.addEventListener('DOMContentLoaded', async () => { window.addEventListener('history-changed', () => { const path = window.location.pathname; if (path === '/recent') { - ui.renderRecentPage(); + UIRenderer.instance.renderRecentPage(); } }); @@ -2717,11 +2959,42 @@ document.addEventListener('DOMContentLoaded', async () => { headerAccountDropdown.innerHTML = ''; if (!user) { + const iconBtnStyle = + 'background:none;border:none;cursor:pointer;padding:4px;border-radius:6px;display:flex;align-items:center;transition:opacity 0.15s'; headerAccountDropdown.innerHTML = ` - + Connect with +
    + + + + +
    +
    `; + + for (const id of [ + 'header-discord-auth', + 'header-google-auth', + 'header-github-auth', + 'header-spotify-auth', + ]) { + const btn = document.getElementById(id); + const svg = btn.querySelector('svg'); + svg.style.filter = 'brightness(0) invert(1)'; + svg.style.transition = 'filter 0.15s'; + btn.addEventListener('mouseenter', () => { + svg.style.filter = 'brightness(0) invert(0.5)'; + }); + btn.addEventListener('mouseleave', () => { + svg.style.filter = 'brightness(0) invert(1)'; + }); + } + document.getElementById('header-google-auth').onclick = () => authManager.signInWithGoogle(); + document.getElementById('header-github-auth').onclick = () => authManager.signInWithGitHub(); + document.getElementById('header-discord-auth').onclick = () => authManager.signInWithDiscord(); + document.getElementById('header-spotify-auth').onclick = () => authManager.signInWithSpotify(); document.getElementById('header-email-auth').onclick = () => { document.getElementById('email-auth-modal').classList.add('active'); headerAccountDropdown.classList.remove('active'); @@ -2765,7 +3038,7 @@ document.addEventListener('DOMContentLoaded', async () => { } } headerAccountImg.style.display = 'none'; - headerAccountIcon.style.display = 'block'; + headerAccountIcon.style.display = 'flex'; }); } }); @@ -2787,10 +3060,7 @@ function showUpdateNotification(updateCallback) {
    `; @@ -2818,10 +3088,11 @@ function escapeHtml(text) { return div.innerHTML; } -function showMissingTracksNotification(missingTracks) { +function showMissingTracksNotification(missingTracks, playlistName) { const modal = document.getElementById('missing-tracks-modal'); const listUl = document.getElementById('missing-tracks-list-ul'); const copyBtn = document.getElementById('copy-missing-tracks-btn'); + const exportCSVBtn = document.getElementById('export-missing-tracks-csv-btn'); listUl.innerHTML = missingTracks .map((track) => { @@ -2836,13 +3107,16 @@ function showMissingTracksNotification(missingTracks) { copyBtn.parentNode.replaceChild(newCopyBtn, copyBtn); newCopyBtn.addEventListener('click', () => { - const textToCopy = missingTracks - .map((track) => { - return typeof track === 'string' - ? track - : `${track.artist ? track.artist + ' - ' : ''}${track.title}`; - }) - .join('\n'); + const header = `Missing songs from ${playlistName} import:\n\n`; + const textToCopy = + header + + missingTracks + .map((track) => { + return typeof track === 'string' + ? track + : `${track.artist ? track.artist + ' - ' : ''}${track.title}`; + }) + .join('\n'); navigator.clipboard.writeText(textToCopy).then(() => { const originalText = newCopyBtn.textContent; @@ -2852,6 +3126,38 @@ function showMissingTracksNotification(missingTracks) { }); } + if (exportCSVBtn) { + const newExportBtn = exportCSVBtn.cloneNode(true); + exportCSVBtn.parentNode.replaceChild(newExportBtn, exportCSVBtn); + + newExportBtn.addEventListener('click', () => { + const headers = ['Artist', 'Title', 'Album']; + let csvContent = headers.join(',') + '\n'; + + missingTracks.forEach((track) => { + if (typeof track === 'string') { + csvContent += `"${track.replace(/"/g, '""')}","",""\n`; + } else { + const artist = (track.artist || '').replace(/"/g, '""'); + const title = (track.title || '').replace(/"/g, '""'); + const album = (track.album || '').replace(/"/g, '""'); + csvContent += `"${artist}","${title}","${album}"\n`; + } + }); + + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.setAttribute('href', url); + const fileName = `${playlistName.replace(/[^a-z0-9]/gi, '_').toLowerCase()}_missing_tracks.csv`; + link.setAttribute('download', fileName); + link.style.visibility = 'hidden'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }); + } + const closeModal = () => modal.classList.remove('active'); // Remove old listeners if any (though usually these functions are called once per instance, @@ -2928,8 +3234,7 @@ function showDiscographyDownloadModal(artist, api, quality, lyricsManager, trigg triggerBtn.disabled = true; const originalHTML = triggerBtn.innerHTML; - triggerBtn.innerHTML = - 'Downloading...'; + triggerBtn.innerHTML = `${SVG_ANIMATE_SPIN(20)}Downloading...`; try { const { downloadDiscography } = await loadDownloadsModule(); @@ -3027,10 +3332,7 @@ function showCustomizeShortcutsModal() {
    ${keyDisplay}
    `; diff --git a/js/audio-context.js b/js/audio-context.js index f2c8fd124..ddbc192f8 100644 --- a/js/audio-context.js +++ b/js/audio-context.js @@ -2,6 +2,7 @@ // Shared Audio Context Manager - handles EQ and provides context for visualizer // Supports 3-32 parametric EQ bands +import { isIos } from './platform-detection.js'; import { equalizerSettings, monoAudioSettings } from './storage.js'; // Generate frequency array for given number of bands using logarithmic spacing @@ -299,9 +300,7 @@ class AudioContextManager { this.audio = audioElement; - // Detect iOS - skip Web Audio initialization on iOS to avoid lock screen audio issues - const isIOS = typeof window !== 'undefined' && window.__IS_IOS__ === true; - if (isIOS) { + if (isIos) { console.log('[AudioContext] Skipping Web Audio initialization on iOS for lock screen compatibility'); return; } @@ -701,6 +700,8 @@ class AudioContextManager { return this.preamp || 0; } + /** + * Called when the app enters the background (screen lock, app switch). /** * Export equalizer settings to text format * @returns {string} Exported settings in text format diff --git a/js/bulk-download-writer.ts b/js/bulk-download-writer.ts new file mode 100644 index 000000000..ec55309d5 --- /dev/null +++ b/js/bulk-download-writer.ts @@ -0,0 +1,303 @@ +import { triggerDownload } from './download-utils'; +import { readableStreamIterator } from './readableStreamIterator'; + +/** + * A single entry to be included in a ZIP archive or written directly to a folder. + */ +export interface WriterEntry { + name: string; + lastModified: Date; + input: Blob | File | string | ArrayBuffer | Uint8Array; +} + +/** Minimal interface for the Neutralino bridge used by ZipNeutralinoWriter */ +interface NeutralinoBridge { + os: { + showSaveDialog( + title: string, + options: { defaultPath: string; filters: Array<{ name: string; extensions: string[] }> } + ): Promise; + showFolderDialog(title: string, options?: Record): Promise; + }; + filesystem: { + writeBinaryFile(path: string, buffer: ArrayBuffer): Promise; + appendBinaryFile(path: string, buffer: ArrayBuffer): Promise; + createDirectory(path: string): Promise; + }; +} + +async function loadClientZip() { + try { + return await import('client-zip'); + } catch (error) { + console.error('Failed to load client-zip:', error); + throw new Error('Failed to load ZIP library'); + } +} + +/** + * Interface for writing a collection of file entries to an output destination. + * Each implementation handles its own output selection (save dialog, directory picker, etc.) + * and throws a DOMException with name 'AbortError' if the user cancels. + */ +export interface IBulkDownloadWriter { + write(files: AsyncIterable): Promise; +} + +/** + * Triggers individual downloads for each file entry, one after another. + */ +class SequentialFileWriter implements IBulkDownloadWriter { + constructor() {} + + async write(files: AsyncIterable): Promise { + for await (const file of files) { + const name = file.name?.split('/').pop(); + const ext = name?.split('.').pop().toLowerCase(); + + if (!name) { + console.warn('No name for file entry.', file); + continue; + } + + if (['m3u', 'm3u8', 'cue', 'jpg', 'png', 'nfo', 'json'].includes(ext)) { + continue; + } + + if (file.input instanceof Blob || file.input instanceof File) { + triggerDownload(file.input, name); + } else { + triggerDownload(new Blob([file.input as BlobPart]), name); + } + await new Promise((resolve) => setTimeout(resolve, 500)); + } + } +} + +const sequentialFileWriter = new SequentialFileWriter(); + +export { sequentialFileWriter as SequentialFileWriter }; + +/** + * Streams a ZIP archive to a file via the File System Access API. + * Prompts the user to choose a save location with showSaveFilePicker. + */ +export class ZipStreamWriter implements IBulkDownloadWriter { + constructor(private readonly suggestedFilename: string) {} + + async write(files: AsyncIterable): Promise { + // showSaveFilePicker is part of the File System Access API (not yet in all TS DOM libs) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const fileHandle = await (window as any).showSaveFilePicker({ + suggestedName: this.suggestedFilename, + types: [{ description: 'ZIP Archive', accept: { 'application/zip': ['.zip'] } }], + }); + const { downloadZip } = await loadClientZip(); + const writable = await fileHandle.createWritable(); + const response = downloadZip(files); + if (!response.body) throw new Error('ZIP response body is null'); + await response.body.pipeTo(writable); + } +} + +/** + * Collects a ZIP archive into a Blob and triggers a browser download. + * Works on all browsers without requiring the File System Access API. + */ +export class ZipBlobWriter implements IBulkDownloadWriter { + constructor(private readonly filename: string) {} + + async write(files: AsyncIterable): Promise { + const { downloadZip } = await loadClientZip(); + const response = downloadZip(files); + const blob = await response.blob(); + triggerDownload(blob, this.filename); + } +} + +/** + * Writes a ZIP archive to the filesystem via the Neutralino desktop bridge, + * showing a native save dialog first. + */ +export class ZipNeutralinoWriter implements IBulkDownloadWriter { + constructor(private readonly folderName: string) {} + + async write(files: AsyncIterable): Promise { + const bridge = (await import('./desktop/neutralino-bridge.js')) as unknown as NeutralinoBridge; + + const savePath = await bridge.os.showSaveDialog(`Select save location for ${this.folderName}.zip`, { + defaultPath: `${this.folderName}.zip`, + filters: [{ name: 'ZIP Archive', extensions: ['zip'] }], + }); + + if (!savePath) { + throw new DOMException('User cancelled save dialog', 'AbortError'); + } + + const { downloadZip } = await loadClientZip(); + const response = downloadZip(files); + if (!response.body) throw new Error('ZIP response body is null'); + + await bridge.filesystem.writeBinaryFile(savePath, new ArrayBuffer(0)); + + const reader = response.body.getReader(); + let receivedLength = 0; + + for await (const value of readableStreamIterator(response.body)) { + const chunk = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength); + await bridge.filesystem.appendBinaryFile(savePath, chunk); + receivedLength += value.length; + } + + console.log(`[ZIP] Download complete. Total size: ${receivedLength} bytes.`); + } +} + +/** + * Writes files directly into a user-chosen folder using the standard browser + * File System Access API (showDirectoryPicker). Subdirectories embedded in + * file entry names are created automatically. + * + * Use the static {@link FolderPickerWriter.create} method to obtain an instance; + * the constructor is private so the directory handle is always set before use. + */ +export class FolderPickerWriter implements IBulkDownloadWriter { + private constructor(private readonly dirHandle: FileSystemDirectoryHandle) {} + + /** Returns the underlying directory handle (e.g. to persist it for later re-use). */ + getDirHandle(): FileSystemDirectoryHandle { + return this.dirHandle; + } + + /** + * Creates a {@link FolderPickerWriter} from an already-obtained handle + * without showing a directory picker. Useful when re-using a stored handle + * whose permission has already been verified by the caller. + */ + static fromHandle(handle: FileSystemDirectoryHandle): FolderPickerWriter { + return new FolderPickerWriter(handle); + } + + /** + * Prompts the user to pick a writable directory, or re-uses a previously + * saved handle when one is supplied and write permission can be obtained. + * Returns a new {@link FolderPickerWriter} bound to the chosen directory. + * If the user dismisses the picker, the promise rejects with a DOMException + * whose name is "AbortError". + */ + static async create(savedHandle?: FileSystemDirectoryHandle | null): Promise { + // Try to re-use a saved handle first + if (savedHandle) { + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const permission = await (savedHandle as any).requestPermission({ mode: 'readwrite' }); + if (permission === 'granted') { + return new FolderPickerWriter(savedHandle); + } + } catch { + // Fall through to show the picker + } + } + + // showDirectoryPicker is part of the File System Access API (not yet in all TS DOM libs) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + try { + const dirHandle: FileSystemDirectoryHandle = await (window as any).showDirectoryPicker({ + mode: 'readwrite', + }); + return new FolderPickerWriter(dirHandle); + } catch (error) { + if (error instanceof DOMException && error.name === 'AbortError') { + throw error; + } + throw new DOMException('User cancelled directory picker', 'AbortError'); + } + } + + async write(files: AsyncIterable): Promise { + for await (const file of files) { + const parts = file.name.split('/').filter(Boolean); + if (parts.length === 0) continue; + + let currentDir: FileSystemDirectoryHandle = this.dirHandle; + for (let i = 0; i < parts.length - 1; i++) { + currentDir = await currentDir.getDirectoryHandle(parts[i], { create: true }); + } + + const filename = parts[parts.length - 1]; + const fileHandle = await currentDir.getFileHandle(filename, { create: true }); + const writable = await fileHandle.createWritable(); + + try { + const { input } = file; + if (input instanceof Blob) { + await writable.write(input); + } else if (typeof input === 'string') { + await writable.write(new Blob([input], { type: 'text/plain' })); + } else { + const buf = + input instanceof Uint8Array + ? input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) + : input; + await writable.write(new Blob([buf as ArrayBuffer])); + } + + await writable.close(); + } catch (error) { + await writable.abort(); + throw error; + } + } + } +} + +/** + * Writes files directly into a folder on the local filesystem via the + * Neutralino desktop bridge. Subdirectories are created automatically. + */ +export class NeutralinoFolderWriter implements IBulkDownloadWriter { + constructor(private readonly basePath: string) {} + + async write(files: AsyncIterable): Promise { + // Import once per write() call; the module system caches the result. + const bridge = (await import('./desktop/neutralino-bridge.js')) as unknown as NeutralinoBridge; + const createdDirs = new Set(); + + for await (const file of files) { + const parts = file.name.split('/').filter(Boolean); + if (parts.length === 0) continue; + + // Ensure all parent directories exist + for (let i = 1; i < parts.length; i++) { + const dirPath = this.basePath + '/' + parts.slice(0, i).join('/'); + if (!createdDirs.has(dirPath)) { + try { + await bridge.filesystem.createDirectory(dirPath); + } catch { + // Directory may already exist; ignore + } + createdDirs.add(dirPath); + } + } + + const filePath = this.basePath + '/' + file.name; + let buffer: ArrayBuffer; + const { input } = file; + if (input instanceof Blob) { + buffer = await input.arrayBuffer(); + } else if (typeof input === 'string') { + const encoded = new TextEncoder().encode(input); + buffer = encoded.buffer.slice( + encoded.byteOffset, + encoded.byteOffset + encoded.byteLength + ) as ArrayBuffer; + } else if (input instanceof Uint8Array) { + buffer = input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) as ArrayBuffer; + } else { + buffer = input; + } + + await bridge.filesystem.writeBinaryFile(filePath, buffer); + } + } +} diff --git a/js/commandPalette.js b/js/commandPalette.js index b9bae5180..5d45981d3 100644 --- a/js/commandPalette.js +++ b/js/commandPalette.js @@ -1,6 +1,102 @@ import { debounce } from './utils.js'; import { db } from './db.js'; import Fuse from 'fuse.js'; +import { navigate } from './router.js'; +import { + SVG_SEARCH, + SVG_HOUSE, + SVG_LIBRARY, + SVG_CLOCK, + SVG_CALENDAR, + SVG_SETTINGS, + SVG_INFO, + SVG_DOWNLOAD, + SVG_HAND_HEART, + SVG_PLAY, + SVG_SKIP_FORWARD, + SVG_SKIP_BACK, + SVG_SHUFFLE, + SVG_REPEAT, + SVG_MUTE, + SVG_VOLUME_1, + SVG_HEART, + SVG_LIST, + SVG_TRASH, + SVG_ALIGN_LEFT, + SVG_MAXIMIZE, + SVG_SPARKLES, + SVG_MONITOR, + SVG_MOON, + SVG_SUN, + SVG_PALETTE, + SVG_STORE, + SVG_SLIDERS, + SVG_PLUS, + SVG_FOLDER_PLUS, + SVG_KEYBOARD, + SVG_UPLOAD, + SVG_USER, + SVG_PENCIL, + SVG_LOG_OUT, + SVG_LOG_IN, + SVG_MUSIC, + SVG_DISC, + SVG_MIC, + SVG_RADIO, +} from './icons.js'; +import { Player } from './player.js'; +import { UIRenderer } from './ui.js'; + +const ICON_SIZE = 16; + +const ICONS = { + search: SVG_SEARCH, + house: SVG_HOUSE, + library: SVG_LIBRARY, + clock: SVG_CLOCK, + calendar: SVG_CALENDAR, + settings: SVG_SETTINGS, + info: SVG_INFO, + download: SVG_DOWNLOAD, + handHeart: SVG_HAND_HEART, + play: SVG_PLAY, + skipForward: SVG_SKIP_FORWARD, + skipBack: SVG_SKIP_BACK, + shuffle: SVG_SHUFFLE, + repeat: SVG_REPEAT, + volumeX: SVG_MUTE, + volume: SVG_VOLUME_1, + heart: SVG_HEART, + list: SVG_LIST, + trash: SVG_TRASH, + text: SVG_ALIGN_LEFT, + maximize: SVG_MAXIMIZE, + sparkles: SVG_SPARKLES, + monitor: SVG_MONITOR, + moon: SVG_MOON, + sun: SVG_SUN, + palette: SVG_PALETTE, + store: SVG_STORE, + sliders: SVG_SLIDERS, + plus: SVG_PLUS, + folderPlus: SVG_FOLDER_PLUS, + keyboard: SVG_KEYBOARD, + upload: SVG_UPLOAD, + user: SVG_USER, + pencil: SVG_PENCIL, + logOut: SVG_LOG_OUT, + logIn: SVG_LOG_IN, + music: SVG_MUSIC, + disc: SVG_DISC, + mic: SVG_MIC, + radio: SVG_RADIO, +}; + +function escapeHtml(str) { + const div = document.createElement('div'); + div.textContent = str; + return div.innerHTML; +} class CommandPalette { constructor() { @@ -9,60 +105,600 @@ class CommandPalette { this.resultsContainer = document.getElementById('command-palette-results'); this.isOpen = false; this.selectedIndex = 0; - this.results = []; - + this.flatItems = []; this.allSettings = []; - this.debouncedSearch = debounce(this.performSearch.bind(this), 300); + this.musicSearchAbort = null; + this.debouncedMusicSearch = debounce(this.searchMusic.bind(this), 300); + this.commands = this.buildCommands(); + this.fuse = new Fuse(this.commands, { + keys: [ + { name: 'label', weight: 0.6 }, + { name: 'keywords', weight: 0.3 }, + { name: 'group', weight: 0.1 }, + ], + threshold: 0.4, + ignoreLocation: true, + includeScore: true, + }); + + this.init(); + } - this.commands = [ + buildCommands() { + return [ { - name: 'theme', - description: 'Change theme (white, dark, ocean, purple, forest, etc.)', - action: (args) => this.handleTheme(args), + id: 'nav-home', + group: 'Navigation', + icon: 'house', + label: 'Go to Home', + keywords: ['home', 'main', 'start', 'landing'], + action: () => { + navigate('/'); + }, }, { - name: 'play', - description: 'Search and play a track', - action: (args, autoPick) => this.handlePlay(args, autoPick), + id: 'nav-library', + group: 'Navigation', + icon: 'library', + label: 'Go to Library', + keywords: ['library', 'collection', 'playlists', 'favorites'], + action: () => { + navigate('/library'); + }, }, { - name: 'shuffle', - description: 'Shuffle a playlist, artist, or album', - action: (args, autoPick) => this.handleShuffle(args, autoPick), + id: 'nav-recent', + group: 'Navigation', + icon: 'clock', + label: 'Go to Recent', + keywords: ['recent', 'history', 'last played'], + action: () => { + navigate('/recent'); + }, }, { - name: 'queue', - description: 'Manage the queue (wipe, like all, download)', - action: (args) => this.handleQueue(args), + id: 'nav-unreleased', + group: 'Navigation', + icon: 'calendar', + label: 'Go to Unreleased', + keywords: ['unreleased', 'upcoming', 'tracker'], + action: () => { + navigate('/unreleased'); + }, }, { - name: 'setting', - description: 'Search for a specific setting', - action: (args) => this.handleSettingSearch(args), + id: 'nav-settings', + group: 'Navigation', + icon: 'settings', + label: 'Go to Settings', + keywords: ['settings', 'preferences', 'config', 'options'], + shortcut: null, + action: () => { + navigate('/settings'); + }, }, { - name: 'sleep', - description: 'Set sleep timer in minutes', - action: (args) => this.handleSleepTimer(args), + id: 'nav-about', + group: 'Navigation', + icon: 'info', + label: 'Go to About', + keywords: ['about', 'version', 'credits'], + action: () => { + navigate('/about'); + }, }, { - name: 'quality', - description: 'Set streaming & download quality', - action: (args) => this.handleQuality(args), + id: 'nav-download', + group: 'Navigation', + icon: 'download', + label: 'Go to Download', + keywords: ['download', 'desktop', 'app'], + action: () => { + navigate('/download'); + }, }, { - name: 'visualizer', - description: 'Control visualizer (toggle, preset)', - action: (args) => this.handleVisualizer(args), + id: 'nav-donate', + group: 'Navigation', + icon: 'handHeart', + label: 'Go to Donate', + keywords: ['donate', 'support', 'contribute'], + action: () => { + navigate('/donate'); + }, }, + { - name: 'cache', - description: 'Clear application cache', - action: () => this.handleClearCache(), + id: 'play-pause', + group: 'Playback', + icon: 'play', + label: 'Play / Pause', + keywords: ['play', 'pause', 'toggle', 'resume', 'stop'], + shortcut: 'Space', + action: () => { + Player.instance.handlePlayPause(); + }, + }, + { + id: 'play-next', + group: 'Playback', + icon: 'skipForward', + label: 'Next Track', + keywords: ['next', 'skip', 'forward'], + shortcut: 'Shift+\u2192', + action: () => { + Player.instance.playNext(); + }, + }, + { + id: 'play-prev', + group: 'Playback', + icon: 'skipBack', + label: 'Previous Track', + keywords: ['previous', 'back', 'rewind'], + shortcut: 'Shift+\u2190', + action: () => { + Player.instance.playPrev(); + }, + }, + { + id: 'play-shuffle', + group: 'Playback', + icon: 'shuffle', + label: 'Toggle Shuffle', + keywords: ['shuffle', 'random'], + shortcut: 'S', + action: () => { + document.getElementById('shuffle-btn')?.click(); + }, + }, + { + id: 'play-repeat', + group: 'Playback', + icon: 'repeat', + label: 'Toggle Repeat', + keywords: ['repeat', 'loop', 'cycle'], + shortcut: 'R', + action: () => { + document.getElementById('repeat-btn')?.click(); + }, + }, + { + id: 'play-mute', + group: 'Playback', + icon: 'volumeX', + label: 'Mute / Unmute', + keywords: ['mute', 'unmute', 'sound', 'volume', 'silent'], + shortcut: 'M', + action: () => { + const el = Player.instance.activeElement; + if (el) el.muted = !el.muted; + }, + }, + { + id: 'play-vol-up', + group: 'Playback', + icon: 'volume', + label: 'Volume Up', + keywords: ['volume', 'louder'], + shortcut: '\u2191', + action: () => { + const p = Player.instance; + if (p) p.setVolume(p.userVolume + 0.1); + }, + }, + { + id: 'play-vol-down', + group: 'Playback', + icon: 'volume', + label: 'Volume Down', + keywords: ['volume', 'quieter', 'softer'], + shortcut: '\u2193', + action: () => { + const p = Player.instance; + if (p) p.setVolume(p.userVolume - 0.1); + }, }, - ]; - this.init(); + { + id: 'like-current', + group: 'Now Playing', + icon: 'heart', + label: 'Like Current Track', + keywords: ['like', 'favorite', 'love', 'heart', 'save'], + action: () => { + document.querySelector('.now-playing-bar .like-btn')?.click(); + }, + }, + { + id: 'download-current', + group: 'Now Playing', + icon: 'download', + label: 'Download Current Track', + keywords: ['download', 'save', 'current'], + action: () => { + document.querySelector('.now-playing-bar .download-btn')?.click(); + }, + }, + + { + id: 'queue-open', + group: 'Queue', + icon: 'list', + label: 'Open Queue', + keywords: ['queue', 'list', 'up next'], + shortcut: 'Q', + action: () => { + document.getElementById('queue-btn')?.click(); + }, + }, + { + id: 'queue-wipe', + group: 'Queue', + icon: 'trash', + label: 'Clear Queue', + keywords: ['wipe', 'clear', 'empty', 'queue'], + action: () => { + Player.instance.wipeQueue(); + this.notify('Queue cleared'); + }, + }, + { + id: 'queue-like-all', + group: 'Queue', + icon: 'heart', + label: 'Like All in Queue', + keywords: ['like', 'all', 'queue', 'heart', 'favorite'], + action: () => this.likeAllInQueue(), + }, + { + id: 'queue-download', + group: 'Queue', + icon: 'download', + label: 'Download Queue', + keywords: ['download', 'queue', 'save', 'all'], + action: () => this.downloadQueue(), + }, + + { + id: 'lyrics-toggle', + group: 'View', + icon: 'text', + label: 'Toggle Lyrics', + keywords: ['lyrics', 'words', 'text', 'karaoke'], + shortcut: 'L', + action: () => { + document.querySelector('.now-playing-bar .cover')?.click(); + }, + }, + { + id: 'fullscreen-open', + group: 'View', + icon: 'maximize', + label: 'Open Fullscreen View', + keywords: ['fullscreen', 'expand', 'immersive', 'cover'], + action: () => { + const cover = document.querySelector('.now-playing-bar .cover-art'); + if (cover) cover.click(); + }, + }, + { + id: 'vis-toggle', + group: 'View', + icon: 'sparkles', + label: 'Toggle Visualizer', + keywords: ['visualizer', 'visual', 'animation', 'effects'], + action: () => this.toggleVisualizer(), + }, + { + id: 'vis-butterchurn', + group: 'View', + icon: 'sparkles', + label: 'Visualizer: Butterchurn', + keywords: ['butterchurn', 'milkdrop', 'preset', 'visualizer'], + action: () => this.setVisualizerPreset('butterchurn'), + }, + { + id: 'vis-kawarp', + group: 'View', + icon: 'sparkles', + label: 'Visualizer: Kawarp', + keywords: ['kawarp', 'preset', 'visualizer'], + action: () => this.setVisualizerPreset('kawarp'), + }, + { + id: 'vis-lcd', + group: 'View', + icon: 'sparkles', + label: 'Visualizer: LCD', + keywords: ['lcd', 'preset', 'visualizer'], + action: () => this.setVisualizerPreset('lcd'), + }, + { + id: 'vis-particles', + group: 'View', + icon: 'sparkles', + label: 'Visualizer: Particles', + keywords: ['particles', 'preset', 'visualizer'], + action: () => this.setVisualizerPreset('particles'), + }, + { + id: 'vis-unknown', + group: 'View', + icon: 'sparkles', + label: 'Visualizer: Unknown Pleasures', + keywords: ['unknown pleasures', 'preset', 'visualizer', 'joy division'], + action: () => this.setVisualizerPreset('unknown-pleasures'), + }, + + { + id: 'theme-system', + group: 'Theme', + icon: 'monitor', + label: 'Theme: System', + keywords: ['theme', 'system', 'auto', 'default'], + action: () => this.setTheme('system'), + }, + { + id: 'theme-black', + group: 'Theme', + icon: 'moon', + label: 'Theme: Monochrome', + keywords: ['theme', 'monochrome', 'black', 'dark', 'amoled'], + action: () => this.setTheme('monochrome'), + }, + { + id: 'theme-dark', + group: 'Theme', + icon: 'moon', + label: 'Theme: Dark', + keywords: ['theme', 'dark'], + action: () => this.setTheme('dark'), + }, + { + id: 'theme-white', + group: 'Theme', + icon: 'sun', + label: 'Theme: White', + keywords: ['theme', 'white', 'light'], + action: () => this.setTheme('white'), + }, + { + id: 'theme-ocean', + group: 'Theme', + icon: 'palette', + label: 'Theme: Ocean', + keywords: ['theme', 'ocean', 'blue', 'sea'], + action: () => this.setTheme('ocean'), + }, + { + id: 'theme-purple', + group: 'Theme', + icon: 'palette', + label: 'Theme: Purple', + keywords: ['theme', 'purple', 'violet'], + action: () => this.setTheme('purple'), + }, + { + id: 'theme-forest', + group: 'Theme', + icon: 'palette', + label: 'Theme: Forest', + keywords: ['theme', 'forest', 'green', 'nature'], + action: () => this.setTheme('forest'), + }, + { + id: 'theme-mocha', + group: 'Theme', + icon: 'palette', + label: 'Theme: Mocha', + keywords: ['theme', 'mocha', 'catppuccin', 'brown', 'warm'], + action: () => this.setTheme('mocha'), + }, + { + id: 'theme-macchiato', + group: 'Theme', + icon: 'palette', + label: 'Theme: Macchiato', + keywords: ['theme', 'macchiato', 'catppuccin'], + action: () => this.setTheme('machiatto'), + }, + { + id: 'theme-frappe', + group: 'Theme', + icon: 'palette', + label: 'Theme: Frapp\u00e9', + keywords: ['theme', 'frappe', 'catppuccin'], + action: () => this.setTheme('frappe'), + }, + { + id: 'theme-latte', + group: 'Theme', + icon: 'palette', + label: 'Theme: Latte', + keywords: ['theme', 'latte', 'catppuccin', 'light'], + action: () => this.setTheme('latte'), + }, + { + id: 'theme-store', + group: 'Theme', + icon: 'store', + label: 'Open Theme Store', + keywords: ['theme', 'store', 'browse', 'community', 'custom'], + action: () => { + document.getElementById('open-theme-store')?.click(); + }, + }, + + { + id: 'quality-auto', + group: 'Audio', + icon: 'sliders', + label: 'Quality: Auto (Adaptive)', + keywords: ['quality', 'auto', 'adaptive', 'streaming', 'bitrate'], + action: () => this.setQuality('auto'), + }, + { + id: 'quality-low', + group: 'Audio', + icon: 'sliders', + label: 'Quality: Low', + keywords: ['quality', 'low', 'streaming', 'bitrate'], + action: () => this.setQuality('LOW'), + }, + { + id: 'quality-high', + group: 'Audio', + icon: 'sliders', + label: 'Quality: High', + keywords: ['quality', 'high', 'streaming', 'bitrate'], + action: () => this.setQuality('HIGH'), + }, + { + id: 'quality-lossless', + group: 'Audio', + icon: 'sliders', + label: 'Quality: Lossless', + keywords: ['quality', 'lossless', 'flac', 'cd', 'streaming'], + action: () => this.setQuality('LOSSLESS'), + }, + { + id: 'quality-hires', + group: 'Audio', + icon: 'sliders', + label: 'Quality: Hi-Res', + keywords: ['quality', 'hires', 'hi-res', 'master', 'mqa', 'streaming'], + action: () => this.setQuality('HI_RES_LOSSLESS'), + }, + { + id: 'sleep-15', + group: 'Audio', + icon: 'clock', + label: 'Sleep Timer: 15 min', + keywords: ['sleep', 'timer', '15', 'minutes'], + action: () => this.setSleepTimer(15), + }, + { + id: 'sleep-30', + group: 'Audio', + icon: 'clock', + label: 'Sleep Timer: 30 min', + keywords: ['sleep', 'timer', '30', 'minutes'], + action: () => this.setSleepTimer(30), + }, + { + id: 'sleep-60', + group: 'Audio', + icon: 'clock', + label: 'Sleep Timer: 60 min', + keywords: ['sleep', 'timer', '60', 'minutes', 'hour'], + action: () => this.setSleepTimer(60), + }, + { + id: 'sleep-120', + group: 'Audio', + icon: 'clock', + label: 'Sleep Timer: 120 min', + keywords: ['sleep', 'timer', '120', 'minutes', 'hours'], + action: () => this.setSleepTimer(120), + }, + + { + id: 'lib-create-playlist', + group: 'Library', + icon: 'plus', + label: 'Create Playlist', + keywords: ['create', 'new', 'playlist', 'add'], + action: () => this.createPlaylist(), + }, + { + id: 'lib-create-folder', + group: 'Library', + icon: 'folderPlus', + label: 'Create Folder', + keywords: ['create', 'new', 'folder', 'add', 'organize'], + action: () => this.createFolder(), + }, + + { + id: 'sys-cache', + group: 'System', + icon: 'trash', + label: 'Clear Cache', + keywords: ['cache', 'clear', 'reset', 'clean'], + action: () => this.clearCache(), + }, + { + id: 'sys-shortcuts', + group: 'System', + icon: 'keyboard', + label: 'View Keyboard Shortcuts', + keywords: ['keyboard', 'shortcuts', 'keys', 'hotkeys', 'bindings'], + action: () => { + document.getElementById('shortcuts-modal')?.style.setProperty('display', 'flex'); + }, + }, + { + id: 'sys-export', + group: 'System', + icon: 'upload', + label: 'Export Data', + keywords: ['export', 'backup', 'data', 'save'], + action: () => this.navigateToSetting({ tab: 'system', id: 'export-data-btn' }), + }, + { + id: 'sys-search-setting', + group: 'System', + icon: 'search', + label: 'Search Settings...', + keywords: ['setting', 'find', 'search', 'preference', 'option', 'configure'], + keepOpen: true, + action: () => this.enterSettingsMode(), + }, + + { + id: 'acc-profile', + group: 'Account', + icon: 'user', + label: 'View Profile', + keywords: ['profile', 'account', 'user', 'me'], + action: () => { + document.querySelector('.user-avatar-btn')?.click(); + }, + }, + { + id: 'acc-edit-profile', + group: 'Account', + icon: 'pencil', + label: 'Edit Profile', + keywords: ['edit', 'profile', 'username', 'avatar', 'display name'], + action: async () => { + const { openEditProfile } = await import('./profile.js'); + openEditProfile(); + }, + }, + { + id: 'acc-sign-out', + group: 'Account', + icon: 'logOut', + label: 'Sign Out', + keywords: ['sign out', 'log out', 'logout', 'disconnect'], + action: async () => { + const { authManager } = await import('./accounts/auth.js'); + await authManager.signOut(); + }, + }, + { + id: 'acc-sign-in', + group: 'Account', + icon: 'logIn', + label: 'Sign In', + keywords: ['sign in', 'log in', 'login', 'account', 'connect'], + action: () => { + navigate('/account'); + }, + }, + ]; } init() { @@ -90,77 +726,53 @@ class CommandPalette { open() { this.isOpen = true; + this.settingsMode = false; this.overlay.style.display = 'flex'; - this.input.value = '>'; + this.input.value = ''; + this.input.placeholder = 'Search commands, music, settings...'; this.input.focus(); - this.handleInput(); + this.showDefaultCommands(); } close() { this.isOpen = false; + this.settingsMode = false; this.overlay.style.display = 'none'; + this.cancelMusicSearch(); + } + + enterSettingsMode() { + this.settingsMode = true; + this.input.value = ''; + this.input.placeholder = 'Search settings...'; + this.input.focus(); + this.cacheAllSettings(); + this.renderSettingsResults(''); } handleInput() { - const value = this.input.value; + const query = this.input.value.trim(); this.selectedIndex = 0; - if (!value.startsWith('>')) { - this.renderResults([ - { - name: 'Type > to use commands', - description: 'e.g. >theme White, >play The Whole World Is Free', - action: () => { - this.input.value = '>'; - this.handleInput(); - }, - type: 'hint', - }, - ]); + if (this.settingsMode) { + this.renderSettingsResults(query); return; } - const fullQuery = value.slice(1); - const match = fullQuery.match(/^(\S+)(?:\s+(.*))?$/); - - if (!match) { - this.renderDefaultCommands(); + if (!query) { + this.cancelMusicSearch(); + this.showDefaultCommands(); return; } - const cmdName = match[1].toLowerCase(); - const args = match[2] || ''; - - const command = this.commands.find((c) => c.name === cmdName); - - if (command) { - const commandsWithSubmenus = ['queue', 'go', 'visualizer', 'quality', 'sleep', 'setting']; - if (commandsWithSubmenus.includes(command.name) && !args.trim()) { - command.action(args); - return; - } - - this.renderResults([ - { - name: `Execute: ${command.name} ${args}`, - description: args ? `Run ${command.name} for "${args}"` : command.description, - action: () => command.action(args, ['play', 'shuffle', 'setting'].includes(command.name)), - type: 'execution', - }, - ]); - - if (args.trim().length > 0 && (cmdName === 'play' || cmdName === 'shuffle')) { - this.debouncedSearch(cmdName, args.trim()); - } - } else { - this.renderDefaultCommands(cmdName); - } + this.searchCommands(query); + this.debouncedMusicSearch(query); } handleKeydown(e) { if (e.key === 'ArrowDown') { e.preventDefault(); - this.selectedIndex = Math.min(this.selectedIndex + 1, this.results.length - 1); + this.selectedIndex = Math.min(this.selectedIndex + 1, this.flatItems.length - 1); this.updateSelection(); } else if (e.key === 'ArrowUp') { e.preventDefault(); @@ -170,431 +782,329 @@ class CommandPalette { e.preventDefault(); this.executeSelected(); } else if (e.key === 'Escape') { - this.close(); - } - } - - renderDefaultCommands(filter = '') { - let cmds = this.commands; - if (filter) { - if (Fuse) { - const fuse = new Fuse(this.commands, { keys: ['name', 'description'] }); - cmds = fuse.search(filter).map((r) => r.item); + if (this.settingsMode) { + this.settingsMode = false; + this.input.value = ''; + this.input.placeholder = 'Search commands, music, settings...'; + this.showDefaultCommands(); } else { - cmds = this.commands.filter((c) => c.name.includes(filter)); + this.close(); } + } else if (e.key === 'Backspace' && this.settingsMode && !this.input.value) { + this.settingsMode = false; + this.input.placeholder = 'Search commands, music, settings...'; + this.showDefaultCommands(); } + } - this.renderResults( - cmds.map((c) => ({ - name: c.name, - description: c.description, - action: () => { - this.input.value = `>${c.name} `; - this.handleInput(); - }, - type: 'command', - })) + showDefaultCommands() { + const groups = this.groupBy( + this.commands.filter((c) => { + const priority = [ + 'nav-home', + 'nav-library', + 'nav-settings', + 'play-pause', + 'play-next', + 'play-prev', + 'play-shuffle', + 'queue-open', + 'lyrics-toggle', + 'fullscreen-open', + 'sys-search-setting', + ]; + return priority.includes(c.id); + }), + 'group' ); + + this.renderGroups(groups); } - renderResults(results) { - this.results = results; - this.resultsContainer.innerHTML = ''; + searchCommands(query) { + const fuseResults = this.fuse.search(query).slice(0, 12); + const matched = fuseResults.map((r) => r.item); - if (results.length === 0) { - this.resultsContainer.innerHTML = - '
    No results found
    '; + if (matched.length === 0) { + this.renderGroups({}); return; } - results.forEach((result, index) => { - const div = document.createElement('div'); - div.className = `command-result-item ${index === this.selectedIndex ? 'selected' : ''}`; - - const imgHtml = result.image - ? `` - : ''; - - div.innerHTML = ` -
    - ${imgHtml} -
    ${result.name}${result.description || ''}
    -
    - `; - div.addEventListener('click', () => { - this.selectedIndex = index; - this.executeSelected(); - }); - this.resultsContainer.appendChild(div); - }); + const groups = this.groupBy(matched, 'group'); + this.renderGroups(groups); } - updateSelection() { - const items = this.resultsContainer.querySelectorAll('.command-result-item'); - items.forEach((item, index) => { - if (index === this.selectedIndex) { - item.classList.add('selected'); - item.scrollIntoView({ block: 'nearest' }); - } else { - item.classList.remove('selected'); - } - }); - } + async searchMusic(query) { + if (!query || query.length < 2) return; - executeSelected() { - const result = this.results[this.selectedIndex]; - if (result && result.action) { - result.action(); - if (result.type !== 'hint') { - this.close(); - } - } else if (result && result.type === 'command') { - this.input.value = `>${result.name} `; - this.handleInput(); - } - } + const api = UIRenderer.instance.api; + if (!api) return; - handleTheme(args) { - if (!args) return; - const theme = args.trim().toLowerCase(); - document.documentElement.setAttribute('data-theme', theme); - localStorage.setItem('theme', theme); + this.cancelMusicSearch(); + const controller = new AbortController(); + this.musicSearchAbort = controller; - const themeOptions = document.querySelectorAll('.theme-option'); - themeOptions.forEach((opt) => { - if (opt.dataset.theme === theme) opt.classList.add('active'); - else opt.classList.remove('active'); - }); - } + this.showMusicLoading(); - async showNotification(message) { - const { showNotification } = await import('./downloads.js'); - showNotification(message); - } + try { + const results = await api.search(query, { limit: 4 }); + const tracks = results.tracks || { items: [] }; + const albums = results.albums || { items: [] }; + const artists = results.artists || { items: [] }; - handleQueue(args) { - const player = window.monochromePlayer; - const ui = window.monochromeUi; + if (controller.signal.aborted || !this.isOpen) return; - if (!player || !ui) { - console.error('Player or UI not available for queue command'); - return; - } + const musicGroups = {}; - if (!args || !args.trim()) { - this.renderResults( - [ - { name: '>queue wipe', description: 'Clear the queue and stop playback' }, - { name: '>queue like all', description: 'Like all tracks in the current queue' }, - { name: '>queue download', description: 'Download all tracks in the current queue' }, - ].map((c) => ({ - ...c, - type: 'command', - action: () => { - this.input.value = c.name; - this.handleInput(); + if (tracks?.items?.length) { + musicGroups['Tracks'] = tracks.items.map((track) => ({ + id: `track-${track.id}`, + group: 'Tracks', + icon: 'music', + image: api.getCoverUrl(track.album?.cover, 80), + label: track.title, + description: `${track.artist?.name || 'Unknown'} \u2022 ${track.album?.title || ''}`, + action: async () => { + Player.instance.setQueue([track], 0); + await Player.instance.playTrackFromQueue(); }, - })) - ); - return; - } - - const subCommand = args.trim().toLowerCase(); + })); + } - switch (subCommand) { - case 'wipe': - player.wipeQueue(); - this.showNotification('Queue wiped.'); - this.close(); - break; - case 'like all': - this.likeAllInQueue(player, ui); - break; - case 'download': - this.downloadQueue(player, ui); - break; - default: - this.showNotification(`Unknown queue command: ${subCommand}`); - break; - } - } + if (albums?.items?.length) { + musicGroups['Albums'] = albums.items.map((album) => ({ + id: `album-${album.id}`, + group: 'Albums', + icon: 'disc', + image: api.getCoverUrl(album.cover, 80), + label: album.title, + description: album.artist?.name || 'Unknown', + action: () => { + navigate(`/album/${album.id}`); + }, + })); + } - async likeAllInQueue(player, ui) { - const queue = player.getCurrentQueue(); - if (queue.length === 0) { - this.showNotification('Queue is empty.'); - return; - } + if (artists?.items?.length) { + musicGroups['Artists'] = artists.items.map((artist) => ({ + id: `artist-${artist.id}`, + group: 'Artists', + icon: 'mic', + image: api.getArtistPictureUrl(artist.picture, 80), + label: artist.name, + description: 'Artist', + action: () => { + navigate(`/artist/${artist.id}`); + }, + })); + } - const { handleTrackAction } = await import('./events.js'); - const scrobbler = window.monochromeScrobbler; + if (Object.keys(musicGroups).length > 0) { + this.appendMusicGroups(musicGroups); + } - let likedCount = 0; - this.showNotification('Liking all tracks in queue...'); - for (const track of queue) { - const isLiked = await db.isFavorite('track', track.id); - if (!isLiked) { - await handleTrackAction('toggle-like', track, player, ui.api, ui.lyricsManager, 'track', ui, scrobbler); - likedCount++; + this.removeMusicLoading(); + } catch (e) { + if (e.name !== 'AbortError') { + this.removeMusicLoading(); } } - this.showNotification(`Liked ${likedCount} new track(s) in the queue.`); - this.close(); } - async downloadQueue(player, ui) { - const queue = player.getCurrentQueue(); - if (queue.length === 0) { - this.showNotification('Queue is empty.'); - return; + cancelMusicSearch() { + if (this.musicSearchAbort) { + this.musicSearchAbort.abort(); + this.musicSearchAbort = null; } + } - const { downloadTracks } = await import('./downloads.js'); - const { downloadQualitySettings } = await import('./storage.js'); - const lyricsManager = ui.lyricsManager; + showMusicLoading() { + this.removeMusicLoading(); + const loading = document.createElement('div'); + loading.className = 'cmdk-loading'; + loading.setAttribute('data-music-loading', ''); + loading.innerHTML = '
    Searching music...'; + this.resultsContainer.appendChild(loading); + } - downloadTracks(queue, ui.api, downloadQualitySettings.getQuality(), lyricsManager); - this.close(); + removeMusicLoading() { + this.resultsContainer.querySelector('[data-music-loading]')?.remove(); } - handleNavigation(args) { - const validPages = ['home', 'library', 'recent', 'settings', 'unreleased', 'about', 'download']; + appendMusicGroups(musicGroups) { + this.removeMusicLoading(); + this.resultsContainer.querySelector('.cmdk-empty')?.remove(); + this.resultsContainer.querySelectorAll('[data-music-group]').forEach((el) => el.remove()); - if (!args || !args.trim()) { - this.renderResults( - validPages.map((p) => ({ - name: `>go ${p}`, - description: `Navigate to ${p}`, - action: () => { - this.close(); - import('./router.js').then((m) => m.navigate(p === 'home' ? '/' : `/${p}`)); - }, - type: 'command', - })) - ); - return; - } + let index = this.flatItems.length; - const page = args.trim().toLowerCase(); + for (const [heading, items] of Object.entries(musicGroups)) { + const groupEl = document.createElement('div'); + groupEl.className = 'cmdk-group'; + groupEl.setAttribute('data-music-group', ''); - if (validPages.includes(page)) { - this.close(); - import('./router.js').then((m) => m.navigate(page === 'home' ? '/' : `/${page}`)); - } else { - this.showNotification(`Unknown page: ${page}`); - } - } + const headingEl = document.createElement('div'); + headingEl.className = 'cmdk-group-heading'; + headingEl.textContent = heading; + groupEl.appendChild(headingEl); - handleSleepTimer(args) { - if (!args || !args.trim()) { - this.renderResults( - [15, 30, 45, 60, 120].map((m) => ({ - name: `>sleep ${m}`, - description: `Set sleep timer for ${m} minutes`, - action: () => { - this.setSleepTimer(m); - this.close(); - }, - type: 'command', - })) - ); - return; - } + for (const item of items) { + const itemEl = this.createItemElement(item, index); + groupEl.appendChild(itemEl); + this.flatItems.push(item); + index++; + } - const minutes = parseInt(args.trim()); - if (!isNaN(minutes) && minutes > 0) { - this.setSleepTimer(minutes); - this.close(); - } else { - this.showNotification('Invalid duration'); + this.resultsContainer.appendChild(groupEl); } } - setSleepTimer(minutes) { - if (window.monochromePlayer) { - window.monochromePlayer.setSleepTimer(minutes); - this.showNotification(`Sleep timer set for ${minutes} minutes`); + groupBy(items, key) { + const groups = {}; + for (const item of items) { + const group = item[key] || 'Other'; + if (!groups[group]) groups[group] = []; + groups[group].push(item); } + return groups; } - handleQuality(args) { - const qualityMap = { - low: 'LOW', - high: 'HIGH', - lossless: 'LOSSLESS', - hires: 'HI_RES_LOSSLESS', - 'hi-res': 'HI_RES_LOSSLESS', - master: 'HI_RES_LOSSLESS', - }; - - const displayQualities = [ - { id: 'low', name: 'Low', code: 'LOW' }, - { id: 'high', name: 'High', code: 'HIGH' }, - { id: 'lossless', name: 'Lossless', code: 'LOSSLESS' }, - { id: 'hi-res', name: 'Hi-Res', code: 'HI_RES_LOSSLESS' }, - ]; - - if (!args || !args.trim()) { - const results = displayQualities.map((q) => ({ - name: `>quality ${q.id}`, - description: `Set quality to ${q.name}`, - action: () => { - this.setQuality(q.code, true, true); - this.close(); - }, - type: 'command', - })); - - results.push({ - name: 'Usage: >quality [level] [-S] [-D]', - description: '-S for Streaming only, -D for Download only', - action: () => {}, - type: 'hint', - }); - this.renderResults(results); + renderGroups(groups) { + this.resultsContainer.innerHTML = ''; + this.flatItems = []; + let index = 0; + + const groupEntries = Object.entries(groups); + if (groupEntries.length === 0) { + const query = this.input.value.trim(); + if (query) { + const empty = document.createElement('div'); + empty.className = 'cmdk-empty'; + empty.textContent = 'No commands found'; + this.resultsContainer.appendChild(empty); + } return; } - const parts = args.trim().split(/\s+/); - const qualityKey = parts.find((p) => !p.startsWith('-'))?.toLowerCase(); - const flags = parts.filter((p) => p.startsWith('-')).map((f) => f.toLowerCase()); + for (const [heading, items] of groupEntries) { + const groupEl = document.createElement('div'); + groupEl.className = 'cmdk-group'; - if (!qualityKey || !qualityMap[qualityKey]) { - this.showNotification('Invalid quality setting'); - return; - } + const headingEl = document.createElement('div'); + headingEl.className = 'cmdk-group-heading'; + headingEl.textContent = heading; + groupEl.appendChild(headingEl); - const qualityCode = qualityMap[qualityKey]; - let setStreaming = true; - let setDownload = true; + for (const item of items) { + const itemEl = this.createItemElement(item, index); + groupEl.appendChild(itemEl); + this.flatItems.push(item); + index++; + } - if (flags.includes('-d') && !flags.includes('-s')) { - setStreaming = false; - } else if (flags.includes('-s') && !flags.includes('-d')) { - setDownload = false; + this.resultsContainer.appendChild(groupEl); } - this.setQuality(qualityCode, setStreaming, setDownload); - this.close(); + this.updateSelection(); } - async setQuality(quality, setStreaming, setDownload) { - const messages = []; - const qualityName = this.getQualityName(quality); - - if (setStreaming) { - if (window.monochromePlayer) { - window.monochromePlayer.setQuality(quality); - localStorage.setItem('playback-quality', quality); - messages.push('Streaming'); + createItemElement(item, index) { + const el = document.createElement('div'); + el.className = 'cmdk-item'; + el.id = `cmdk-item-${index}`; + el.setAttribute('role', 'option'); + el.setAttribute('data-index', index); + el.setAttribute('aria-selected', index === this.selectedIndex ? 'true' : 'false'); + if (index === this.selectedIndex) el.setAttribute('data-selected', 'true'); + + let iconHtml = ''; + if (item.image) { + iconHtml = `
    `; + } else if (item.icon && ICONS[item.icon]) { + iconHtml = `
    ${ICONS[item.icon](ICON_SIZE)}
    `; + } - const streamingSelect = document.getElementById('streaming-quality-setting'); - if (streamingSelect) { - streamingSelect.value = quality; - } - } + let shortcutHtml = ''; + if (item.shortcut) { + const keys = item.shortcut.split('+'); + shortcutHtml = `
    ${keys.map((k) => `${escapeHtml(k)}`).join('')}
    `; } - if (setDownload) { - const { downloadQualitySettings } = await import('./storage.js'); - downloadQualitySettings.setQuality(quality); - messages.push('Download'); + const descHtml = item.description + ? `${escapeHtml(item.description)}` + : ''; - const downloadSelect = document.getElementById('download-quality-setting'); - if (downloadSelect) { - downloadSelect.value = quality; - } - } + el.innerHTML = `${iconHtml}
    ${escapeHtml(item.label)}${descHtml}
    ${shortcutHtml}`; - if (messages.length > 0) { - this.showNotification(`${messages.join(' & ')} quality set to ${qualityName}`); - } - } + el.addEventListener('click', () => { + this.selectedIndex = index; + this.executeSelected(); + }); - getQualityName(code) { - const names = { - LOW: 'Low', - HIGH: 'High', - LOSSLESS: 'Lossless', - HI_RES_LOSSLESS: 'Hi-Res', - }; - return names[code] || code; - } - - async handleVisualizer(args) { - if (!args || !args.trim()) { - this.renderResults( - [ - { name: '>visualizer toggle', description: 'Toggle visualizer on/off', cmd: 'toggle' }, - { name: '>visualizer butterchurn', description: 'Set preset to Butterchurn', cmd: 'butterchurn' }, - { name: '>visualizer kawarp', description: 'Set preset to Kawarp', cmd: 'kawarp' }, - { name: '>visualizer lcd', description: 'Set preset to LCD', cmd: 'lcd' }, - { name: '>visualizer particles', description: 'Set preset to Particles', cmd: 'particles' }, - { - name: '>visualizer unknown-pleasures', - description: 'Set preset to Unknown Pleasures', - cmd: 'unknown-pleasures', - }, - ].map((c) => ({ - ...c, - action: () => { - if (c.cmd === 'toggle') { - this.toggleVisualizer(); - } else { - this.setVisualizerPreset(c.cmd); - } - this.close(); - }, - type: 'command', - })) - ); - return; - } + el.addEventListener('mouseenter', () => { + this.selectedIndex = index; + this.updateSelection(); + }); - const subCmd = args.trim().toLowerCase(); - if (subCmd === 'toggle') { - this.toggleVisualizer(); - this.close(); - } else { - const presets = ['butterchurn', 'kawarp', 'lcd', 'particles', 'unknown-pleasures']; - if (presets.includes(subCmd)) { - this.setVisualizerPreset(subCmd); - this.close(); + return el; + } + + updateSelection() { + const items = this.resultsContainer.querySelectorAll('.cmdk-item'); + items.forEach((item) => { + const idx = parseInt(item.getAttribute('data-index')); + if (idx === this.selectedIndex) { + item.setAttribute('data-selected', 'true'); + item.setAttribute('aria-selected', 'true'); + item.scrollIntoView({ block: 'nearest' }); } else { - this.showNotification('Unknown visualizer command'); + item.removeAttribute('data-selected'); + item.setAttribute('aria-selected', 'false'); } - } + }); + this.input.setAttribute('aria-activedescendant', `cmdk-item-${this.selectedIndex}`); } - async toggleVisualizer() { - const { visualizerSettings } = await import('./storage.js'); - const current = visualizerSettings.isEnabled(); - visualizerSettings.setEnabled(!current); - this.showNotification(`Visualizer ${!current ? 'enabled' : 'disabled'}`); + async executeSelected() { + const item = this.flatItems[this.selectedIndex]; + if (!item || !item.action) return; - const overlay = document.getElementById('fullscreen-cover-overlay'); - if (overlay && getComputedStyle(overlay).display !== 'none') { - window.monochromeUi?.closeFullscreenCover(); + if (item.keepOpen) { + try { + await item.action(); + } catch (e) { + console.error('Command palette action error:', e); + } + return; } - } - async setVisualizerPreset(preset) { - const { visualizerSettings } = await import('./storage.js'); - visualizerSettings.setPreset(preset); - if (window.monochromeUi?.visualizer) { - window.monochromeUi.visualizer.setPreset(preset); + try { + await item.action(); + } catch (e) { + console.error('Command palette action error:', e); } - this.showNotification(`Visualizer preset set to ${preset}`); + this.close(); } - async handleClearCache() { - const api = window.monochromeUi?.api; - if (api) { - await api.clearCache(); - this.showNotification('Cache cleared'); - this.close(); + renderSettingsResults(query) { + if (this.allSettings.length === 0) this.cacheAllSettings(); + + let results = this.allSettings; + if (query) { + results = this.settingsFuse.search(query).map((r) => r.item); } + + const items = results.map((setting) => ({ + id: `setting-${setting.id}`, + group: `Settings \u2022 ${setting.tab}`, + icon: 'settings', + label: setting.label, + description: setting.description, + action: () => this.navigateToSetting(setting), + })); + + const groups = this.groupBy(items, 'group'); + this.renderGroups(groups); } cacheAllSettings() { @@ -616,65 +1126,20 @@ class CommandPalette { : `setting-item-${Math.random().toString(36).substr(2, 9)}`; } - return { - id: item.id, - label, - description, - tab, - }; + return { id: item.id, label, description, tab }; }) .filter((s) => s.label); - } - - async handleSettingSearch(args, autoPick = false) { - const query = args.trim().toLowerCase(); - if (!query) { - this.renderResults( - this.allSettings.map((setting) => ({ - name: setting.label, - description: `[${setting.tab}] ${setting.description}`, - action: () => { - this.navigateToSetting(setting); - this.close(); - }, - type: 'setting', - })) - ); - return; - } - - const fuse = new Fuse(this.allSettings, { + this.settingsFuse = new Fuse(this.allSettings, { keys: ['label', 'description'], includeScore: true, threshold: 0.4, ignoreLocation: true, }); - - const results = fuse.search(query).map((r) => r.item); - - if (autoPick && results.length > 0) { - this.navigateToSetting(results[0]); - this.close(); - return; - } - - this.renderResults( - results.map((setting) => ({ - name: setting.label, - description: `[${setting.tab}] ${setting.description}`, - action: () => { - this.navigateToSetting(setting); - this.close(); - }, - type: 'setting', - })) - ); } async navigateToSetting(setting) { - const router = await import('./router.js'); - router.navigate('/settings'); + navigate('/settings'); await new Promise((resolve) => setTimeout(resolve, 100)); @@ -698,167 +1163,146 @@ class CommandPalette { } } - async performSearch(cmdName, query) { - if (!this.isOpen) return; + async setTheme(theme) { + const { themeManager } = await import('./storage.js'); + themeManager.setTheme(theme); + const themeOptions = document.querySelectorAll('.theme-option'); + themeOptions.forEach((opt) => { + if (opt.dataset.theme === theme) opt.classList.add('active'); + else opt.classList.remove('active'); + }); + this.notify(`Theme set to ${theme}`); + } - const api = window.monochromeUi?.api; - if (!api) return; + async toggleVisualizer() { + const { visualizerSettings } = await import('./storage.js'); + const current = visualizerSettings.isEnabled(); + visualizerSettings.setEnabled(!current); + this.notify(`Visualizer ${!current ? 'enabled' : 'disabled'}`); - let results = []; + const overlay = document.getElementById('fullscreen-cover-overlay'); + if (overlay && getComputedStyle(overlay).display !== 'none') { + UIRenderer.instance.closeFullscreenCover(); + } + } - try { - if (cmdName === 'play') { - const data = await api.searchTracks(query); - results = data.items.map((track) => ({ - name: track.title, - description: `${track.artist?.name || 'Unknown'} β€’ ${track.album?.title || 'Unknown'}`, - image: api.getCoverUrl(track.album?.cover, 80), - action: () => { - window.monochromePlayer.setQueue([track], 0); - window.monochromePlayer.playTrackFromQueue(); - this.close(); - }, - type: 'result', - })); - } else if (cmdName === 'shuffle') { - const [albums, artists, playlists, userPlaylists] = await Promise.all([ - api.searchAlbums(query), - api.searchArtists(query), - api.searchPlaylists(query), - db.getPlaylists(true), - ]); - - let matchedUserPlaylists = []; - if (Fuse) { - const fuse = new Fuse(userPlaylists, { keys: ['name'] }); - matchedUserPlaylists = fuse.search(query).map((r) => r.item); - } else { - matchedUserPlaylists = userPlaylists.filter((p) => - p.name.toLowerCase().includes(query.toLowerCase()) - ); - } + async setVisualizerPreset(preset) { + const { visualizerSettings } = await import('./storage.js'); + visualizerSettings.setPreset(preset); + if (UIRenderer.instance.visualizer) { + UIRenderer.instance.visualizer.setPreset(preset); + } + this.notify(`Visualizer preset: ${preset}`); + } - const formatResult = (item, type, subtitle, image) => ({ - name: item.title || item.name, - description: `${type} β€’ ${subtitle}`, - image: image, - action: () => this.playCollection(item, type, true), - type: 'result', - }); - - results = [ - ...matchedUserPlaylists.map((p) => - formatResult( - p, - 'User Playlist', - `${p.tracks?.length || 0} tracks`, - p.cover || (p.images && p.images[0]) - ) - ), - ...artists.items.map((a) => - formatResult(a, 'Artist', 'Artist', api.getArtistPictureUrl(a.picture, 80)) - ), - ...albums.items.map((a) => formatResult(a, 'Album', a.artist?.name, api.getCoverUrl(a.cover, 80))), - ...playlists.items.map((p) => - formatResult(p, 'Playlist', p.creator?.name || 'Tidal', api.getCoverUrl(p.image, 80)) - ), - ]; - } - } catch (e) { - console.error('Command palette search error:', e); + async setQuality(quality) { + const qualityNames = { + auto: 'Auto', + LOW: 'Low', + HIGH: 'High', + LOSSLESS: 'Lossless', + HI_RES_LOSSLESS: 'Hi-Res', + }; + + if (Player.instance) { + // Set fallback API quality (Auto maps back to Hi-Res) + const apiQuality = quality === 'auto' ? 'HI_RES_LOSSLESS' : quality; + Player.instance.setQuality(apiQuality); + localStorage.setItem('playback-quality', apiQuality); + + // Set adaptive streaming quality + localStorage.setItem('adaptive-playback-quality', quality); + if (Player.instance.forceQuality) Player.instance.forceQuality(quality); + + const streamingSelect = document.getElementById('streaming-quality-setting'); + if (streamingSelect) streamingSelect.value = quality; } - if (this.isOpen && results.length > 0) { - this.renderResults(results); + const { downloadQualitySettings } = await import('./storage.js'); + // Do not pass auto to download quality, resolve it to original fallback + const dlQuality = quality === 'auto' ? 'HI_RES_LOSSLESS' : quality; + downloadQualitySettings.setQuality(dlQuality); + const downloadSelect = document.getElementById('download-quality-setting'); + if (downloadSelect) downloadSelect.value = dlQuality; + + this.notify(`Quality set to ${qualityNames[quality] || quality}`); + } + + setSleepTimer(minutes) { + if (Player.instance) { + Player.instance.setSleepTimer(minutes); + this.notify(`Sleep timer: ${minutes} minutes`); } } - async handlePlay(args, autoPick) { - if (!args) return; + async likeAllInQueue() { + const player = Player.instance; + const ui = UIRenderer.instance; + if (!player || !ui) return; - if (autoPick) { - const api = window.monochromeUi?.api; - const results = await api.searchTracks(args); - if (results.items.length > 0) { - const track = results.items[0]; - window.monochromePlayer.setQueue([track], 0); - window.monochromePlayer.playTrackFromQueue(); - this.close(); + const queue = player.getCurrentQueue(); + if (queue.length === 0) { + this.notify('Queue is empty'); + return; + } + + const { handleTrackAction } = await import('./events.js'); + const scrobbler = window.monochromeScrobbler; + + let likedCount = 0; + this.notify('Liking all tracks in queue...'); + for (const track of queue) { + const isLiked = await db.isFavorite('track', track.id); + if (!isLiked) { + await handleTrackAction('toggle-like', track, player, ui.api, ui.lyricsManager, 'track', ui, scrobbler); + likedCount++; } } + this.notify(`Liked ${likedCount} new track(s)`); } - async handleShuffle(args, autoPick) { - if (!args) return; + async downloadQueue() { + const player = Player.instance; + const ui = UIRenderer.instance; + if (!player || !ui) return; - if (autoPick) { - this.performSearch('shuffle', args).then(() => { - if (this.results.length > 0 && this.results[0].action) { - this.results[0].action(); - } - }); + const queue = player.getCurrentQueue(); + if (queue.length === 0) { + this.notify('Queue is empty'); + return; } - } - async playCollection(item, type, shuffle) { - const player = window.monochromePlayer; - const api = window.monochromeUi.api; - let tracks = []; + const { downloadTracks } = await import('./downloads.js'); + const { downloadQualitySettings } = await import('./storage.js'); + downloadTracks(queue, ui.api, downloadQualitySettings.getQuality(), ui.lyricsManager); + } - try { - if (type === 'User Playlist') { - tracks = item.tracks; - } else if (type === 'Artist') { - const artist = await api.getArtist(item.id); - const allReleases = [...(artist.albums || []), ...(artist.eps || [])]; - const trackSet = new Set(); - const allTracks = []; - - const chunkSize = 8; - for (let i = 0; i < allReleases.length; i += chunkSize) { - const chunk = allReleases.slice(i, i + chunkSize); - await Promise.all( - chunk.map(async (album) => { - try { - const { tracks: albumTracks } = await api.getAlbum(album.id); - albumTracks.forEach((track) => { - if (!trackSet.has(track.id)) { - trackSet.add(track.id); - allTracks.push(track); - } - }); - } catch (err) { - console.warn(`Failed to fetch tracks for album ${album.title}:`, err); - } - }) - ); - } + async createPlaylist() { + const name = `New Playlist ${new Date().toLocaleDateString()}`; + await db.createPlaylist(name); + navigate('/library'); + this.notify('Playlist created'); + } - if (allTracks.length > 0) { - tracks = allTracks; - } else { - tracks = artist.tracks || []; - } - } else if (type === 'Album') { - tracks = (await api.getAlbum(item.id)).tracks; - } else if (type === 'Playlist') { - tracks = (await api.getPlaylist(item.uuid)).tracks; - } + async createFolder() { + const name = `New Folder ${new Date().toLocaleDateString()}`; + await db.createFolder(name); + navigate('/library'); + this.notify('Folder created'); + } - if (tracks && tracks.length > 0) { - if (shuffle) { - tracks = [...tracks].sort(() => Math.random() - 0.5); - player.shuffleActive = true; - document.getElementById('shuffle-btn')?.classList.add('active'); - } - player.setQueue(tracks, 0); - player.playTrackFromQueue(); - this.close(); - } - } catch (e) { - console.error('Failed to play collection:', e); + async clearCache() { + const api = UIRenderer.instance.api; + if (api) { + await api.clearCache(); + this.notify('Cache cleared'); } } + + async notify(message) { + const { showNotification } = await import('./downloads.js'); + showNotification(message); + } } new CommandPalette(); diff --git a/js/container-classes.ts b/js/container-classes.ts new file mode 100644 index 000000000..e33029b12 --- /dev/null +++ b/js/container-classes.ts @@ -0,0 +1,113 @@ +export class ReplayGain { + trackReplayGain: number; + albumReplayGain: number; + trackPeakAmplitude: number; + albumPeakAmplitude: number; +} + +export class Track { + accessType: string; + adSupportedStreamReady: boolean; + album: TrackAlbum; + allowStreaming: true; + artist: Artist; + artists: Artist[]; + audioModes: string[]; + audioQuality: string; + bpm: number; + copyright: string; + djReady: boolean; + duration: number; + explicit: boolean; + id: number; + isrc: string; + key: string; + keyScale?: string; + mediaMetadata: MediaMetadata; + mixes: Record; + payToStream: boolean; + peak: number; + popularity: number; + premiumStreamingOnly: boolean; + replayGain: number; + spotlighted: boolean; + stemReady: boolean; + streamStartDate: string; + title: string; + trackNumber: number; + type?: string; + upload: boolean; + url: string; + version?: string; + volumeNumber: number; +} + +export class PlaybackInfo extends ReplayGain { + trackId: number; + assetPresentation: string; + audioMode: string; + audioQuality: string; + manifestMimeType: string; + manifestHash: string; + manifest: string; + bitDepth: number; + sampleRate: number; +} + +export class MediaMetadata { + tags: string[]; +} + +export class Artist { + handle: any; + id: number; + name: string; + picture: string; + type: string; +} + +export class EnrichedTrack extends Track { + declare album: TrackAlbum | EnrichedAlbum; + declare replayGain: any | ReplayGain; +} + +export class TrackAlbum { + cover: string; + id: number; + title: string; + vibrantColor: string; + videoCover?: string; +} + +export class Album extends TrackAlbum { + adSupportedStreamReady: boolean; + allowStreaming: boolean; + artist: Artist; + artists: Artist[]; + audioModes: string[]; + audioQuality: string; + copyright: string; + djReady: boolean; + duration: number; + explicit: boolean; + mediaMetadata: MediaMetadata; + numberOfTracks: number; + numberOfVideos: number; + numberOfVolumes: number; + popularity: number; + premiumStreamingOnly: boolean; + releaseDate?: string; + stemReady: boolean; + streamReady: boolean; + streamStartDate: string; + type: string; + upc: string; + upload: boolean; + url: string; + version?: string; +} + +export class EnrichedAlbum extends Album { + totalDiscs?: number; + numberOfTracksOnDisc?: number; +} diff --git a/js/dash-downloader.js b/js/dash-downloader.ts similarity index 64% rename from js/dash-downloader.js rename to js/dash-downloader.ts index a67fa8b5b..21391ce8c 100644 --- a/js/dash-downloader.js +++ b/js/dash-downloader.ts @@ -1,8 +1,54 @@ +import { AbortError } from './errorTypes'; +import { SegmentedDownloadProgress } from './progressEvents'; + +export interface DashDownloadOptions { + onProgress?: MonochromeProgressListener; + signal?: AbortSignal; + calculateDashBytes?: boolean; +} + +interface DashSegment { + number: number; + time: number; +} + +interface DashManifest { + baseUrl: string; + initialization: string | null; + media: string | null; + segments: DashSegment[]; + repId: string | null; + mimeType: string | null; +} + export class DashDownloader { constructor() {} - async downloadDashStream(manifestBlobUrl, options = {}) { - const { onProgress, signal } = options; + async getTotalSize(urls: string[], signal?: AbortSignal): Promise { + try { + let totalSize = 0; + + await Promise.all( + urls.map(async (url) => { + const result = await fetch(url, { method: 'HEAD', signal }); + + if (result.ok) { + const contentLength = result.headers.get('Content-Length'); + if (contentLength) totalSize += parseInt(contentLength, 10); + } else { + throw new Error(`Failed to fetch segment HEAD: ${result.status}`); + } + }) + ); + + return totalSize; + } catch { + return undefined; + } + } + + async downloadDashStream(manifestBlobUrl: string, options: DashDownloadOptions = {}): Promise { + const { onProgress, signal, calculateDashBytes = true } = options; // 1. Fetch and Parse Manifest const response = await fetch(manifestBlobUrl); @@ -18,24 +64,30 @@ export class DashDownloader { const mimeType = manifest.mimeType || 'audio/mp4'; // 3. Download Segments - const chunks = []; + const chunks: ArrayBuffer[] = []; let downloadedBytes = 0; - // Estimate total size? Hard to know exactly without Content-Length of each. - // We can just track progress by segment count. + const totalSegments = urls.length; + const totalSize = calculateDashBytes ? await this.getTotalSize(urls, signal) : undefined; for (let i = 0; i < urls.length; i++) { - if (signal?.aborted) throw new Error('AbortError'); + if (signal?.aborted) throw new AbortError(); + + onProgress?.(new SegmentedDownloadProgress(downloadedBytes, totalSize ?? undefined, i, totalSegments)); const url = urls[i]; const segmentResponse = await fetch(url, { signal }); if (!segmentResponse.ok) { - // Retry once? console.warn(`Failed to fetch segment ${i}, retrying...`); await new Promise((r) => setTimeout(r, 1000)); + const retryResponse = await fetch(url, { signal }); - if (!retryResponse.ok) throw new Error(`Failed to fetch segment ${i}: ${retryResponse.status}`); + + if (!retryResponse.ok) { + throw new Error(`Failed to fetch segment ${i}: ${retryResponse.status}`); + } + const chunk = await retryResponse.arrayBuffer(); chunks.push(chunk); downloadedBytes += chunk.byteLength; @@ -45,22 +97,14 @@ export class DashDownloader { downloadedBytes += chunk.byteLength; } - if (onProgress) { - onProgress({ - stage: 'downloading', - receivedBytes: downloadedBytes, // accurate byte count - totalBytes: undefined, // Unknown total - currentSegment: i + 1, - totalSegments: totalSegments, - }); - } + onProgress?.(new SegmentedDownloadProgress(downloadedBytes, totalSize ?? undefined, i + 1, totalSegments)); } // 4. Concatenate return new Blob(chunks, { type: mimeType }); } - parseManifest(manifestText) { + parseManifest(manifestText: string): DashManifest { const parser = new DOMParser(); const xml = parser.parseFromString(manifestText, 'text/xml'); @@ -70,25 +114,22 @@ export class DashDownloader { const period = mpd.querySelector('Period'); if (!period) throw new Error('Invalid DASH manifest: No Period tag'); - // Prefer highest bandwidth audio adaptation set const adaptationSets = Array.from(period.querySelectorAll('AdaptationSet')); adaptationSets.sort((a, b) => { - const getMaxBandwidth = (set) => { + const getMaxBandwidth = (set: Element) => { const reps = Array.from(set.querySelectorAll('Representation')); return reps.length ? Math.max(...reps.map((r) => parseInt(r.getAttribute('bandwidth') || '0', 10))) : 0; }; + return getMaxBandwidth(b) - getMaxBandwidth(a); }); - let audioSet = adaptationSets.find((as) => as.getAttribute('mimeType')?.startsWith('audio')); + let audioSet = adaptationSets.find((as) => as.getAttribute('mimeType')?.startsWith('audio')) ?? null; - // Fallback: look for any adaptation set if mimeType is missing (rare) if (!audioSet && adaptationSets.length > 0) audioSet = adaptationSets[0]; if (!audioSet) throw new Error('No AdaptationSet found'); - // Find Representation - // Get all representations and sort by bandwidth descending const representations = Array.from(audioSet.querySelectorAll('Representation')).sort((a, b) => { const bwA = parseInt(a.getAttribute('bandwidth') || '0'); const bwB = parseInt(b.getAttribute('bandwidth') || '0'); @@ -96,55 +137,47 @@ export class DashDownloader { }); if (representations.length === 0) throw new Error('No Representation found'); + const rep = representations[0]; const repId = rep.getAttribute('id'); - // Find SegmentTemplate - // Can be in Representation or AdaptationSet const segmentTemplate = rep.querySelector('SegmentTemplate') || audioSet.querySelector('SegmentTemplate'); + if (!segmentTemplate) throw new Error('No SegmentTemplate found'); const initialization = segmentTemplate.getAttribute('initialization'); const media = segmentTemplate.getAttribute('media'); const startNumber = parseInt(segmentTemplate.getAttribute('startNumber') || '1', 10); - // BaseURL - // Can be at MPD, Period, AdaptationSet, or Representation level. - // We strictly need to find the "deepest" one or combine them? - // Usually simpler manifests have it at one level. - // Let's resolve closest BaseURL. const baseUrlTag = rep.querySelector('BaseURL') || audioSet.querySelector('BaseURL') || period.querySelector('BaseURL') || mpd.querySelector('BaseURL'); - const baseUrl = baseUrlTag ? baseUrlTag.textContent.trim() : ''; - // SegmentTimeline + const baseUrl = baseUrlTag?.textContent?.trim() || ''; + const segmentTimeline = segmentTemplate.querySelector('SegmentTimeline'); - const segments = []; + const segments: DashSegment[] = []; if (segmentTimeline) { const sElements = segmentTimeline.querySelectorAll('S'); + let currentTime = 0; let currentNumber = startNumber; sElements.forEach((s) => { - // t is optional, defaults to previous end const tAttr = s.getAttribute('t'); if (tAttr) currentTime = parseInt(tAttr, 10); - const d = parseInt(s.getAttribute('d'), 10); + const d = parseInt(s.getAttribute('d') || '0', 10); const r = parseInt(s.getAttribute('r') || '0', 10); - // Initial segment segments.push({ number: currentNumber, time: currentTime }); + currentTime += d; currentNumber++; - // Repeats - // r is the number of REPEATS (so total occurrences = 1 + r) - // If r is negative, it refers to open-ended? (Usually not in static manifests) for (let i = 0; i < r; i++) { segments.push({ number: currentNumber, time: currentTime }); currentTime += d; @@ -163,43 +196,40 @@ export class DashDownloader { }; } - generateSegmentUrls(manifest) { + generateSegmentUrls(manifest: DashManifest): string[] { const { baseUrl, initialization, media, segments, repId } = manifest; - const urls = []; - // Helper to resolve template strings - const resolveTemplate = (template, number, time) => { + const urls: string[] = []; + + const resolveTemplate = (template: string, number: number, time: number): string => { return template - .replace(/\$RepresentationID\$/g, repId) - .replace(/\$Number(?:%0([0-9]+)d)?\$/g, (match, width) => { + .replace(/\$RepresentationID\$/g, repId ?? '') + .replace(/\$Number(?:%0([0-9]+)d)?\$/g, (_, width) => { if (width) { return number.toString().padStart(parseInt(width), '0'); } - return number; + return number.toString(); }) - .replace(/\$Time(?:%0([0-9]+)d)?\$/g, (match, width) => { + .replace(/\$Time(?:%0([0-9]+)d)?\$/g, (_, width) => { if (width) { return time.toString().padStart(parseInt(width), '0'); } - return time; + return time.toString(); }); }; - // Helper to join paths handling slashes - const joinPath = (base, part) => { + const joinPath = (base: string, part: string): string => { if (!base) return part; - if (part.startsWith('http')) return part; // Absolute path + if (part.startsWith('http')) return part; return base.endsWith('/') ? base + part : base + '/' + part; }; - // 1. Initialization Segment if (initialization) { - const initPath = resolveTemplate(initialization, 0, 0); // Init often doesn't use Number/Time but just in case + const initPath = resolveTemplate(initialization, 0, 0); urls.push(joinPath(baseUrl, initPath)); } - // 2. Media Segments - if (segments && segments.length > 0) { + if (media && segments.length > 0) { segments.forEach((seg) => { const path = resolveTemplate(media, seg.number, seg.time); urls.push(joinPath(baseUrl, path)); diff --git a/js/db.js b/js/db.js index 76477aa22..bcc6835eb 100644 --- a/js/db.js +++ b/js/db.js @@ -1,7 +1,7 @@ export class MusicDatabase { constructor() { this.dbName = 'MonochromeDB'; - this.version = 9; + this.version = 11; this.db = null; } @@ -24,6 +24,11 @@ export class MusicDatabase { request.onupgradeneeded = (event) => { const db = event.target.result; + // v10 introduced track_ratings (bad PR) β€” remove it + if (db.objectStoreNames.contains('track_ratings')) { + db.deleteObjectStore('track_ratings'); + } + // Favorites stores if (!db.objectStoreNames.contains('favorites_tracks')) { const store = db.createObjectStore('favorites_tracks', { keyPath: 'id' }); @@ -107,7 +112,6 @@ export class MusicDatabase { const store = transaction.objectStore(storeName); const index = store.index('timestamp'); - // Check the most recent entry const cursorReq = index.openCursor(null, 'prev'); cursorReq.onsuccess = (e) => { @@ -115,11 +119,9 @@ export class MusicDatabase { if (cursor) { const lastTrack = cursor.value; if (lastTrack.id === track.id) { - // If same track, delete the old entry so we just update the timestamp store.delete(cursor.primaryKey); } } - // Add the new entry store.put(entry); }; @@ -172,11 +174,13 @@ export class MusicDatabase { if (exists) { await this.performTransaction(storeName, 'readwrite', (store) => store.delete(key)); + window.dispatchEvent(new CustomEvent('favorites-changed')); return false; // Removed } else { const minified = this._minifyItem(type, item); const entry = { ...minified, addedAt: Date.now() }; await this.performTransaction(storeName, 'readwrite', (store) => store.put(entry)); + window.dispatchEvent(new CustomEvent('favorites-changed')); return true; // Added } } @@ -258,6 +262,10 @@ export class MusicDatabase { mixes: item.mixes || null, isTracker: item.isTracker || (item.id && String(item.id).startsWith('tracker-')), trackerInfo: item.trackerInfo || null, + isPodcast: item.isPodcast || (item.id && String(item.id).startsWith('podcast_')) || null, + enclosureUrl: item.enclosureUrl || null, + enclosureType: item.enclosureType || null, + enclosureLength: item.enclosureLength || null, audioUrl: item.remoteUrl || item.audioUrl || null, remoteUrl: item.remoteUrl || null, audioQuality: item.audioQuality || null, @@ -583,6 +591,7 @@ export class MusicDatabase { // TRIGGER SYNC this._dispatchPlaylistSync('create', playlist); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); return playlist; } @@ -600,6 +609,7 @@ export class MusicDatabase { await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); this._dispatchPlaylistSync('update', playlist); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); return playlist; } @@ -623,6 +633,7 @@ export class MusicDatabase { this._updatePlaylistMetadata(playlist); await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); this._dispatchPlaylistSync('update', playlist); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); } return playlist; @@ -643,6 +654,7 @@ export class MusicDatabase { await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); this._dispatchPlaylistSync('update', playlist); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); return playlist; } @@ -652,6 +664,7 @@ export class MusicDatabase { // TRIGGER SYNC (but for deleting) this._dispatchPlaylistSync('delete', { id: playlistId }); + window.dispatchEvent(new CustomEvent('playlist-tracks-changed')); } async getPlaylist(playlistId) { diff --git a/js/doTimed.ts b/js/doTimed.ts index 812ddb96f..1e5d123da 100644 --- a/js/doTimed.ts +++ b/js/doTimed.ts @@ -4,23 +4,44 @@ import { v7 } from 'uuid'; export const InvisibleCodec = baseCodecFrom(InvisibleDictionary); export function doTimed(message: string, callback: () => T): T { - const hiddenId = InvisibleCodec.encode(v7()); - console.time(message + hiddenId); - try { - const output = callback(); - return output; - } finally { - console.timeEnd(message + hiddenId); + if (import.meta.env.DEV) { + const hiddenId = InvisibleCodec.encode(v7()); + console.time(message + hiddenId); + try { + const output = callback(); + return output; + } finally { + console.timeEnd(message + hiddenId); + } + } else { + return callback(); } } -export async function doTimedAsync(message: string, callback: () => T): Promise> { - const hiddenId = InvisibleCodec.encode(v7()); - console.time(message + hiddenId); - try { - const output = await callback(); - return output; - } finally { - console.timeEnd(message + hiddenId); +export function doTimedAsync ? Promise : T>( + message: string, + callback: () => R, + throwError: boolean = false +): R { + if (import.meta.env.DEV) { + return new Promise(async (resolve, reject) => { + const hiddenId = InvisibleCodec.encode(v7()); + console.time(message + hiddenId); + try { + const output = await callback(); + resolve(output); + } catch (err) { + console.error(`Error in timed operation "${message}":`, err); + if (throwError) { + reject(err); + } else { + resolve(undefined as R); + } + } finally { + console.timeEnd(message + hiddenId); + } + }) as R; + } else { + return callback() as R; } } diff --git a/js/download-utils.ts b/js/download-utils.ts new file mode 100644 index 000000000..51ed90c69 --- /dev/null +++ b/js/download-utils.ts @@ -0,0 +1,142 @@ +import { losslessContainerSettings } from './storage'; +import { getExtensionFromBlob } from './utils'; +import { rebuildFlacWithoutMetadata } from './metadata.flac.js'; +import { + type ProgressEvent, + isCustomFormat, + getCustomFormat, + transcodeWithCustomFormat, + getContainerFormat, + transcodeWithContainerFormat, +} from './ffmpegFormats'; +import { ffmpegNewContainer } from './ffmpeg'; + +/** + * Triggers a browser file download for the given blob. + */ +export function triggerDownload(blob: Blob, filename: string): void { + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} + +/** + * Apply post-processing to an audio Blob according to the requested quality. + * + * This function: + * - Detects the source container/extension via getExtensionFromBlob. + * - Determines whether the source is lossless: + * - FLAC is always lossless. + * - M4A is treated as lossless only when trackAudioQuality is "LOSSLESS" or "HI_RES_LOSSLESS". + * - If a custom lossy format is requested (isCustomFormat(quality)): + * - If the source is already lossy, returns the original Blob to avoid quality degradation. + * - Otherwise, obtains the custom format via getCustomFormat and transcodes using + * transcodeWithCustomFormat(...). Progress events are reported via onProgress. + * - If encoding fails, onProgress is notified with an error stage and the original error is rethrown. + * - If a lossless output is requested (quality ends with "LOSSLESS"): + * - Retrieves the configured lossless container and its format handler. + * - If the source is not lossless, logs a warning and returns the original Blob. + * - Otherwise: + * - If containerFmt.needsTranscode(blob) is true, transcodes via transcodeWithContainerFormat(...). + * - Else if the source is FLAC, calls rebuildFlacWithoutMetadata to strip/rebuild metadata safely. + * - Else remuxes into the desired container via ffmpegNewContainer (maps m4a -> mp4 where appropriate). + * - Any non-abort errors during lossless container conversion are caught and logged (conversion is best-effort). + * + * Progress and cancellation: + * - onProgress, if provided, will be called with progress/update/error events from the underlying encoding/transcode helpers. + * - An AbortSignal may be provided to cancel long-running transcode operations; abort-related errors (AbortError) + * are propagated. + * + * @param blob - The source audio Blob to process. + * @param quality - Requested output quality identifier (may indicate custom lossy format or lossless output). + * @param onProgress - Optional callback invoked with progress/update events (or error notifications). + * @param signal - Optional AbortSignal used to cancel asynchronous transcode operations. + * @param trackAudioQuality - Optional track audio quality information from the API (e.g. "LOSSLESS", "HI_RES_LOSSLESS") + * used to determine whether an m4a source should be treated as lossless. + * @returns A Promise that resolves to the resulting audio Blob (may be the original blob if no processing was needed + * or if processing was skipped due to source/quality constraints). + * @throws Throws underlying encoding/transcoding errors (including AbortError when aborted). Encoding errors during + * custom-format transcode are rethrown after reporting via onProgress. Non-abort errors during lossless + * container conversion are logged and do not necessarily propagate. + */ +export async function applyAudioPostProcessing( + blob: Blob, + quality: string, + onProgress: ((progress: ProgressEvent) => void) | null = null, + signal: AbortSignal | null = null, + trackAudioQuality: string | null = null +): Promise { + const extension = await getExtensionFromBlob(blob); + + // Determine whether the downloaded source is lossless. + // FLAC is always lossless. m4a is lossless only when the track's + // audio quality from the API is LOSSLESS or HI_RES_LOSSLESS; otherwise + // it is AAC (lossy). + const sourceIsLossless = + extension === 'flac' || + (extension === 'm4a' && (trackAudioQuality === 'LOSSLESS' || trackAudioQuality === 'HI_RES_LOSSLESS')); + + // Transcode to custom lossy format if requested + if (isCustomFormat(quality)) { + // If the source is already lossy, transcoding would degrade quality + // further (lossy β†’ lossy). Return the blob as-is instead. + if (!sourceIsLossless) { + return blob; + } + const format = getCustomFormat(quality); + if (format) { + try { + blob = await transcodeWithCustomFormat(blob, format, onProgress, signal); + } catch (encodingError) { + if (onProgress) { + onProgress({ + stage: 'error', + message: `Encoding failed: ${(encodingError as Error).message}`, + }); + } + throw encodingError; + } + } + } + + if (quality.endsWith('LOSSLESS')) { + try { + const containerName = losslessContainerSettings.getContainer(); + const containerFmt = getContainerFormat(containerName); + + if (!sourceIsLossless) { + console.warn( + `Requested lossless output but source is not lossless (quality: ${quality}, trackAudioQuality: ${trackAudioQuality}, extension: ${extension}).` + ); + return blob; + } + + if (await containerFmt?.needsTranscode(blob)) { + blob = await transcodeWithContainerFormat(blob, containerFmt, onProgress, signal); + } else if (extension === 'flac') { + blob = await rebuildFlacWithoutMetadata(blob); + } else { + blob = await ffmpegNewContainer( + blob, + extension == 'm4a' ? 'mp4' : extension, + blob.type, + onProgress, + signal + ); + } + } catch (error) { + if ((error as Error)?.name === 'AbortError' || signal?.aborted) { + throw error; + } + + console.error('Lossless container conversion failed:', error); + } + } + + return blob; +} diff --git a/js/downloadProgressUtils.js b/js/downloadProgressUtils.js new file mode 100644 index 000000000..6360a5346 --- /dev/null +++ b/js/downloadProgressUtils.js @@ -0,0 +1,14 @@ +/** + * Helpers for download progress. Extracted for testability (fixes #278). + * Resolve total byte count from GET and optional HEAD Content-Length. + */ + +/** + * @param {string | null} contentLengthFromGet - Content-Length header from GET response + * @param {number | null} headContentLength - Content-Length from prior HEAD request + * @returns {number} + */ +export function resolveDownloadTotalBytes(contentLengthFromGet, headContentLength) { + const fromGet = contentLengthFromGet ? parseInt(contentLengthFromGet, 10) : null; + return fromGet ?? headContentLength ?? 0; +} diff --git a/js/errorTypes.ts b/js/errorTypes.ts new file mode 100644 index 000000000..8ae9cdb5c --- /dev/null +++ b/js/errorTypes.ts @@ -0,0 +1,6 @@ +export class AbortError extends Error { + constructor(cause: string = 'The task was aborted.') { + super(cause); + this.name = 'AbortError'; + } +} diff --git a/js/events.js b/js/events.js index 29dbc81c3..e90f7cfdb 100644 --- a/js/events.js +++ b/js/events.js @@ -1,19 +1,20 @@ //js/events.js import { - SVG_PLAY, - SVG_PAUSE, - SVG_VOLUME, - SVG_MUTE, REPEAT_MODE, trackDataStore, formatTime, - SVG_BIN, getTrackArtists, positionMenu, getShareUrl, escapeHtml, } from './utils.js'; -import { lastFMStorage, libreFmSettings, waveformSettings } from './storage.js'; +import { + lastFMStorage, + libreFmSettings, + listenBrainzSettings, + waveformSettings, + keyboardShortcuts, +} from './storage.js'; import { showNotification, downloadTrackWithMetadata, downloadAlbumAsZip, downloadPlaylistAsZip } from './downloads.js'; import { downloadQualitySettings } from './storage.js'; import { updateTabTitle, navigate } from './router.js'; @@ -21,6 +22,7 @@ import { db } from './db.js'; import { syncManager } from './accounts/pocketbase.js'; import { waveformGenerator } from './waveform.js'; import { audioContextManager } from './audio-context.js'; +import { hapticLongPress, hapticMedium, hapticLight } from './haptics.js'; import { trackPlayTrack, trackPauseTrack, @@ -52,9 +54,229 @@ import { trackStartMix, trackEvent, } from './analytics.js'; +import { SVG_BIN, SVG_MUTE, SVG_PAUSE, SVG_PLAY, SVG_VOLUME, SVG_CHECKBOX, SVG_CHECKBOX_CHECKED } from './icons.js'; let currentTrackIdForWaveform = null; +const trackSelection = { + selectedIds: new Set(), + lastClickedId: null, + isSelecting: false, +}; + +let longPressTimer = null; +let isLongPress = false; +let longPressTrackItem = null; +const LONG_PRESS_DURATION = 500; + +function handleTrackTouchStart(e) { + if (!('ontouchstart' in window)) return; + const trackItem = e.target.closest('.track-item'); + if (!trackItem || trackItem.classList.contains('unavailable') || trackItem.classList.contains('blocked')) return; + + isLongPress = false; + longPressTrackItem = trackItem; + + longPressTimer = setTimeout(() => { + isLongPress = true; + toggleTrackSelection(trackItem, true, false); + hapticLongPress(); + }, LONG_PRESS_DURATION); +} + +function handleTrackTouchMove(e) { + if (longPressTimer) { + clearTimeout(longPressTimer); + longPressTimer = null; + } +} + +function handleTrackTouchEnd(e) { + if (longPressTimer) { + clearTimeout(longPressTimer); + longPressTimer = null; + } + setTimeout(() => { + isLongPress = false; + longPressTrackItem = null; + }, 100); +} + +function isMultiSelectToggle(e) { + const shortcut = keyboardShortcuts.getShortcutForAction('multiSelectToggle'); + if (!shortcut) return e.ctrlKey || e.metaKey; + const key = e.key?.toLowerCase(); + const shortcutKey = shortcut.key?.toLowerCase(); + + if (['control', 'shift', 'alt', 'meta'].includes(shortcutKey)) { + if (shortcut.ctrl && !(e.ctrlKey || e.metaKey)) return false; + if (shortcut.shift && !e.shiftKey) return false; + if (shortcut.alt && !e.altKey) return false; + return true; + } + + return ( + (shortcut.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey) && + (shortcut.shift ? e.shiftKey : !e.shiftKey) && + (shortcut.alt ? e.altKey : !e.altKey) && + key === shortcutKey + ); +} + +function isMultiSelectRange(e) { + const shortcut = keyboardShortcuts.getShortcutForAction('multiSelectRange'); + if (!shortcut) return e.shiftKey; + const key = e.key?.toLowerCase(); + const shortcutKey = shortcut.key?.toLowerCase(); + + if (['control', 'shift', 'alt', 'meta'].includes(shortcutKey)) { + if (shortcut.ctrl && !(e.ctrlKey || e.metaKey)) return false; + if (shortcut.shift && !e.shiftKey) return false; + if (shortcut.alt && !e.altKey) return false; + return true; + } + + return ( + (shortcut.ctrl ? e.ctrlKey || e.metaKey : !e.ctrlKey && !e.metaKey) && + (shortcut.shift ? e.shiftKey : !e.shiftKey) && + (shortcut.alt ? e.altKey : !e.altKey) && + key === shortcutKey + ); +} + +function getSelectedTracks() { + return Array.from(trackSelection.selectedIds); +} + +function updateCheckbox(checkbox, checked) { + if (checkbox) { + checkbox.innerHTML = checked ? SVG_CHECKBOX_CHECKED(18) : SVG_CHECKBOX(18); + checkbox.classList.toggle('checked', checked); + } +} + +function toggleTrackSelection(trackItem, ctrlHeld, shiftHeld) { + const trackId = trackItem.dataset.trackId; + const isSelected = trackSelection.selectedIds.has(trackId); + + if (ctrlHeld) { + if (isSelected) { + trackSelection.selectedIds.delete(trackId); + trackItem.classList.remove('selected'); + updateCheckbox(trackItem.querySelector('.track-checkbox'), false); + } else { + trackSelection.selectedIds.add(trackId); + trackItem.classList.add('selected'); + updateCheckbox(trackItem.querySelector('.track-checkbox'), true); + } + trackSelection.lastClickedId = trackId; + } else if (shiftHeld && trackSelection.lastClickedId && trackSelection.lastClickedId !== trackId) { + const parentList = trackItem.closest('.track-list') || trackItem.closest('#main-content'); + const allTrackElements = Array.from(parentList.querySelectorAll('.track-item')); + const lastIndex = allTrackElements.findIndex((el) => el.dataset.trackId === trackSelection.lastClickedId); + const currentIndex = allTrackElements.findIndex((el) => el.dataset.trackId === trackId); + + if (lastIndex !== -1 && currentIndex !== -1) { + const start = Math.min(lastIndex, currentIndex); + const end = Math.max(lastIndex, currentIndex); + for (let i = start; i <= end; i++) { + const el = allTrackElements[i]; + trackSelection.selectedIds.add(el.dataset.trackId); + el.classList.add('selected'); + updateCheckbox(el.querySelector('.track-checkbox'), true); + } + } + } else { + if (!isSelected) { + trackSelection.selectedIds.add(trackId); + trackItem.classList.add('selected'); + updateCheckbox(trackItem.querySelector('.track-checkbox'), true); + } else { + trackSelection.selectedIds.delete(trackId); + trackItem.classList.remove('selected'); + updateCheckbox(trackItem.querySelector('.track-checkbox'), false); + } + trackSelection.lastClickedId = trackId; + } + + trackSelection.isSelecting = trackSelection.selectedIds.size > 0; + document.body.classList.toggle('multi-select-mode', trackSelection.isSelecting); +} + +function showMultiSelectPlaylistModal(tracks) { + const modal = document.createElement('div'); + modal.className = 'modal-overlay'; + modal.style.cssText = + 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center; z-index: 10000;'; + modal.innerHTML = ` + + `; + + const closeModal = () => { + modal.remove(); + document.body.style.overflow = ''; + }; + + modal.querySelector('.modal-close').addEventListener('click', closeModal); + modal.addEventListener('click', (e) => { + if (e.target === modal) closeModal(); + }); + + document.body.appendChild(modal); + document.body.style.overflow = 'hidden'; + + db.getPlaylists(true).then((playlists) => { + const listEl = modal.querySelector('.playlist-list'); + if (playlists.length === 0) { + listEl.innerHTML = '
    No playlists yet
    '; + } else { + listEl.innerHTML = playlists + .map( + (p) => ` +
    + ${escapeHtml(p.name)} + ${p.tracks?.length || 0} tracks +
    + ` + ) + .join(''); + } + + listEl.querySelectorAll('.playlist-item').forEach((item) => { + item.addEventListener('click', async () => { + const playlistId = item.dataset.playlistId; + for (const track of tracks) { + await db.addTrackToPlaylist(playlistId, track); + } + syncManager.syncUserPlaylist(await db.getPlaylist(playlistId), 'update'); + showNotification(`Added ${tracks.length} tracks to playlist`); + closeModal(); + }); + }); + }); + + modal.querySelector('.create-new-playlist').addEventListener('click', () => { + const name = prompt('Playlist name:'); + if (name) { + db.createPlaylist(name, tracks).then((playlist) => { + showNotification(`Created playlist "${name}" with ${tracks.length} tracks`); + closeModal(); + }); + } + }); +} + export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { const playPauseBtn = document.querySelector('.now-playing-bar .play-pause-btn'); const nextBtn = document.getElementById('next-btn'); @@ -72,12 +294,110 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { const activeEl = player.activeElement; const { muted } = activeEl; const volume = player.userVolume; - volumeBtn.innerHTML = muted || volume === 0 ? SVG_MUTE : SVG_VOLUME; + volumeBtn.innerHTML = muted || volume === 0 ? SVG_MUTE(20) : SVG_VOLUME(20); const effectiveVolume = muted ? 0 : volume * 100; volumeFill.style.setProperty('--volume-level', `${effectiveVolume}%`); volumeFill.style.width = `${effectiveVolume}%`; }; + function clearSelection() { + trackSelection.selectedIds.clear(); + trackSelection.lastClickedId = null; + trackSelection.isSelecting = false; + document.body.classList.remove('multi-select-mode'); + document.querySelectorAll('.track-item.selected').forEach((el) => { + el.classList.remove('selected'); + }); + document.querySelectorAll('.track-checkbox').forEach((checkbox) => { + checkbox.innerHTML = SVG_CHECKBOX(18); + checkbox.classList.remove('checked'); + }); + updateSelectionBar(); + } + + function updateSelectionBar() { + let bar = document.getElementById('selection-bar'); + if (!bar) { + bar = document.createElement('div'); + bar.id = 'selection-bar'; + bar.className = 'selection-bar'; + bar.innerHTML = ` + 0 selected +
    + + + + + +
    + + `; + document.body.appendChild(bar); + + bar.querySelectorAll('button').forEach((btn) => { + btn.addEventListener('click', () => handleSelectionAction(btn.dataset.action)); + }); + } + + const count = trackSelection.selectedIds.size; + bar.querySelector('.selection-count').textContent = `${count} selected`; + bar.classList.toggle('visible', count > 0); + } + + function handleSelectionAction(action) { + const selectedIds = getSelectedTracks(); + if (selectedIds.length === 0) return; + + const mainContent = document.getElementById('main-content'); + const selectedTracks = []; + mainContent.querySelectorAll('.track-item').forEach((item) => { + if (trackSelection.selectedIds.has(item.dataset.trackId)) { + const track = trackDataStore.get(item); + if (track) selectedTracks.push(track); + } + }); + + switch (action) { + case 'play-selected': + if (selectedTracks.length > 0) { + player.setQueue(selectedTracks, 0); + document.getElementById('shuffle-btn').classList.remove('active'); + player.playTrackFromQueue(); + } + break; + case 'add-to-queue-selected': + if (selectedTracks.length > 0) { + player.addToQueue(selectedTracks); + if (window.renderQueueFunction) window.renderQueueFunction(); + showNotification(`Added ${selectedTracks.length} tracks to queue`); + } + break; + case 'add-to-playlist-selected': + if (selectedTracks.length > 0) { + showMultiSelectPlaylistModal(selectedTracks); + } + break; + case 'download-selected': + if (selectedTracks.length > 0) { + selectedTracks.forEach((track) => { + downloadTrackWithMetadata(track, downloadQualitySettings.getQuality(), api, lyricsManager); + }); + showNotification(`Downloading ${selectedTracks.length} tracks`); + } + break; + case 'like-selected': + selectedTracks.forEach(async (track) => { + const added = await db.toggleFavorite('track', track); + syncManager.syncLibraryItem('track', track, added); + }); + showNotification(`Liked ${selectedTracks.length} tracks`); + break; + case 'clear-selection': + clearSelection(); + break; + } + } + if (homeStartRadioBtn) { homeStartRadioBtn.addEventListener('click', async () => { await player.enableRadio(); @@ -117,7 +437,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { updateWaveform(); } - playPauseBtn.innerHTML = SVG_PAUSE; + playPauseBtn.innerHTML = SVG_PAUSE(20); player.updateMediaSessionPlaybackState(); player.updateMediaSessionPositionState(); updateTabTitle(player); @@ -134,7 +454,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { if (player.currentTrack) { trackPauseTrack(player.currentTrack); } - playPauseBtn.innerHTML = SVG_PLAY; + playPauseBtn.innerHTML = SVG_PLAY(20); player.updateMediaSessionPlaybackState(); player.updateMediaSessionPositionState(); }); @@ -200,7 +520,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { } console.error(`Media playback error (${element.id}):`, errorMsg, e); - playPauseBtn.innerHTML = SVG_PLAY; + playPauseBtn.innerHTML = SVG_PLAY(20); const canFallback = player.quality === 'HI_RES_LOSSLESS' && @@ -233,17 +553,23 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { setupMediaListeners(player.video); } - playPauseBtn.addEventListener('click', () => player.handlePlayPause()); + playPauseBtn.addEventListener('click', () => { + hapticMedium(); + player.handlePlayPause(); + }); nextBtn.addEventListener('click', () => { + hapticMedium(); trackSkipTrack(player.currentTrack, 'next'); player.playNext(); }); prevBtn.addEventListener('click', () => { + hapticMedium(); trackSkipTrack(player.currentTrack, 'previous'); player.playPrev(); }); shuffleBtn.addEventListener('click', () => { + hapticLight(); player.toggleShuffle(); trackToggleShuffle(player.shuffleActive); shuffleBtn.classList.toggle('active', player.shuffleActive); @@ -251,6 +577,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) { }); repeatBtn.addEventListener('click', () => { + hapticLight(); const mode = player.toggleRepeat(); trackToggleRepeat(mode === REPEAT_MODE.OFF ? 'off' : mode === REPEAT_MODE.ALL ? 'all' : 'one'); repeatBtn.classList.toggle('active', mode !== REPEAT_MODE.OFF); @@ -712,7 +1039,7 @@ export async function showAddToPlaylistModal(track) { ${p.name} ${ alreadyContains - ? `` + ? `` : '' } @@ -1054,6 +1381,9 @@ export async function handleTrackAction( if (libreFmSettings.isEnabled() && libreFmSettings.shouldLoveOnLike()) { scrobbler.loveTrack(item); } + if (listenBrainzSettings.isEnabled() && listenBrainzSettings.shouldLoveOnLike()) { + scrobbler.loveTrack(item); + } } // Update all instances of this item's like button on the page @@ -1094,10 +1424,10 @@ export async function handleTrackAction( }); // Handle Library Page Update - if (window.location.hash === '#library') { + if (window.location.pathname.split('/').filter(Boolean)[0] === 'library') { const itemSelector = type === 'track' - ? `.track-item[data-track-id="${id}"]` + ? `.track-item[data-track-id="${id}"], .card[data-track-id="${id}"]` : type === 'video' ? `.video-card[data-video-id="${id}"]` : `.card[data-${type}-id="${id}"], .card[data-playlist-id="${id}"]`; @@ -1125,17 +1455,31 @@ export async function handleTrackAction( const placeholder = tracksContainer.querySelector('.placeholder-text'); if (placeholder) placeholder.remove(); - const index = tracksContainer.children.length; - const trackHTML = ui.createTrackItemHTML(item, index, true, false); - + const layout = localStorage.getItem('libraryLikedTracksView') || 'list'; const tempDiv = document.createElement('div'); - tempDiv.innerHTML = trackHTML; + if (layout === 'grid') { + tracksContainer.classList.remove('track-list'); + tracksContainer.classList.add('card-grid'); + tempDiv.innerHTML = ui.createTrackCardHTML(item); + } else { + tracksContainer.classList.remove('card-grid'); + tracksContainer.classList.add('track-list'); + const index = tracksContainer.children.length; + tempDiv.innerHTML = ui.createTrackItemHTML(item, index, true, false, false, true); + } const newEl = tempDiv.firstElementChild; if (newEl) { tracksContainer.appendChild(newEl); trackDataStore.set(newEl, item); ui.updateLikeState(newEl, 'track', item.id); + const likedToolbar = document.getElementById('library-liked-tracks-toolbar'); + if (likedToolbar) likedToolbar.style.display = 'flex'; + const shuffleBtn = document.getElementById('shuffle-liked-tracks-btn'); + const downloadBtn = document.getElementById('download-liked-tracks-btn'); + if (shuffleBtn) shuffleBtn.style.display = 'flex'; + if (downloadBtn) downloadBtn.style.display = 'flex'; + ui.setupLibraryLikedTracksSearch(tracksContainer); } } } else if (type === 'video') { @@ -1207,7 +1551,7 @@ export async function handleTrackAction( ${p.name} ${ alreadyContains - ? `` + ? `` : '' } @@ -1311,7 +1655,8 @@ export async function handleTrackAction( // Use stored href from card if available, otherwise construct URL const contextMenu = document.getElementById('context-menu'); const storedHref = contextMenu?._contextHref; - const url = getShareUrl(storedHref ? storedHref : `/track/${item.id || item.uuid}`); + const typeForUrl = type === 'user-playlist' ? 'userplaylist' : type; + const url = getShareUrl(storedHref ? storedHref : `/${typeForUrl}/${item.id || item.uuid}`); trackCopyLink(type, item.id || item.uuid); navigator.clipboard.writeText(url).then(() => { @@ -1323,7 +1668,7 @@ export async function handleTrackAction( const storedHref = contextMenu?._contextHref; const url = storedHref ? `${window.location.origin}${storedHref}` - : `${window.location.origin}/track/${item.id || item.uuid}`; + : `${window.location.origin}/${type}/${item.id || item.uuid}`; trackOpenInNewTab(type, item.id || item.uuid); window.open(url, '_blank'); @@ -1351,7 +1696,7 @@ export async function handleTrackAction(

    Unreleased Track

    - +
    ${item.artists ? `

    Artist: ${escapeHtml(Array.isArray(item.artists) ? item.artists.map((a) => a.name || a).join(', ') : item.artists)}

    ` : ''} ${item.trackerInfo.artist ? `

    Tracked Artist: ${escapeHtml(item.trackerInfo.artist)}

    ` : ''} @@ -1366,7 +1711,7 @@ export async function handleTrackAction( ${item.trackerInfo.leakedDate ? `

    Leak Date: ${escapeHtml(new Date(item.trackerInfo.leakedDate).toLocaleDateString())}

    ` : ''} ${item.trackerInfo.recordingDate ? `

    Recording Date: ${escapeHtml(new Date(item.trackerInfo.recordingDate).toLocaleDateString())}

    ` : ''}
    - + ${ item.trackerInfo.description ? ` @@ -1377,7 +1722,7 @@ export async function handleTrackAction( ` : '' } - + ${ item.trackerInfo.notes ? ` @@ -1388,7 +1733,7 @@ export async function handleTrackAction( ` : '' } - + ${ item.trackerInfo.sourceUrl ? ` @@ -1401,7 +1746,7 @@ export async function handleTrackAction( ` : '' } - + ${item.id ? `

    Track ID: ${escapeHtml(item.id)}

    ` : ''} @@ -1430,7 +1775,7 @@ export async function handleTrackAction( ${item.explicit ? `

    Explicit: Yes

    ` : ''}

    Quality: ${escapeHtml(quality)} ${bitrate ? `(${escapeHtml(bitrate)})` : ''}

    - + ${ item.credits && item.credits.length > 0 ? ` @@ -1443,7 +1788,7 @@ export async function handleTrackAction( ` : '' } - + ${ item.composers && item.composers.length > 0 ? ` @@ -1451,7 +1796,7 @@ export async function handleTrackAction( ` : '' } - + ${ item.lyrics?.text ? ` @@ -1461,7 +1806,7 @@ export async function handleTrackAction( ` : '' } - + ${item.id ? `

    Track ID: ${escapeHtml(item.id)}

    ` : ''} ${item.album?.id ? `

    Album ID: ${escapeHtml(item.album.id)}

    ` : ''} @@ -1664,6 +2009,10 @@ async function updateContextMenuLikeState(contextMenu, contextTrack) { export function initializeTrackInteractions(player, api, mainContent, contextMenu, lyricsManager, ui, scrobbler) { let contextTrack = null; + mainContent.addEventListener('touchstart', handleTrackTouchStart, { passive: true }); + mainContent.addEventListener('touchmove', handleTrackTouchMove, { passive: true }); + mainContent.addEventListener('touchend', handleTrackTouchEnd, { passive: true }); + mainContent.addEventListener('click', async (e) => { const actionBtn = e.target.closest('.track-action-btn, .like-btn, .play-btn'); if (actionBtn && actionBtn.dataset.action) { @@ -1773,6 +2122,14 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen } contextMenu._contextTrack = contextTrack; contextMenu._contextType = menuBtn.dataset.type || trackItem.dataset.type || 'track'; + if (trackSelection.isSelecting && trackSelection.selectedIds.size > 0) { + const selectedTracks = []; + document.querySelectorAll('.track-item.selected').forEach((item) => { + const track = trackDataStore.get(item); + if (track) selectedTracks.push(track); + }); + contextMenu._selectedTracks = selectedTracks; + } await updateContextMenuLikeState(contextMenu, contextTrack); const rect = menuBtn.getBoundingClientRect(); positionMenu(contextMenu, rect.left, rect.bottom + 5, rect); @@ -1781,19 +2138,49 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen return; } + const checkbox = e.target.closest('.track-checkbox'); + if (checkbox) { + e.stopPropagation(); + const trackItem = checkbox.closest('.track-item'); + if (trackItem) { + toggleTrackSelection(trackItem, isMultiSelectToggle(e), isMultiSelectRange(e)); + } + return; + } + const trackItem = e.target.closest('.track-item'); if (trackItem && (trackItem.classList.contains('unavailable') || trackItem.classList.contains('blocked'))) { return; } + if (isLongPress && longPressTrackItem === trackItem) { + return; + } if ( trackItem && !trackItem.dataset.queueIndex && !e.target.closest('.remove-from-playlist-btn') && - !e.target.closest('.artist-link') + !e.target.closest('.artist-link') && + !e.target.closest('.like-btn') ) { const clickedTrackId = trackItem.dataset.trackId; const isSearch = window.location.pathname.startsWith('/search/'); + if (isMultiSelectToggle(e)) { + e.preventDefault(); + toggleTrackSelection(trackItem, true, isMultiSelectRange(e)); + return; + } + + if (isMultiSelectRange(e) && trackSelection.isSelecting) { + e.preventDefault(); + toggleTrackSelection(trackItem, false, true); + return; + } + + if (trackSelection.isSelecting) { + return; + } + if (isSearch) { const clickedTrack = trackDataStore.get(trackItem); if (clickedTrack) { @@ -1820,6 +2207,17 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen const startIndex = trackList.findIndex((t) => t.id == clickedTrackId); player.setQueue(trackList, startIndex); + + // Set artist popular tracks context if on artist page + console.log('[Events] Setting context:', { + page: ui.currentPage, + artistId: ui.currentArtistId, + trackCount: trackList.length, + }); + if (ui.currentPage === 'artist' && ui.currentArtistId) { + player.setArtistPopularTracksContext(ui.currentArtistId, trackList, trackList.length, true); + } + document.getElementById('shuffle-btn').classList.remove('active'); player.playTrackFromQueue(); } @@ -1851,6 +2249,32 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen return; } + const libraryTracksContainer = card.closest('#library-tracks-container'); + if (libraryTracksContainer && card.dataset.trackId) { + if ( + e.target.closest('.like-btn') || + e.target.closest('.card-play-btn') || + e.target.closest('.card-menu-btn') + ) { + return; + } + e.preventDefault(); + const clickedTrackId = card.dataset.trackId; + const clickedTrack = trackDataStore.get(card); + if (!clickedTrack) return; + const allTrackElements = Array.from(libraryTracksContainer.querySelectorAll('.card[data-track-id]')); + const trackList = allTrackElements.map((el) => trackDataStore.get(el)).filter(Boolean); + if (trackList.length === 0) return; + const startIndex = trackList.findIndex((t) => t.id == clickedTrackId); + player.setQueue(trackList, startIndex); + if (ui.currentPage === 'artist' && ui.currentArtistId) { + player.setArtistPopularTracksContext(ui.currentArtistId, trackList, trackList.length, true); + } + document.getElementById('shuffle-btn').classList.remove('active'); + player.playTrackFromQueue(); + return; + } + const href = card.dataset.href; if (href) { // Allow native links inside card to work if any exist @@ -1885,6 +2309,15 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen contextMenu._originalHTML = null; } + // Store selected tracks for multi-select actions + let selectedTracks = []; + if (trackSelection.isSelecting && trackSelection.selectedIds.size > 0) { + document.querySelectorAll('.track-item.selected').forEach((item) => { + const track = trackDataStore.get(item); + if (track) selectedTracks.push(track); + }); + } + // Hide actions for unavailable tracks const unavailableActions = ['play-next', 'add-to-queue', 'download', 'track-mix']; contextMenu.querySelectorAll('[data-action]').forEach((btn) => { @@ -1895,6 +2328,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen contextMenu._contextTrack = contextTrack; contextMenu._contextType = contextTrack.type || 'track'; + contextMenu._selectedTracks = selectedTracks; await updateContextMenuLikeState(contextMenu, contextTrack); positionMenu(contextMenu, e.clientX, e.clientY); } @@ -1932,7 +2366,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen } }); - document.addEventListener('click', () => { + document.addEventListener('click', (e) => { if (contextMenu.style.display === 'block') { if (contextMenu._originalHTML) { contextMenu.innerHTML = contextMenu._originalHTML; @@ -1941,6 +2375,21 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen contextMenu._contextType = null; contextMenu._originalHTML = null; } + + if ( + trackSelection.isSelecting && + !e.target.closest('.track-item') && + !e.target.closest('.selection-bar') && + !e.target.closest('.track-checkbox') + ) { + clearSelection(); + } + }); + + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && trackSelection.isSelecting) { + clearSelection(); + } }); contextMenu.addEventListener('click', async (e) => { @@ -1982,9 +2431,55 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen } if (action && track) { - // Track context menu action - trackContextMenuAction(action, type, track); - await handleTrackAction(action, track, player, api, lyricsManager, type, ui, scrobbler, target.dataset); + const selectedTracks = contextMenu._selectedTracks || []; + const isMultiSelect = selectedTracks.length > 1; + + if (isMultiSelect) { + // Handle multi-select actions + switch (action) { + case 'play-next': + selectedTracks.forEach((t) => { + trackPlayNext(t); + player.addNextToQueue(t); + }); + if (window.renderQueueFunction) window.renderQueueFunction(); + showNotification(`Playing next: ${selectedTracks.length} tracks`); + clearSelection(); + break; + case 'add-to-queue': + player.addToQueue(selectedTracks); + if (window.renderQueueFunction) window.renderQueueFunction(); + showNotification(`Added ${selectedTracks.length} tracks to queue`); + clearSelection(); + break; + case 'toggle-like': + selectedTracks.forEach(async (t) => { + const added = await db.toggleFavorite('track', t); + syncManager.syncLibraryItem('track', t, added); + }); + showNotification(`Liked ${selectedTracks.length} tracks`); + clearSelection(); + break; + case 'add-to-playlist': + showMultiSelectPlaylistModal(selectedTracks); + clearSelection(); + break; + case 'download': + selectedTracks.forEach((t) => { + downloadTrackWithMetadata(t, downloadQualitySettings.getQuality(), api, lyricsManager); + }); + showNotification(`Downloading ${selectedTracks.length} tracks`); + clearSelection(); + break; + default: + clearSelection(); + break; + } + } else { + // Track context menu action + trackContextMenuAction(action, type, track); + await handleTrackAction(action, track, player, api, lyricsManager, type, ui, scrobbler, target.dataset); + } } // Reset menu state before closing @@ -1994,6 +2489,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen } contextMenu.style.display = 'none'; contextMenu._contextType = null; + contextMenu._selectedTracks = null; }); // Now playing bar interactions diff --git a/js/ffmpeg.js b/js/ffmpeg.js index 0ea51d892..fff10f0fb 100644 --- a/js/ffmpeg.js +++ b/js/ffmpeg.js @@ -1,8 +1,11 @@ -import { fetchBlobURL } from './utils'; import FfmpegWorker from './ffmpeg.worker.js?worker'; -const ffmpegBase = 'https://unpkg.com/@ffmpeg/core/dist/esm'; -const coreJs = `${ffmpegBase}/ffmpeg-core.js`; -const coreWasm = `${ffmpegBase}/ffmpeg-core.wasm`; +import coreJs from '!/@ffmpeg/core/dist/esm/ffmpeg-core.js?blob-url'; +import coreWasm from '!/@ffmpeg/core/dist/esm/ffmpeg-core.wasm?blob-url'; +import { FfmpegProgress } from './ffmpeg.types'; + +/** + * @typedef {import('./ffmpeg.types.ts').FfmpegProgress} FfmpegProgress + */ class FfmpegError extends Error { constructor(message) { @@ -17,8 +20,8 @@ export function loadFfmpeg() { loadFfmpeg.promise || (loadFfmpeg.promise = (async () => { const data = { - coreURL: await fetchBlobURL(coreJs), - wasmURL: await fetchBlobURL(coreWasm), + coreURL: await coreJs(), + wasmURL: await coreWasm(), }; return data; @@ -26,15 +29,27 @@ export function loadFfmpeg() { ); } +/** + * + * @param {Blob} audioBlob + * @param {string[]} args + * @param {string} outputName + * @param {string} outputMime + * @param {(progress: FfmpegProgress) => void} onProgress + * @param {AbortSignal|null} signal + * @param {Array<{name: string, data: ArrayBuffer | Uint8Array}>} extraFiles + * @returns {Promise} Encoded audio blob + */ async function ffmpegWorker( audioBlob, - args = {}, + args = [], outputName = 'output', outputMime = 'application/octet-stream', onProgress = null, - signal = null + signal = null, + extraFiles = [] ) { - const audioData = await audioBlob.arrayBuffer(); + const audioData = audioBlob ? await audioBlob.arrayBuffer() : null; const assets = loadFfmpeg(); return new Promise((resolve, reject) => { @@ -65,8 +80,10 @@ async function ffmpegWorker( if (signal) signal.removeEventListener('abort', abortHandler); worker.terminate(); reject(new FfmpegError(message)); - } else if (type === 'progress' && onProgress) { - onProgress({ stage, message, progress }); + } else if (type === 'progress' && message) { + onProgress?.(new FfmpegProgress(stage, progress || 0, message)); + } else if (type === 'progress' && stage != 'loading' && progress !== null) { + onProgress?.(new FfmpegProgress(stage, progress || 0, message)); } else if (type === 'log') { console.log('[FFmpeg]', message); } @@ -79,34 +96,60 @@ async function ffmpegWorker( }; (async () => { + const transferables = []; + if (audioData) transferables.push(audioData); + for (const f of extraFiles) { + if (f.data instanceof ArrayBuffer) { + transferables.push(f.data); + } else if (f.data.buffer instanceof ArrayBuffer) { + transferables.push(f.data.buffer); + } + } + worker.postMessage( { audioData, - ...args, + extraFiles, + args, output: { name: outputName, mime: outputMime, }, loadOptions: await assets, }, - [audioData] + transferables ); })(); }); } +/** + * Encodes audio using FFmpeg via Web Worker + * @async + * @param {Blob} audioBlob - The audio blob to encode + * @param {string[]} [args=[]] - FFmpeg command-line arguments + * @param {string} [outputName='output'] - Name of the output file + * @param {string} [outputMime='application/octet-stream'] - MIME type of the output + * @param {(progress: FfmpegProgress) => void} [onProgress=null] - Optional callback for progress updates + * @param {AbortSignal|null} [signal=null] - Optional abort signal to cancel encoding + * @param {Array} [extraFiles=[]] - Additional files to provide to FFmpeg + * @returns {Promise} Encoded audio blob + * @throws {FfmpegError} If Web Workers are not available + * @throws {Error} If FFmpeg encoding fails + */ export async function ffmpeg( audioBlob, - args = {}, + args = [], outputName = 'output', outputMime = 'application/octet-stream', onProgress = null, - signal = null + signal = null, + extraFiles = [] ) { try { // Use Web Worker for non-blocking FFmpeg encoding if (typeof Worker !== 'undefined') { - return await ffmpegWorker(audioBlob, args, outputName, outputMime, onProgress, signal); + return await ffmpegWorker(audioBlob, args, outputName, outputMime, onProgress, signal, extraFiles); } throw new FfmpegError('Web Workers are required for FFMPEG'); @@ -116,4 +159,24 @@ export async function ffmpeg( } } +/** + * Creates a new FFmpeg container with copied codec and stripped metadata. + * @param {Blob} audioBlob - The audio blob to process + * @param {string} outputExtension - The extension for the output file + * @param {string} outputMime - The MIME type for the output blob + * @param {Function} onProgress - Callback function to track conversion progress + * @param {AbortSignal} signal - AbortSignal for cancelling the operation + * @returns {Promise} A promise that resolves to the processed data blob + */ +export async function ffmpegNewContainer(audioBlob, outputExtension, outputMime, onProgress, signal) { + return await ffmpeg( + audioBlob, + ['-map_metadata', '-1', '-c', 'copy', '-strict', '-2'], + `output.${outputExtension}`, + outputMime, + onProgress, + signal + ); +} + export { FfmpegError }; diff --git a/js/ffmpeg.types.ts b/js/ffmpeg.types.ts new file mode 100644 index 000000000..43ffa3836 --- /dev/null +++ b/js/ffmpeg.types.ts @@ -0,0 +1,7 @@ +export class FfmpegProgress implements MonochromeProgress { + constructor( + public readonly stage: 'loading' | 'encoding' | 'finalizing', + public readonly progress: number, + public readonly message?: string + ) {} +} diff --git a/js/ffmpeg.worker.js b/js/ffmpeg.worker.js index bcf866b20..ecee08c14 100644 --- a/js/ffmpeg.worker.js +++ b/js/ffmpeg.worker.js @@ -101,6 +101,7 @@ async function loadFFmpeg(loadOptions = {}) { self.onmessage = async (e) => { const { audioData, + extraFiles = [], args = [], output = { name: 'output', @@ -112,41 +113,51 @@ self.onmessage = async (e) => { } = e.data; try { - console.log(loadOptions); await loadFFmpeg(loadOptions); self.postMessage({ type: 'progress', stage: 'encoding', message: encodeStartMessage, progress: 0.0 }); try { - // Write input file to FFmpeg virtual filesystem - await ffmpeg.writeFile('input', new Uint8Array(audioData)); + if (audioData) { + await ffmpeg.writeFile('input', new Uint8Array(audioData)); + } + + for (const file of extraFiles) { + await ffmpeg.writeFile(file.name, new Uint8Array(file.data)); + } const ffmpegArgs = ['-i', 'input', ...args, output.name]; + self.postMessage({ type: 'log', message: `FFmpeg command: ffmpeg ${ffmpegArgs.join(' ')}` }); - // Log the exact FFmpeg command being run for debugging. - self.postMessage({ type: 'log', message: `Running with args: ${ffmpegArgs.join(' ')}` }); + const exitCode = await ffmpeg.exec(ffmpegArgs); - // Run FFMPEG with the provided arguments. - await ffmpeg.exec(ffmpegArgs); + if (exitCode !== 0) { + throw new Error(`FFmpeg failed with exit code ${exitCode}.`); + } self.postMessage({ type: 'progress', stage: 'finalizing', message: encodeEndMessage, progress: 100.0 }); - // Read output file - use Uint8Array directly to avoid extra bytes from ArrayBuffer const data = await ffmpeg.readFile(output.name); const outputBlob = new Blob([data], { type: output.mime }); self.postMessage({ type: 'complete', blob: outputBlob }); } finally { - // Always cleanup virtual filesystem files try { - await ffmpeg.deleteFile('input'); + if (audioData) await ffmpeg.deleteFile('input'); } catch { - // File may not exist if writeFile failed + self.postMessage({ type: 'log', message: 'Failed to delete input file from FFmpeg FS.' }); + } + for (const file of extraFiles) { + try { + await ffmpeg.deleteFile(file.name); + } catch { + self.postMessage({ type: 'log', message: `Failed to delete ${file.name} from FFmpeg FS.` }); + } } try { await ffmpeg.deleteFile(output.name); } catch { - // File may not exist if exec failed + self.postMessage({ type: 'log', message: `Failed to delete ${output.name} from FFmpeg FS.` }); } } } catch (error) { diff --git a/js/ffmpegFormats.ts b/js/ffmpegFormats.ts new file mode 100644 index 000000000..562cbd039 --- /dev/null +++ b/js/ffmpegFormats.ts @@ -0,0 +1,228 @@ +import { ffmpeg } from './ffmpeg'; +import { getExtensionFromBlob } from './utils'; + +export interface ProgressEvent { + stage?: string; + message?: string; + progress?: number; + receivedBytes?: number; + totalBytes?: number; +} + +export interface CustomFormat { + /** Human-readable label shown in the UI */ + displayName: string; + /** Arguments passed to ffmpeg (excluding input/output file args) */ + ffmpegArgs: string[]; + /** Output filename used when calling ffmpeg */ + outputFilename: string; + /** MIME type of the encoded output */ + outputMime: string; + /** File extension of the encoded output */ + extension: string; + /** Category label used for grouping in the UI (e.g. 'MP3', 'OGG', 'AAC') */ + category: string; +} + +/** + * A container format definition for lossless re-muxing/re-encoding. + * Extends CustomFormat with a callback that decides whether ffmpeg needs to run + * at all (e.g. FLAC can skip if the source is already FLAC). + */ +export interface ContainerFormat extends Omit { + /** + * Returns true when the source blob must be passed through ffmpeg to produce + * the desired container. Return false to skip the ffmpeg step (the caller + * may still apply a lightweight metadata-strip pass instead). + */ + needsTranscode: (blob: Blob) => Promise; +} + +export const customFormats: Record = { + FFMPEG_MP3_320: { + displayName: 'MP3 320kbps', + ffmpegArgs: ['-map_metadata', '-1', '-c:a', 'libmp3lame', '-b:a', '320k', '-ar', '44100'], + outputFilename: 'output.mp3', + outputMime: 'audio/mpeg', + extension: 'mp3', + category: 'MP3', + }, + FFMPEG_MP3_256: { + displayName: 'MP3 256kbps', + ffmpegArgs: ['-map_metadata', '-1', '-c:a', 'libmp3lame', '-b:a', '256k', '-ar', '44100'], + outputFilename: 'output.mp3', + outputMime: 'audio/mpeg', + extension: 'mp3', + category: 'MP3', + }, + FFMPEG_MP3_128: { + displayName: 'MP3 128kbps', + ffmpegArgs: ['-map_metadata', '-1', '-c:a', 'libmp3lame', '-b:a', '128k', '-ar', '44100'], + outputFilename: 'output.mp3', + outputMime: 'audio/mpeg', + extension: 'mp3', + category: 'MP3', + }, + FFMPEG_OGG_320: { + displayName: 'OGG 320kbps', + ffmpegArgs: [ + '-map_metadata', + '-1', + '-c:a', + 'libvorbis', + '-b:a', + '320k', + '-minrate', + '320k', + '-maxrate', + '320k', + ], + outputFilename: 'output.ogg', + outputMime: 'audio/ogg', + extension: 'ogg', + category: 'OGG', + }, + FFMPEG_OGG_256: { + displayName: 'OGG 256kbps', + ffmpegArgs: [ + '-map_metadata', + '-1', + '-c:a', + 'libvorbis', + '-b:a', + '256k', + '-minrate', + '256k', + '-maxrate', + '256k', + ], + outputFilename: 'output.ogg', + outputMime: 'audio/ogg', + extension: 'ogg', + category: 'OGG', + }, + FFMPEG_OGG_128: { + displayName: 'OGG 128kbps', + ffmpegArgs: [ + '-map_metadata', + '-1', + '-c:a', + 'libvorbis', + '-b:a', + '128k', + '-minrate', + '128k', + '-maxrate', + '128k', + ], + outputFilename: 'output.ogg', + outputMime: 'audio/ogg', + extension: 'ogg', + category: 'OGG', + }, + FFMPEG_AAC_256: { + displayName: 'AAC 256kbps', + ffmpegArgs: ['-map_metadata', '-1', '-c:a', 'aac', '-b:a', '256k'], + outputFilename: 'output.m4a', + outputMime: 'audio/mp4', + extension: 'm4a', + category: 'AAC', + }, +}; + +// Add wav to custom formats when vite is in dev mode +if (import.meta.env.DEV) { + customFormats.FFMPEG_WAV = { + displayName: 'WAV (16-bit PCM)', + ffmpegArgs: ['-map_metadata', '-1'], + outputFilename: 'output.wav', + outputMime: 'audio/wav', + extension: 'wav', + category: 'WAV', + }; +} + +/** + * Container format definitions for lossless re-muxing. Each entry describes + * the ffmpeg arguments needed to produce that container and provides a + * `needsTranscode` predicate so callers can skip the ffmpeg step when the + * source is already in the correct container. + */ +export const containerFormats: Record = { + flac: { + displayName: 'FLAC', + ffmpegArgs: ['-vn', '-map_metadata', '-1', '-map', '0:a', '-c:a', 'flac'], + outputFilename: 'output.flac', + outputMime: 'audio/flac', + extension: 'flac', + // Only transcode when the source is NOT already a FLAC file. + needsTranscode: async (blob) => (await getExtensionFromBlob(blob)) !== 'flac', + }, + alac: { + displayName: 'Apple Lossless', + ffmpegArgs: ['-c:a', 'alac'], + outputFilename: 'output.m4a', + outputMime: 'audio/mp4', + extension: 'm4a', + needsTranscode: async () => true, + }, +}; + +/** Returns true if the quality string identifies a known custom ffmpeg-transcoded format */ +export function isCustomFormat(quality: string): boolean { + return getCustomFormat(quality) !== undefined; +} + +/** Looks up a custom format by its internal name, or returns undefined */ +export function getCustomFormat(internalName: string): CustomFormat | undefined { + return customFormats[internalName]; +} + +/** Looks up a container format by its internal name, or returns undefined */ +export function getContainerFormat(internalName: string): ContainerFormat | undefined { + return containerFormats[internalName]; +} + +/** + * Transcodes an audio blob using the specified custom format via ffmpeg. + * Throws if ffmpeg fails during transcoding. + */ +export async function transcodeWithCustomFormat( + audioBlob: Blob, + format: CustomFormat, + onProgress: ((progress: ProgressEvent) => void) | null = null, + signal: AbortSignal | null = null, + extraFiles: any[] = [] +): Promise { + return ffmpeg( + audioBlob, + format.ffmpegArgs, + format.outputFilename, + format.outputMime, + onProgress, + signal, + extraFiles + ); +} + +/** + * Re-muxes / re-encodes an audio blob into the specified container format via ffmpeg. + * Throws if ffmpeg fails during transcoding. + */ +export async function transcodeWithContainerFormat( + audioBlob: Blob, + format: ContainerFormat, + onProgress: ((progress: ProgressEvent) => void) | null = null, + signal: AbortSignal | null = null, + extraFiles: any[] = [] +): Promise { + return ffmpeg( + audioBlob, + format.ffmpegArgs, + format.outputFilename, + format.outputMime, + onProgress, + signal, + extraFiles + ); +} diff --git a/js/global.d.ts b/js/global.d.ts index ed623f9ae..c8dbc549f 100644 --- a/js/global.d.ts +++ b/js/global.d.ts @@ -2,3 +2,28 @@ declare module '*?url' { const content: string; export default content; } + +declare module '*?blob-url' { + const urlPromise: () => Promise; + export default urlPromise; +} + +declare module '*?svg&icon' { + const resize: (size: number, attrs?: Record) => string; + export default resize; +} + +declare module '*?svg&icon&class=heart-icon' { + const resize: (size: number, attrs?: Record) => string; + export default resize; +} + +declare module '*?svg&icon&class=heart-icon+filled' { + const resize: (size: number, attrs?: Record) => string; + export default resize; +} + +declare module 'https://cdn.jsdelivr.net/npm/client-zip@2.4.5/+esm' { + /** Creates a ZIP stream from an async iterable of file entries. */ + export function downloadZip(files: AsyncIterable): Response; +} diff --git a/js/haptics.js b/js/haptics.js new file mode 100644 index 000000000..18ebeb178 --- /dev/null +++ b/js/haptics.js @@ -0,0 +1,69 @@ +// js/haptics.js +// Capacitor Haptics wrapper with fallback to Web Vibration API + +let _Haptics = null; +let _ImpactStyle = null; +let _NotificationStyle = null; + +// Single stored promise β€” subsequent calls reuse the same one +const _ready = import('@capacitor/haptics') + .then((mod) => { + _Haptics = mod.Haptics; + _ImpactStyle = mod.ImpactStyle; + _NotificationStyle = mod.NotificationStyle; + }) + .catch(() => { + // Not in Capacitor or haptics not available β€” fall back to navigator.vibrate + }); + +function vibrateFallback(ms) { + if (navigator.vibrate) navigator.vibrate(ms); +} + +/** Light tap β€” for toggles, menu opens */ +export async function hapticLight() { + await _ready; + try { + if (_Haptics) { + await _Haptics.impact({ style: _ImpactStyle.Light }); + return; + } + } catch {} + vibrateFallback(30); +} + +/** Medium impact β€” for play/pause, skip */ +export async function hapticMedium() { + await _ready; + try { + if (_Haptics) { + await _Haptics.impact({ style: _ImpactStyle.Medium }); + return; + } + } catch {} + vibrateFallback(50); +} + +/** Success notification β€” for like/unlike, add to queue */ +export async function hapticSuccess() { + await _ready; + try { + if (_Haptics) { + await _Haptics.notification({ type: _NotificationStyle.Success }); + return; + } + } catch {} + vibrateFallback(40); +} + +/** Long press β€” replaces navigator.vibrate(50) for track selection */ +export async function hapticLongPress() { + await _ready; + try { + if (_Haptics) { + await _Haptics.impact({ style: _ImpactStyle.Medium }); + return; + } + } catch {} + vibrateFallback(50); +} diff --git a/js/hls-downloader.js b/js/hls-downloader.js index a05aa1e47..19ab45f3f 100644 --- a/js/hls-downloader.js +++ b/js/hls-downloader.js @@ -1,3 +1,5 @@ +import { SegmentedDownloadProgress } from './progressEvents'; + export class HlsDownloader { constructor() {} @@ -24,6 +26,8 @@ export class HlsDownloader { for (let i = 0; i < totalSegments; i++) { if (signal?.aborted) throw new Error('AbortError'); + onProgress?.(new SegmentedDownloadProgress(downloadedBytes, undefined, i, totalSegments)); + const segmentUrl = segments[i]; const segmentResponse = await fetch(segmentUrl, { signal }); @@ -35,15 +39,7 @@ export class HlsDownloader { chunks.push(chunk); downloadedBytes += chunk.byteLength; - if (onProgress) { - onProgress({ - stage: 'downloading', - receivedBytes: downloadedBytes, - totalBytes: undefined, - currentSegment: i + 1, - totalSegments: totalSegments, - }); - } + onProgress?.(new SegmentedDownloadProgress(downloadedBytes, undefined, i + 1, totalSegments)); } const mimeType = segments[0].endsWith('.m4s') || segments[0].includes('mp4') ? 'video/mp4' : 'video/mp2t'; diff --git a/js/icons.ts b/js/icons.ts new file mode 100644 index 000000000..39ebf20c1 --- /dev/null +++ b/js/icons.ts @@ -0,0 +1,77 @@ +export { default as SVG_ALIGN_LEFT } from '!lucide/align-left.svg?svg&icon'; +export { default as SVG_ANIMATE_SPIN } from '../images/animate-spin.svg?svg&icon'; +export { default as SVG_APPLE } from '../images/apple.svg?svg&icon'; +export { default as SVG_ATMOS } from '../images/atmos.svg?svg&icon'; +export { default as SVG_BIN } from '!lucide/trash-2.svg?svg&icon'; +export { default as SVG_CALENDAR } from '!lucide/calendar.svg?svg&icon'; +export { default as SVG_CHECK } from '!lucide/check.svg?svg&icon'; +export { default as SVG_CHECKBOX } from '!lucide/square.svg?svg&icon'; +export { default as SVG_CHECKBOX_CHECKED } from '!lucide/check-square.svg?svg&icon'; +export { default as SVG_CLOCK } from '!lucide/clock.svg?svg&icon'; +export { default as SVG_CLOSE } from '!lucide/x.svg?svg&icon'; +export { default as SVG_DISC } from '!lucide/disc.svg?svg&icon'; +export { default as SVG_DOWNLOAD } from '!lucide/download.svg?svg&icon'; +export { default as SVG_EQUAL } from '!lucide/equal.svg?svg&icon'; +export { default as SVG_FACEBOOK } from '../images/facebook.svg?svg&icon'; +export { default as SVG_FOLDER_PLUS } from '!lucide/folder-plus.svg?svg&icon'; +export { default as SVG_GENIUS_ACTIVE } from '../images/genius-active.svg?svg&icon'; +export { default as SVG_GENIUS_INACTIVE } from '../images/genius-inactive.svg?svg&icon'; +export { default as SVG_GLOBE } from '!lucide/globe.svg?svg&icon'; +export { default as SVG_HAND_HEART } from '!lucide/hand-heart.svg?svg&icon'; +export { default as SVG_HEART } from '!lucide/heart.svg?svg&icon&class=heart-icon'; +export { default as SVG_HEART_FILLED } from '!lucide/heart.svg?svg&icon&class=heart-icon+filled'; +export { default as SVG_HOUSE } from '!lucide/house.svg?svg&icon'; +export { default as SVG_INFO } from '!lucide/info.svg?svg&icon'; +export { default as SVG_INSTAGRAM } from '../images/instagram.svg?svg&icon'; +export { default as SVG_KEYBOARD } from '!lucide/keyboard.svg?svg&icon'; +export { default as SVG_LEFT_ARROW } from '!lucide/chevron-left.svg?svg&icon'; +export { default as SVG_LIBRARY } from '!lucide/library.svg?svg&icon'; +export { default as SVG_LINK } from '!lucide/link.svg?svg&icon'; +export { default as SVG_LIST } from '!lucide/list.svg?svg&icon'; +export { default as SVG_LOG_IN } from '!lucide/log-in.svg?svg&icon'; +export { default as SVG_LOG_OUT } from '!lucide/log-out.svg?svg&icon'; +export { default as SVG_MAXIMIZE } from '!lucide/maximize.svg?svg&icon'; +export { default as SVG_MENU } from '!lucide/ellipsis-vertical.svg?svg&icon'; +export { default as SVG_MIC } from '!lucide/mic.svg?svg&icon'; +export { default as SVG_MINUS } from '!lucide/minus.svg?svg&icon'; +export { default as SVG_MIX } from '../images/mix.svg?svg&icon'; +export { default as SVG_MONITOR } from '!lucide/monitor.svg?svg&icon'; +export { default as SVG_MOON } from '!lucide/moon.svg?svg&icon'; +export { default as SVG_MOVE_DOWN } from '!lucide/move-down.svg?svg&icon'; +export { default as SVG_MOVE_UP } from '!lucide/move-up.svg?svg&icon'; +export { default as SVG_MUSIC } from '!lucide/music.svg?svg&icon'; +export { default as SVG_MUTE } from '!lucide/volume-x.svg?svg&icon'; +export { default as SVG_OFFLINE } from '!lucide/triangle-alert.svg?svg&icon'; +export { default as SVG_PALETTE } from '!lucide/palette.svg?svg&icon'; +export { default as SVG_PAUSE } from '../images/pause.svg?svg&icon'; +export { default as SVG_PAUSE_LARGE } from '../images/pause-large.svg?svg&icon'; +export { default as SVG_PENCIL } from '!lucide/pencil.svg?svg&icon'; +export { default as SVG_PLAY } from '../images/play.svg?svg&icon'; +export { default as SVG_PLAY_LARGE } from '../images/play-large.svg?svg&icon'; +export { default as SVG_PLUS } from '!lucide/plus.svg?svg&icon'; +export { default as SVG_RADIO } from '!lucide/radio.svg?svg&icon'; +export { default as SVG_REPEAT } from '!lucide/repeat.svg?svg&icon'; +export { default as SVG_REPEAT_ONE } from '!lucide/repeat-1.svg?svg&icon'; +export { default as SVG_RESET } from '!lucide/rotate-ccw.svg?svg&icon'; +export { default as SVG_RIGHT_ARROW } from '!lucide/chevron-right.svg?svg&icon'; +export { default as SVG_SEARCH } from '!lucide/search.svg?svg&icon'; +export { default as SVG_SETTINGS } from '!lucide/settings.svg?svg&icon'; +export { default as SVG_SHARE } from '!lucide/share.svg?svg&icon'; +export { default as SVG_SHUFFLE } from '!lucide/shuffle.svg?svg&icon'; +export { default as SVG_SKIP_BACK } from '!lucide/skip-back.svg?svg&icon'; +export { default as SVG_SKIP_FORWARD } from '!lucide/skip-forward.svg?svg&icon'; +export { default as SVG_SLIDERS } from '!lucide/sliders-horizontal.svg?svg&icon'; +export { default as SVG_SORT } from '../images/sort.svg?svg&icon'; +export { default as SVG_SOUNDCLOUD } from '../images/soundcloud.svg?svg&icon'; +export { default as SVG_SPARKLES } from '!lucide/sparkles.svg?svg&icon'; +export { default as SVG_SQUARE_PEN } from '!lucide/square-pen.svg?svg&icon'; +export { default as SVG_STORE } from '!lucide/store.svg?svg&icon'; +export { default as SVG_SUN } from '!lucide/sun.svg?svg&icon'; +export { default as SVG_TRASH } from '!lucide/trash.svg?svg&icon'; +export { default as SVG_TWITTER } from '../images/twitter.svg?svg&icon'; +export { default as SVG_UPLOAD } from '!lucide/upload.svg?svg&icon'; +export { default as SVG_USER } from '!lucide/user.svg?svg&icon'; +export { default as SVG_VIDEO } from '!lucide/video.svg?svg&icon'; +export { default as SVG_VOLUME } from '!lucide/volume-2.svg?svg&icon'; +export { default as SVG_VOLUME_1 } from '!lucide/volume-1.svg?svg&icon'; +export { default as SVG_YOUTUBE } from '../images/youtube.svg?svg&icon'; diff --git a/js/listenbrainz.js b/js/listenbrainz.js index 44ff52cda..0310c1643 100644 --- a/js/listenbrainz.js +++ b/js/listenbrainz.js @@ -2,17 +2,19 @@ import { listenBrainzSettings, lastFMStorage } from './storage.js'; export class ListenBrainzScrobbler { constructor() { - this.DEFAULT_API_URL = 'https://api.listenbrainz.org/1'; + this.DEFAULT_API_URL = 'https://api.listenbrainz.org'; this.currentTrack = null; this.scrobbleTimer = null; this.scrobbleThreshold = 0; this.hasScrobbled = false; this.isScrobbling = false; + this.lovingTracks = new Set(); } getApiUrl() { const customUrl = listenBrainzSettings.getCustomUrl(); - return customUrl || this.DEFAULT_API_URL; + const base = customUrl || this.DEFAULT_API_URL; + return base.replace(/\/1\/?$/, ''); } isEnabled() { @@ -26,7 +28,6 @@ export class ListenBrainzScrobbler { _getMetadata(track) { if (!track) return null; - // Get the primary artist name let artistName = 'Unknown Artist'; if (track.artist?.name) { @@ -38,10 +39,9 @@ export class ListenBrainzScrobbler { artistName = typeof first === 'string' ? first : first.name || 'Unknown Artist'; } - // Clean artist name if (typeof artistName === 'string') { artistName = artistName - .split(/\s*[&]\s*|\s+feat\.?\s+|\s+ft\.?\s+|\s+featuring\s+|\s+with\s+|\s+x\s+/i)[0] + .split(/\s*[&]\s*|\s+feat\.?\s*|\s+ft\.?\s*|\s+featuring\s+|\s+with\s+|\s+x\s+/i)[0] .trim(); } @@ -70,12 +70,86 @@ export class ListenBrainzScrobbler { payload.additional_info.is_local = true; } + if (track.mbids) { + if (track.mbids.recording_mbid) { + payload.additional_info.recording_mbid = track.mbids.recording_mbid; + } + if (track.mbids.release_mbid) { + payload.additional_info.release_mbid = track.mbids.release_mbid; + } + if (track.mbids.artist_mbids) { + payload.additional_info.artist_mbids = track.mbids.artist_mbids; + } + } + return payload; } + async _lookupMbids(track) { + if (track.mbids?.recording_mbid) return track.mbids; + let with_album = true; + const metadata = this._getMetadata(track); + if (!metadata || !metadata.artist_name || !metadata.track_name) return null; + + try { + const apiUrl = this.getApiUrl(); + const params = new URLSearchParams({ + recording_name: metadata.track_name, + artist_name: metadata.artist_name, + }); + + if (track.album?.title) { + params.append('release_name', track.album.title); + } + + let response = await fetch(`${apiUrl}/1/metadata/lookup/?${params}`, { + method: 'GET', + headers: { + Authorization: `Token ${this.getToken()}`, + }, + }); + + if (!response.ok) { + console.warn(`[ListenBrainz] MBID lookup failed, trying without album`); + with_album = false; + const params = new URLSearchParams({ + recording_name: metadata.track_name, + artist_name: metadata.artist_name, + }); + response = await fetch(`${apiUrl}/1/metadata/lookup/?${params}`, { + method: 'GET', + headers: { + Authorization: `Token ${this.getToken()}`, + }, + }); + if (!response.ok) { + console.warn(`[ListenBrainz] MBID lookup failed: ${response.status}`); + return null; + } + } + + const data = await response.json(); + if (data?.recording_mbid) { + track.mbids = { + recording_mbid: data.recording_mbid, + artist_mbids: data.artist_mbids, + }; + if (with_album) { + track.mbids.release_mbid = data.release_mbid; + } + console.log(`[ListenBrainz] Found MBID: ${data.recording_mbid}`); + return track.mbids; + } + console.warn('[ListenBrainz] No recording_mbid found in lookup response'); + } catch (error) { + console.error('[ListenBrainz] MBID lookup error:', error); + } + return null; + } + async submitListen(listenType, track, timestamp = null) { if (!this.isEnabled()) return; - + await this._lookupMbids(track); const metadata = this._getMetadata(track); if (!metadata) return; @@ -96,7 +170,7 @@ export class ListenBrainzScrobbler { try { const apiUrl = this.getApiUrl(); - const response = await fetch(`${apiUrl}/submit-listens`, { + const response = await fetch(`${apiUrl}/1/submit-listens`, { method: 'POST', headers: { Authorization: `Token ${this.getToken()}`, @@ -106,12 +180,13 @@ export class ListenBrainzScrobbler { }); if (!response.ok) { - // ListenBrainz doesn't always return JSON on error const text = await response.text(); throw new Error(`ListenBrainz API Error ${response.status}: ${text}`); } - console.log(`[ListenBrainz] Submitted ${listenType}: ${metadata.track_name}`); + console.log( + `[ListenBrainz] Submitted ${listenType}: ${metadata.track_name} ${metadata.artist_name} ${metadata.release_name}` + ); } catch (error) { console.error('[ListenBrainz] Submission failed:', error); } @@ -121,13 +196,10 @@ export class ListenBrainzScrobbler { if (!this.isEnabled()) return; this.currentTrack = track; - // Only reset hasScrobbled if we're not currently in the middle of scrobbling - // to prevent race conditions that could cause double scrobbles if (!this.isScrobbling) { this.hasScrobbled = false; } this.clearScrobbleTimer(); - await this.submitListen('playing_now', track); const scrobblePercentage = lastFMStorage.getScrobblePercentage() / 100; @@ -175,4 +247,44 @@ export class ListenBrainzScrobbler { this.clearScrobbleTimer(); this.currentTrack = null; } + + async loveTrack(track) { + if (!track.artist?.name || !track.title) return; + const trackKey = `${track.artist.name}-${track.title}`; + if (!this.isEnabled() || this.lovingTracks.has(trackKey)) return; + this.lovingTracks.add(trackKey); + + try { + const apiUrl = this.getApiUrl(); + const mbids = await this._lookupMbids(track); + const mbid = mbids?.recording_mbid; + + if (mbid) { + const response = await fetch(`${apiUrl}/1/feedback/recording-feedback`, { + method: 'POST', + headers: { + Authorization: `Token ${this.getToken()}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + recording_mbid: mbid, + score: 1, + }), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`ListenBrainz Feedback Error ${response.status}: ${text}`); + } + + console.log('[ListenBrainz] Loved track:', track.title); + } else { + console.warn('[ListenBrainz] Could not find recording MBID for love feedback'); + } + } catch (error) { + console.error('[ListenBrainz] Failed to love track:', error); + } finally { + this.lovingTracks.delete(trackKey); + } + } } diff --git a/js/lyrics.js b/js/lyrics.js index 8359ba468..3abeca693 100644 --- a/js/lyrics.js +++ b/js/lyrics.js @@ -1,5 +1,14 @@ //js/lyrics.js -import { getTrackTitle, getTrackArtists, buildTrackFilename, SVG_CLOSE } from './utils.js'; +import { getTrackTitle, getTrackArtists, buildTrackFilename } from './utils.js'; +import { + SVG_CLOSE, + SVG_GENIUS_ACTIVE, + SVG_GENIUS_INACTIVE, + SVG_MINUS, + SVG_PLUS, + SVG_RESET, + SVG_GLOBE, +} from './icons.js'; import { sidePanelManager } from './side-panel.js'; import '@uimaxbai/am-lyrics/am-lyrics.js'; @@ -22,7 +31,23 @@ function trackHasAsianText(track) { const artist = getTrackArtists(track) || ''; return containsAsianText(title) || containsAsianText(artist); } -const SVG_GENIUS_INACTIVE = ``; + +function cleanTrackerSearch(text) { + if (!text) return ''; + // chud emojis will NOT be tolerated in my precious genius lyrics worker + let cleaned = text.replace( + /[\p{Extended_Pictographic}\p{Emoji_Component}\p{Emoji_Presentation}\p{Emoji_Modifier}\p{Emoji_Modifier_Base}\p{Symbol}]/gu, + '' + ); + + cleaned = cleaned.replace(/[\u2600-\u27BF\u2B50\u2B06\u2194\u21AA\u2934\u203C\u2049\u3030\u303D\u3297\u3299]/g, ''); + + cleaned = cleaned.replace(/\[v\s*\d+\s*\]/gi, ''); + + cleaned = cleaned.replace(/\s+/g, ' '); + + return cleaned.trim(); +} class GeniusManager { constructor() { @@ -128,6 +153,16 @@ class GeniusManager { } export class LyricsManager { + static #instance = null; + + static get instance() { + if (!LyricsManager.#instance) { + throw new Error('LyricsManager is not initialized. Call LyricsManager.initialize() first.'); + } + return LyricsManager.#instance; + } + + /** @private */ constructor(api) { this.api = api; this.currentLyrics = null; @@ -151,6 +186,13 @@ export class LyricsManager { this.timingOffset = 0; // Offset in milliseconds (positive = delay lyrics, negative = advance lyrics) } + static async initialize(api) { + if (LyricsManager.#instance) { + throw new Error('LyricsManager is already initialized'); + } + return (LyricsManager.#instance = new LyricsManager(api)); + } + // Get timing offset for current track getTimingOffset(trackId) { try { @@ -449,18 +491,24 @@ export class LyricsManager { return lrc; } - downloadLRC(lyricsData, track) { + getLRC(lyricsData, track) { const lrcContent = this.generateLRCContent(lyricsData, track); if (!lrcContent) { alert('No synced lyrics available for this track'); return; } - const blob = new Blob([lrcContent], { type: 'application/octet-stream' }); + return new File([lrcContent], buildTrackFilename(track, 'LOSSLESS').replace(/\.flac$/, '.lrc'), { + type: 'application/octet-stream', + }); + } + + downloadLRC(lyricsData, track) { + const blob = this.getLRC(lyricsData, track); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; - a.download = buildTrackFilename(track, 'LOSSLESS').replace(/\.flac$/, '.lrc'); + a.download = blob.name; document.body.appendChild(a); a.click(); document.body.removeChild(a); @@ -759,34 +807,24 @@ export function openLyricsPanel(track, audioPlayer, lyricsManager, forceOpen = f container.innerHTML = `
    ${offsetDisplay}
    `; @@ -849,7 +887,7 @@ export function openLyricsPanel(track, audioPlayer, lyricsManager, forceOpen = f geniusBtn.classList.toggle('active-genius', enabled); geniusBtn.style.color = enabled ? '#ffff64' : ''; - geniusBtn.innerHTML = enabled ? SVG_GENIUS_ACTIVE : SVG_GENIUS_INACTIVE; + geniusBtn.innerHTML = enabled ? SVG_GENIUS_ACTIVE(20) : SVG_GENIUS_INACTIVE(20); if (enabled) { try { @@ -937,19 +975,28 @@ async function renderLyricsComponent(container, track, audioPlayer, lyricsManage lyricsManager.isRomajiMode = lyricsManager.getRomajiMode(); lyricsManager.currentTrackId = track.id; - const title = track.title; + const title = getTrackTitle(track); const artist = getTrackArtists(track); const album = track.album?.title; const durationMs = track.duration ? Math.round(track.duration * 1000) : undefined; const isrc = track.isrc || ''; + const isTracker = track.isTracker || (track.id && String(track.id).startsWith('tracker-')); + let queryTitle = title; + let queryArtist = artist; + + if (isTracker) { + queryTitle = cleanTrackerSearch(title); + queryArtist = cleanTrackerSearch(artist); + } + container.innerHTML = ''; const amLyrics = document.createElement('am-lyrics'); - amLyrics.setAttribute('song-title', title); - amLyrics.setAttribute('song-artist', artist); + amLyrics.setAttribute('song-title', queryTitle); + amLyrics.setAttribute('song-artist', queryArtist); if (album) amLyrics.setAttribute('song-album', album); if (durationMs) amLyrics.setAttribute('song-duration', durationMs); - amLyrics.setAttribute('query', `${title} ${artist}`.trim()); + amLyrics.setAttribute('query', `${queryTitle} ${queryArtist}`.trim()); if (isrc) amLyrics.setAttribute('isrc', isrc); amLyrics.setAttribute('highlight-color', getLyricsHighlightColor()); diff --git a/js/metadata.flac.js b/js/metadata.flac.js index 7a3f7682a..d5045f202 100644 --- a/js/metadata.flac.js +++ b/js/metadata.flac.js @@ -1,6 +1,6 @@ import { getCoverBlob, getTrackTitle } from './utils.js'; import { getFullArtistString } from './utils.js'; -import { METADATA_STRINGS } from './metadata.js'; +import { METADATA_STRINGS } from './METADATA_STRINGS.js'; export const FLAC_MIME_TYPE = 'audio/flac'; const FLAC_BLOCK_TYPES = { diff --git a/js/metadata.js b/js/metadata.js index 76e24b946..57fe1c8bd 100644 --- a/js/metadata.js +++ b/js/metadata.js @@ -1,32 +1,30 @@ import { getCoverBlob, getTrackTitle, getFullArtistString, getMimeType, getTrackCoverId } from './utils.js'; -import { fetchTagLib, addMetadataWithTagLib, getMetadataWithTagLib } from './taglib.ts'; -import { doTimed, doTimedAsync } from './doTimed.ts'; -import { managers } from './app.js'; +import { addMetadataWithTagLib, getMetadataWithTagLib } from './taglib.ts'; +import { LyricsManager } from './lyrics.js'; +import { Mp4Stik } from './taglib.types.ts'; -export const METADATA_STRINGS = { - VENDOR_STRING: 'Monochrome', - DEFAULT_TITLE: 'Unknown Title', - DEFAULT_ARTIST: 'Unknown Artist', - DEFAULT_ALBUM: 'Unknown Album', -}; +/** + * @typedef {import('./container-classes.ts').Track} Track + * @typedef {import('./container-classes.ts').EnrichedTrack} EnrichedTrack + * @typedef {import("./taglib.types.ts").TagLibMetadata} TagLibMetadata + */ export function prefetchMetadataObjects(track, api, coverBlob = null) { - const _tagLib = fetchTagLib().catch(console.error); const coverId = getTrackCoverId(track); const coverFetch = coverBlob ? Promise.resolve(coverBlob) : coverId ? getCoverBlob(api, coverId).catch(console.error) : Promise.resolve(null); - const lyricsFetch = managers?.lyricsManager?.fetchLyrics?.(track.id, track)?.catch(console.error); + const lyricsFetch = LyricsManager.instance.fetchLyrics?.(track.id, track)?.catch(console.error); - return { _tagLib, coverFetch, lyricsFetch }; + return { coverFetch, lyricsFetch }; } /** * Adds metadata tags to audio files (FLAC, M4A or MP3) * @param {Blob} audioBlob - The audio file blob - * @param {Object} track - Track metadata + * @param {Track | EnrichedTrack} track - Track metadata * @param {Object} api - API instance for fetching album art * @param {string} quality - Audio quality * @returns {Promise} - Audio blob with embedded metadata @@ -35,23 +33,32 @@ export async function addMetadataToAudio(audioBlob, track, api, _quality, prefet const { coverFetch, lyricsFetch } = prefetchPromises; /** - * @type {import("./taglib.worker.ts").TagLibMetadata} + * @type {TagLibMetadata} */ const data = {}; - const audioBuffer = await doTimedAsync('Get audio array buffer', () => audioBlob.arrayBuffer()); - try { data.title = getTrackTitle(track); data.artist = getFullArtistString(track); - data.albumTitle = track.album.title; + data.albumTitle = track.album?.title; data.albumArtist = track.album?.artist?.name || track.artist?.name; data.trackNumber = track.trackNumber; data.discNumber = track.volumeNumber ?? track.discNumber; - data.totalTracks = track.album.numberOfTracks; + data.totalTracks = track.album?.numberOfTracksOnDisc ?? track.album?.numberOfTracks; + data.totalDiscs = track.album?.totalDiscs; data.copyright = track.copyright; data.isrc = track.isrc; + data.upc = track.album?.upc; data.explicit = Boolean(track.explicit); + data.stik = track.type?.toLowerCase().includes('video') ? Mp4Stik.MusicVideo : Mp4Stik.Normal; + data.extra = { + TIDAL_TRACK_ID: track.id ? String(track.id) : undefined, + TIDAL_ALBUM_ID: track.album?.id ? String(track.album?.id) : undefined, + TIDAL_TRACK_URL: track.url?.trim() || undefined, + TIDAL_ALBUM_URL: track.album?.url?.trim() || undefined, + ALBUM_RELEASE_DATE: track.album?.releaseDate?.trim() || undefined, + TIDAL_DATA: JSON.stringify(track, null, 2).replace(/\n/g, '\r\n'), + }; if (track.bpm != null) { const bpm = Number(track.bpm); @@ -88,9 +95,9 @@ export async function addMetadataToAudio(audioBlob, track, api, _quality, prefet try { if (track.album?.cover) { const coverBlob = await coverFetch; - const coverBuffer = new Uint8Array(await coverBlob.arrayBuffer()); if (coverBlob) { + const coverBuffer = new Uint8Array(await coverBlob.arrayBuffer()); data.cover = { data: coverBuffer, type: getMimeType(coverBuffer), @@ -108,16 +115,14 @@ export async function addMetadataToAudio(audioBlob, track, api, _quality, prefet console.warn('Error setting lyrics metadata', track, e); } - const newAudioBuffer = await addMetadataWithTagLib(audioBuffer, { - ...data, - }); - - return doTimed( - 'Create new audio blob', - () => - new Blob([newAudioBuffer], { - type: audioBlob.type, - }) + return await addMetadataWithTagLib( + audioBlob, + { + ...data, + }, + undefined, + true, + true ); } catch (err) { console.error(err); @@ -128,12 +133,12 @@ export async function addMetadataToAudio(audioBlob, track, api, _quality, prefet /** * Reads metadata from a file - * @param {File} file + * @param {Uint8Array | Blob | File | FileSystemFileHandle | FileSystemFileEntry} file * @returns {Promise} Track metadata */ -export async function readTrackMetadata(file, siblings = []) { +export async function readTrackMetadata(file, { filename = file?.name || 'Unknown Title', siblings } = {}) { const metadata = { - title: file.name.replace(/\.[^/.]+$/, ''), + title: filename?.replace(/\.[^/.]+$/, ''), artists: [], artist: { name: 'Unknown Artist' }, // For fallback/compatibility album: { title: 'Unknown Album', cover: 'assets/appicon.png', releaseDate: null }, @@ -143,24 +148,33 @@ export async function readTrackMetadata(file, siblings = []) { explicit: false, isLocal: true, file: file, - id: `local-${file.name}-${file.lastModified}`, + id: `local-${filename}-${file.lastModified}`, }; try { - const data = await getMetadataWithTagLib(await file.arrayBuffer()); + const data = await getMetadataWithTagLib(file, filename, true); if (data) { metadata.title = data.title || metadata.title; - metadata.artists.push( - ...(data.artist || '') - .split(';') - .map((a) => a.trim()) - .filter((a) => a) - ); - metadata.artist = data.artist || metadata.artist; + const artistNames = (data.artist || '') + .split(';') + .map((a) => a.trim()) + .filter((a) => a); + + if (artistNames.length > 0) { + metadata.artists = artistNames.map((name) => ({ name })); + metadata.artist = metadata.artists[0]; + } + metadata.album.title = data.albumTitle || metadata.album.title; metadata.album.releaseDate = data.releaseDate || metadata.album.releaseDate; + if (data.albumArtist) { + metadata.album.artist = { name: data.albumArtist }; + } else if (metadata.artist.name !== 'Unknown Artist') { + metadata.album.artist = { name: metadata.artist.name }; + } + if (data.cover) { const blob = new Blob([data.cover.data], { type: data.cover.type }); metadata.album.cover = URL.createObjectURL(blob); @@ -172,15 +186,11 @@ export async function readTrackMetadata(file, siblings = []) { metadata.explicit = !!data.explicit; } } catch (e) { - console.warn('Error reading metadata for', file.name, e); - } - - if (metadata.artists.length > 0) { - metadata.artist = metadata.artists[0]; + console.warn('Error reading metadata for', filename, e); } - if (metadata.album.cover === 'assets/appicon.png' && siblings.length > 0) { - const baseName = file.name.substring(0, file.name.lastIndexOf('.')); + if (metadata.album.cover === 'assets/appicon.png' && siblings?.length > 0) { + const baseName = filename.substring(0, filename.lastIndexOf('.')); const imageExtensions = ['.jpg', '.jpeg', '.png', '.webp']; const coverFile = siblings.find((f) => { const fName = f.name; diff --git a/js/mp3-encoder.js b/js/mp3-encoder.js index 6664fb0ca..f45811a40 100644 --- a/js/mp3-encoder.js +++ b/js/mp3-encoder.js @@ -1,5 +1,9 @@ import { ffmpeg } from './ffmpeg'; +/** + * @typedef {import('./ffmpeg.types.ts').FfmpegProgress} FfmpegProgress + */ + class MP3EncodingError extends Error { constructor(message) { super(message); @@ -8,6 +12,13 @@ class MP3EncodingError extends Error { } } +/** + * + * @param {Blob} audioBlob + * @param {(progress: FfmpegProgress) => void} [onProgress=null] + * @param {AbortSignal|null} [signal=null] + * @returns {Promise} Encoded MP3 audio blob + */ export async function encodeToMp3(audioBlob, onProgress = null, signal = null) { try { // Use Web Worker for non-blocking FFmpeg encoding diff --git a/js/multi-scrobbler.js b/js/multi-scrobbler.js index 0e057ab30..d4616acef 100644 --- a/js/multi-scrobbler.js +++ b/js/multi-scrobbler.js @@ -57,6 +57,7 @@ export class MultiScrobbler { async loveTrack(track) { await this.lastfm.loveTrack(track); await this.librefm.loveTrack(track); - // ListenBrainz and Maloja feedback could be added here when supported + await this.listenbrainz.loveTrack(track); + // Maloja feedback could be added here when supported } } diff --git a/js/music-api.js b/js/music-api.js index 221c2f50f..33d0ff44a 100644 --- a/js/music-api.js +++ b/js/music-api.js @@ -1,92 +1,132 @@ // js/music-api.js -// Unified API wrapper that supports both Tidal and Qobuz import { LosslessAPI } from './api.js'; -import { QobuzAPI } from './qobuz-api.js'; +import { PodcastsAPI } from './podcasts-api.js'; import { musicProviderSettings } from './storage.js'; export class MusicAPI { + static #instance = null; + static get instance() { + if (!MusicAPI.#instance) { + throw new Error('MusicAPI not initialized. Call MusicAPI.initialize(settings) first.'); + } + return MusicAPI.#instance; + } + + /** @private */ constructor(settings) { this.tidalAPI = new LosslessAPI(settings); - this.qobuzAPI = new QobuzAPI(); + this.podcastsAPI = new PodcastsAPI(); this._settings = settings; this.videoArtworkCache = new Map(); } + static async initialize(settings) { + if (MusicAPI.#instance) { + throw new Error('MusicAPI is already initialized'); + } + + const api = new MusicAPI(settings); + return (MusicAPI.#instance = api); + } + getCurrentProvider() { return musicProviderSettings.getProvider(); } // Get the appropriate API based on provider getAPI(provider = null) { - const p = provider || this.getCurrentProvider(); - return p === 'qobuz' ? this.qobuzAPI : this.tidalAPI; + return this.tidalAPI; } // Search methods + async search(query, options = {}) { + const api = this.getAPI(); + if (typeof api.search === 'function') { + return api.search(query, options); + } + + // Fallback for providers that don't implement unified search + const [tracksResult, videosResult, artistsResult, albumsResult, playlistsResult] = await Promise.all([ + api.searchTracks(query, options), + api.searchVideos ? api.searchVideos(query, options) : Promise.resolve({ items: [] }), + api.searchArtists(query, options), + api.searchAlbums(query, options), + api.searchPlaylists ? api.searchPlaylists(query, options) : Promise.resolve({ items: [] }), + ]); + + return { + tracks: tracksResult, + videos: videosResult, + artists: artistsResult, + albums: albumsResult, + playlists: playlistsResult, + }; + } + async searchTracks(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchTracks(query, options); + return this.getAPI().searchTracks(query, options); } async searchArtists(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchArtists(query, options); + return this.getAPI().searchArtists(query, options); } async searchAlbums(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchAlbums(query, options); + return this.getAPI().searchAlbums(query, options); } async searchPlaylists(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - if (provider === 'qobuz') { - // Qobuz doesn't support playlist search, return empty - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } return this.tidalAPI.searchPlaylists(query, options); } async searchVideos(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); return this.tidalAPI.searchVideos(query, options); } + async searchPodcasts(query, options = {}) { + return this.podcastsAPI.searchPodcasts(query, options); + } + + async getPodcast(id, options = {}) { + return this.podcastsAPI.getPodcastById(id, options); + } + + async getPodcastEpisodes(id, options = {}) { + return this.podcastsAPI.getPodcastEpisodes(id, options); + } + + async getTrendingPodcasts(options = {}) { + return this.podcastsAPI.getTrendingPodcasts(options); + } + // Get methods async getTrack(id, quality, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getTrack(cleanId, quality); } async getTrackMetadata(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getTrackMetadata(cleanId); } async getAlbum(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getAlbum(cleanId); } async getArtist(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getArtist(cleanId); } async getArtistBiography(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - if (p !== 'tidal') return null; // Biography only supported for Tidal - - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getArtistBiography === 'function') { return api.getArtistBiography(cleanId); @@ -95,15 +135,13 @@ export class MusicAPI { } async getVideo(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getVideo(cleanId); } async getVideoStreamUrl(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getVideoStreamUrl === 'function') { return api.getVideoStreamUrl(cleanId); @@ -125,8 +163,7 @@ export class MusicAPI { } async getTrackRecommendations(id) { - const p = this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getTrackRecommendations === 'function') { return api.getTrackRecommendations(cleanId); @@ -136,8 +173,7 @@ export class MusicAPI { // Stream methods async getStreamUrl(id, quality, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getStreamUrl(cleanId, quality); } @@ -147,10 +183,7 @@ export class MusicAPI { if (typeof id === 'string' && id.startsWith('blob:')) { return id; } - if (typeof id === 'string' && id.startsWith('q:')) { - return this.qobuzAPI.getCoverUrl(id.slice(2), size); - } - return this.tidalAPI.getCoverUrl(id, size); + return this.tidalAPI.getCoverUrl(this.stripProviderPrefix(id), size); } getVideoCoverUrl(imageId, size = '1280') { @@ -160,10 +193,7 @@ export class MusicAPI { if (typeof imageId === 'string' && imageId.startsWith('blob:')) { return imageId; } - if (typeof imageId === 'string' && imageId.startsWith('q:')) { - return null; - } - return this.tidalAPI.getVideoCoverUrl(imageId, size); + return this.tidalAPI.getVideoCoverUrl(this.stripProviderPrefix(imageId), size); } async getVideoArtwork(title, artist) { @@ -190,10 +220,7 @@ export class MusicAPI { } getArtistPictureUrl(id, size = '320') { - if (typeof id === 'string' && id.startsWith('q:')) { - return this.qobuzAPI.getArtistPictureUrl(id.slice(2), size); - } - return this.tidalAPI.getArtistPictureUrl(id, size); + return this.tidalAPI.getArtistPictureUrl(this.stripProviderPrefix(id), size); } extractStreamUrlFromManifest(manifest) { @@ -203,7 +230,6 @@ export class MusicAPI { // Helper methods getProviderFromId(id) { if (typeof id === 'string') { - if (id.startsWith('q:')) return 'qobuz'; if (id.startsWith('t:')) return 'tidal'; } return null; @@ -220,23 +246,24 @@ export class MusicAPI { // Download methods async downloadTrack(id, quality, filename, options = {}) { - const provider = this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.downloadTrack(cleanId, quality, filename, options); } // Similar/recommendation methods async getSimilarArtists(artistId) { - const provider = this.getProviderFromId(artistId) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(artistId); return api.getSimilarArtists(cleanId); } + async getArtistTopTracks(artistId, options = {}) { + return this.tidalAPI.getArtistTopTracks(artistId, options); + } + async getSimilarAlbums(albumId) { - const provider = this.getProviderFromId(albumId) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(albumId); return api.getSimilarAlbums(cleanId); } @@ -249,7 +276,6 @@ export class MusicAPI { // Cache methods async clearCache() { await this.tidalAPI.clearCache(); - // Qobuz doesn't have cache yet } getCacheStats() { @@ -261,3 +287,5 @@ export class MusicAPI { return this._settings; } } + +export const musicAPI = new MusicAPI(); diff --git a/js/platform-detection.ts b/js/platform-detection.ts new file mode 100644 index 000000000..a44ac38a4 --- /dev/null +++ b/js/platform-detection.ts @@ -0,0 +1,17 @@ +/** The original user agent string before spoofing. */ +export const originalUserAgent = navigator.userAgent; + +/** A lowercase version of the original user agent string. */ +const lowerCaseOriginalUserAgent = originalUserAgent.toLowerCase(); + +/** If the device is an iOS device. (iPhone, iPad, iPod, or Apple Vision) */ +export const isIos = + /iphone|ipad|ipod|applevision/.test(lowerCaseOriginalUserAgent) || + (lowerCaseOriginalUserAgent.includes('mac') && navigator.maxTouchPoints > 1); + +/** If the browser is Safari (excluding Chrome, Chromium-based browsers, and Android browsers). */ +export const isSafari = + lowerCaseOriginalUserAgent.includes('safari') && + !lowerCaseOriginalUserAgent.includes('chrome') && + !lowerCaseOriginalUserAgent.includes('crios') && + !lowerCaseOriginalUserAgent.includes('android'); diff --git a/js/player.js b/js/player.js index 1a6476db9..f9485775c 100644 --- a/js/player.js +++ b/js/player.js @@ -1,5 +1,3 @@ -//js/player.js -import { MediaPlayer } from 'dashjs'; import { REPEAT_MODE, formatTime, @@ -9,6 +7,7 @@ import { getTrackYearDisplay, createQualityBadgeHTML, escapeHtml, + deriveTrackQuality, } from './utils.js'; import { queueManager, @@ -19,10 +18,23 @@ import { radioSettings, } from './storage.js'; import { audioContextManager } from './audio-context.js'; +import { isIos, isSafari } from './platform-detection.js'; import { db } from './db.js'; -import Hls from 'hls.js'; + +import { SVG_CLOCK, SVG_ATMOS } from './icons.js'; +import { UIRenderer } from './ui.js'; export class Player { + static #instance = null; + + static get instance() { + if (!Player.#instance) { + throw new Error('Player is not initialized. Call Player.initialize(audioElement, api) first.'); + } + return Player.#instance; + } + + /** @private */ constructor(audioElement, api, quality = 'HI_RES_LOSSLESS') { this.audio = audioElement; this.video = document.getElementById('video-player'); @@ -42,7 +54,7 @@ export class Player { this.isFallbackRetry = false; this.isFallbackInProgress = false; this.autoplayBlocked = false; - this.isIOS = typeof window !== 'undefined' && window.__IS_IOS__ === true; + this.isIOS = isIos; this.isPwa = typeof window !== 'undefined' && (window.matchMedia?.('(display-mode: standalone)')?.matches || window.navigator?.standalone === true); @@ -52,7 +64,28 @@ export class Player { this.sleepTimer = null; this.sleepTimerEndTime = null; this.sleepTimerInterval = null; + // Artist popular tracks state + this.artistPopularTracksState = { + artistId: null, + offset: 0, + initialTracks: [], + isFetching: false, + hasMore: true, + }; + } + static async initialize(audioElement, api, quality) { + if (Player.#instance) { + throw new Error('Player is already initialized'); + } + + const player = new Player(audioElement, api, quality); + await player.init(); + Player.#instance = player; + return player; + } + + async init() { // Apply audio effects when track is ready this.audio.addEventListener('canplay', () => { this.applyAudioEffects(); @@ -63,16 +96,41 @@ export class Player { }); } - // Initialize dash.js player - this.dashPlayer = MediaPlayer().create(); - this.dashPlayer.updateSettings({ - streaming: { - buffer: { - fastSwitchEnabled: true, + // Initialize Shaka player + const shaka = await import('shaka-player'); + shaka.polyfill.installAll(); + if (shaka.Player.isBrowserSupported()) { + this.shakaPlayer = new shaka.Player(); + this.shakaPlayer.configure({ + streaming: { + bufferingGoal: 30, + rebufferingGoal: 2, + bufferBehind: 30, + jumpLargeGaps: true, }, - }, - }); - this.dashInitialized = false; + abr: { + enabled: true, + // Start with a low bandwidth estimate (200kbps) so it plays instantly + // on slow connections and smoothly scales UP to Hi-Fi if the connection allows. + defaultBandwidthEstimate: 100000, + switchInterval: 1, // Check more frequently + bandwidthDowngradeTarget: 0.8, // Downgrade more aggressively if bandwidth drops + restrictToElementSize: false, + }, + mediaSource: { + codecSwitchingStrategy: 'smooth', + }, + }); + this.shakaPlayer.addEventListener('adaptation', this.updateAdaptiveQualityBadge.bind(this)); + this.shakaPlayer.addEventListener('variantchanged', this.updateAdaptiveQualityBadge.bind(this)); + + this.shakaInitialized = false; + + // Monitor and bridge different codec groups (e.g. AAC to FLAC) since native ABR isolates them + setInterval(this.evaluateCrossCodecAbr.bind(this), 3000); + } else { + console.error('Browser not supported for Shaka Player'); + } this.loadQueueState(); this.setupMediaSession(); @@ -178,12 +236,18 @@ export class Player { const el = this.activeElement; // Apply to audio element and/or Web Audio graph - if (audioContextManager.isReady()) { + const isApple = isIos || isSafari; + + if (audioContextManager.isReady() && !isApple) { // If Web Audio is active, we apply volume there for better compatibility // Especially on Linux where audio.volume might not affect the Web Audio graph el.volume = 1.0; audioContextManager.setVolume(effectiveVolume); } else { + // Safari bypasses WebAudio for HLS, so we MUST set el.volume directly to reflect ReplayGain + if (audioContextManager.isReady()) { + audioContextManager.setVolume(1.0); // Reset graph gain if it somehow routes + } el.volume = Math.max(0, Math.min(1, effectiveVolume)); } } @@ -192,14 +256,8 @@ export class Player { const speed = audioEffectsSettings.getSpeed(); const el = this.activeElement; - if (this.dashInitialized && this.dashPlayer) { - if (this.dashPlayer.getPlaybackRate() !== speed) { - this.dashPlayer.setPlaybackRate(speed); - } - } else { - if (el.playbackRate !== speed) { - el.playbackRate = speed; - } + if (el.playbackRate !== speed) { + el.playbackRate = speed; } const preservePitch = audioEffectsSettings.isPreservePitchEnabled(); @@ -457,17 +515,20 @@ export class Player { for (const { track } of tracksToPreload) { if (this.preloadCache.has(track.id)) continue; const isTracker = track.isTracker || (track.id && String(track.id).startsWith('tracker-')); - if (track.isLocal || isTracker || (track.audioUrl && !track.isLocal)) continue; + const isPodcast = track.isPodcast || (track.id && String(track.id).startsWith('podcast_')); + if (track.isLocal || isTracker || isPodcast || (track.audioUrl && !track.isLocal)) continue; try { - const streamUrl = await this.api.getStreamUrl(track.id, this.quality); + const streamInfo = await this.api.getStreamUrl(track.id, this.quality); if (this.preloadAbortController.signal.aborted) break; - this.preloadCache.set(track.id, streamUrl); + this.preloadCache.set(track.id, streamInfo); // Warm connection/cache // For Blob URLs (DASH), this head request is not needed and can cause errors. - if (!streamUrl.startsWith('blob:')) { - fetch(streamUrl, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch(() => {}); + if (!streamInfo.url.startsWith('blob:')) { + fetch(streamInfo.url, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch( + () => {} + ); } } catch (error) { if (error.name !== 'AbortError') { @@ -477,8 +538,9 @@ export class Player { } } - setupHlsVideo(video, result, fallbackImg) { + async setupHlsVideo(video, result, fallbackImg) { const url = result.videoUrl || result.hlsUrl || result; + const Hls = (await import('hls.js')).default; if (!url) return; if (this.hls) { @@ -496,9 +558,9 @@ export class Player { this.hls = new Hls(); this.hls.loadSource(url); this.hls.attachMedia(video); - this.hls.on(Hls.Events.MANIFEST_PARSED, () => { + this.hls.on(Hls.Events.MANIFEST_PARSED, async () => { video.play().catch(() => {}); - this.setupVideoQualitySelector(); + await this.setupVideoQualitySelector(); }); this.hls.on(Hls.Events.ERROR, (event, data) => { if (data.fatal) { @@ -515,9 +577,9 @@ export class Player { } } else { video.src = url; - video.onerror = () => { + video.onerror = async () => { if (result && result.hlsUrl) { - this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, fallbackImg); + await this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, fallbackImg); } else if (fallbackImg) { video.replaceWith(fallbackImg); } @@ -525,8 +587,9 @@ export class Player { } } - setupVideoQualitySelector() { + async setupVideoQualitySelector() { if (!this.hls || !this.hls.levels || this.hls.levels.length === 0) return; + const Hls = (await import('hls.js')).default; const qualityBtn = document.getElementById('fs-quality-btn'); const qualityMenu = document.getElementById('fs-quality-menu'); @@ -632,6 +695,33 @@ export class Player { return; } + // Proactively fetch more artist tracks when the last track starts playing + console.log('[playTrackFromQueue] Check for fetch:', { + radioEnabled: this.radioEnabled, + artistId: this.artistPopularTracksState.artistId, + hasMore: this.artistPopularTracksState.hasMore, + isFetching: this.artistPopularTracksState.isFetching, + currentIndex: this.currentQueueIndex, + queueLength: currentQueue.length, + isLastTrack: this.currentQueueIndex >= currentQueue.length - 1, + }); + + if ( + !this.radioEnabled && + this.artistPopularTracksState.artistId && + this.artistPopularTracksState.hasMore && + !this.artistPopularTracksState.isFetching && + this.currentQueueIndex >= currentQueue.length - 1 + ) { + console.log('[playTrackFromQueue] Fetching more tracks!'); + this.fetchMoreArtistPopularTracks().then((newTracks) => { + console.log('[playTrackFromQueue] Got tracks:', newTracks?.length); + if (newTracks && newTracks.length > 0) { + this.addToQueue(newTracks); + } + }); + } + this.saveQueueState(); this.currentTrack = track; @@ -652,9 +742,9 @@ export class Player { this.hls.destroy(); this.hls = null; } - if (this.dashInitialized) { - this.dashPlayer.reset(); - this.dashInitialized = false; + if (this.shakaInitialized && this.shakaPlayer) { + this.shakaPlayer.unload(); + this.shakaInitialized = false; } if (inactiveElement) { @@ -744,8 +834,34 @@ export class Player { let streamUrl; const isTracker = track.isTracker || (track.id && String(track.id).startsWith('tracker-')); + const isPodcast = track.isPodcast || (track.id && String(track.id).startsWith('podcast_')); + + if (isPodcast) { + streamUrl = track.enclosureUrl; + if (!streamUrl) { + console.warn(`Podcast episode ${trackTitle} audio URL is missing. Skipping.`); + track.isUnavailable = true; + this.playNext(); + return; + } + + if (this.playbackSequence !== currentSequence) return; - if (isTracker || (track.audioUrl && !track.isLocal)) { + this.currentRgValues = null; + this.applyReplayGain(); + + activeElement.src = streamUrl; + this.applyAudioEffects(); + + const canPlay = await this.waitForCanPlayOrTimeout(activeElement); + if (!canPlay || this.playbackSequence !== currentSequence) return; + + if (startTime > 0) { + activeElement.currentTime = startTime; + } + const played = await this.safePlay(activeElement); + if (!played) return; + } else if (isTracker || (track.audioUrl && !track.isLocal)) { streamUrl = track.audioUrl; if ( @@ -811,12 +927,12 @@ export class Player { const played = await this.safePlay(activeElement); if (!played) return; } else if (track.type === 'video') { - if (window.monochromeUi) { + if (UIRenderer.instance) { const isInFullscreen = document.getElementById('fullscreen-cover-overlay')?.style.display === 'flex'; if (!isInFullscreen) { - const lyricsManager = window.monochromeUi.lyricsManager; - window.monochromeUi.showFullscreenCover( + const lyricsManager = UIRenderer.instance.lyricsManager; + UIRenderer.instance.showFullscreenCover( track, this.getNextTrack(), lyricsManager, @@ -829,10 +945,16 @@ export class Player { if (this.playbackSequence !== currentSequence) return; if (streamUrl.includes('.m3u8') || streamUrl.includes('application/vnd.apple.mpegurl')) { - this.setupHlsVideo(activeElement, streamUrl, null); + await this.setupHlsVideo(activeElement, streamUrl, null); } else if (streamUrl.startsWith('blob:') || streamUrl.includes('.mpd')) { - this.dashPlayer.initialize(activeElement, streamUrl, false); - this.dashInitialized = true; + await this.shakaPlayer.attach(activeElement); + await this.shakaPlayer.load(streamUrl); + this.shakaInitialized = true; + + const savedAdaptiveQuality = localStorage.getItem('adaptive-playback-quality') || 'auto'; + this.forceQuality(savedAdaptiveQuality); + + this.updateAdaptiveQualityBadge(); } else { activeElement.src = streamUrl; } @@ -848,21 +970,23 @@ export class Player { await this.safePlay(activeElement); } else { - const isQobuz = String(track.id).startsWith('q:'); + // Tidal: Try to get ReplayGain from manifest first, supplement with track info if needed + const streamInfoPromise = this.preloadCache.has(track.id) + ? Promise.resolve(this.preloadCache.get(track.id)) + : this.api.getStreamUrl(track.id, this.quality); - if (isQobuz) { - // Qobuz: skip getTrack call, directly fetch stream URL - this.currentRgValues = null; - this.applyReplayGain(); + // We only need the legacy track info if we missed getting ReplayGain from the manifest endpoint + const resolvedStreamInfo = await streamInfoPromise; + if (this.playbackSequence !== currentSequence) return; - if (this.preloadCache.has(track.id)) { - streamUrl = this.preloadCache.get(track.id); - } else { - streamUrl = await this.api.getStreamUrl(track.id, this.quality); - } + streamUrl = resolvedStreamInfo.url; + + if (resolvedStreamInfo.rgInfo) { + this.currentRgValues = resolvedStreamInfo.rgInfo; + this.applyReplayGain(); } else { - // Tidal: Get track data for ReplayGain (should be cached by API) - const trackData = await this.api.getTrack(track.id, this.quality); + // Fallback to legacy metadata if manifest lacked normalization data + const trackData = await this.api.getTrack(track.id, this.quality).catch(() => null); if (this.playbackSequence !== currentSequence) return; if (trackData && trackData.info) { @@ -876,30 +1000,26 @@ export class Player { this.currentRgValues = null; } this.applyReplayGain(); - - if (this.preloadCache.has(track.id)) { - streamUrl = this.preloadCache.get(track.id); - } else if (trackData.originalTrackUrl) { - streamUrl = trackData.originalTrackUrl; - } else if (trackData.info?.manifest) { - streamUrl = this.api.extractStreamUrlFromManifest(trackData.info.manifest); - } else { - streamUrl = await this.api.getStreamUrl(track.id, this.quality); - } } if (this.playbackSequence !== currentSequence) return; // Handle playback - if (streamUrl && streamUrl.startsWith('blob:') && !track.isLocal) { - // It's likely a DASH manifest blob URL - this.dashPlayer.initialize(activeElement, streamUrl, false); - this.dashInitialized = true; - this.applyAudioEffects(); - + if (streamUrl && (streamUrl.startsWith('blob:') || streamUrl.includes('.mpd')) && !track.isLocal) { + // It's likely a DASH manifest URL + await this.shakaPlayer.attach(activeElement); if (startTime > 0) { - this.dashPlayer.seek(startTime); + await this.shakaPlayer.load(streamUrl, startTime); + } else { + await this.shakaPlayer.load(streamUrl); } + this.shakaInitialized = true; + this.applyAudioEffects(); + + const savedAdaptiveQuality = localStorage.getItem('adaptive-playback-quality') || 'auto'; + this.forceQuality(savedAdaptiveQuality); + + this.updateAdaptiveQualityBadge(); const canPlay = await this.waitForCanPlayOrTimeout(activeElement); if (!canPlay || this.playbackSequence !== currentSequence) return; @@ -907,6 +1027,7 @@ export class Player { } else { activeElement.src = streamUrl; this.applyAudioEffects(); + this.updateAdaptiveQualityBadge(); // Wait for audio to be ready before playing const canPlay = await this.waitForCanPlayOrTimeout(activeElement); @@ -965,10 +1086,6 @@ export class Player { const currentQueue = this.getCurrentQueue(); const isLastTrack = this.currentQueueIndex >= currentQueue.length - 1; - if (this.radioEnabled && this.currentQueueIndex >= currentQueue.length - 3) { - this.fetchRadioRecommendations(); - } - if (recursiveCount > currentQueue.length) { if (this.radioEnabled && isLastTrack) { this.fetchRadioRecommendations().then(() => { @@ -979,12 +1096,21 @@ export class Player { }); return; } - console.error('All tracks in queue are unavailable or blocked.'); + if (this.artistPopularTracksState.artistId && this.artistPopularTracksState.hasMore) { + this.fetchMoreArtistPopularTracks().then((newTracks) => { + if (newTracks && newTracks.length > 0) { + this.addToQueue(newTracks); + this.playNext(0); + } else { + this.activeElement.pause(); + } + }); + return; + } this.activeElement.pause(); return; } - // Import blocking settings dynamically import('./storage.js').then(({ contentBlockingSettings }) => { if ( this.repeatMode === REPEAT_MODE.ONE && @@ -998,7 +1124,6 @@ export class Player { if (!isLastTrack) { this.currentQueueIndex++; const track = currentQueue[this.currentQueueIndex]; - // Skip unavailable and blocked tracks if (track?.isUnavailable || contentBlockingSettings.shouldHideTrack(track)) { return this.playNext(recursiveCount + 1); } @@ -1010,10 +1135,19 @@ export class Player { } }); return; + } else if (this.artistPopularTracksState.artistId && this.artistPopularTracksState.hasMore) { + this.fetchMoreArtistPopularTracks().then((newTracks) => { + if (newTracks && newTracks.length > 0) { + this.addToQueue(newTracks); + } + // Now play the next track (which is now at currentQueueIndex + 1 if tracks were added) + this.currentQueueIndex++; + this.playTrackFromQueue(0, recursiveCount); + }); + return; } else if (this.repeatMode === REPEAT_MODE.ALL) { this.currentQueueIndex = 0; const track = currentQueue[this.currentQueueIndex]; - // Skip unavailable and blocked tracks if (track?.isUnavailable || contentBlockingSettings.shouldHideTrack(track)) { return this.playNext(recursiveCount + 1); } @@ -1209,7 +1343,9 @@ export class Player { handlePlayPause() { const el = this.activeElement; - if (!el.src || el.error) { + const hasSource = el.src || el.currentSrc || el.srcObject || this.shakaInitialized; + + if (!hasSource || el.error) { if (this.currentTrack) { this.playTrackFromQueue(0, 0); } @@ -1297,6 +1433,70 @@ export class Player { this.saveQueueState(); } + setArtistPopularTracksContext(artistId, initialTracks, offset = 15, hasMore = true) { + this.artistPopularTracksState = { + artistId, + offset, + initialTracks, + isFetching: false, + hasMore, + }; + } + + clearArtistPopularTracksContext() { + this.artistPopularTracksState = { + artistId: null, + offset: 0, + initialTracks: [], + isFetching: false, + hasMore: false, + }; + } + + async fetchMoreArtistPopularTracks() { + const state = this.artistPopularTracksState; + console.log('[fetchMoreArtistPopularTracks] Called:', { + artistId: state.artistId, + offset: state.offset, + isFetching: state.isFetching, + hasMore: state.hasMore, + }); + + if (!state.artistId || state.isFetching || !state.hasMore) { + console.log('[fetchMoreArtistPopularTracks] Early return'); + return []; + } + + state.isFetching = true; + + try { + console.log('[fetchMoreArtistPopularTracks] Fetching with offset:', state.offset); + const result = await this.api.getArtistTopTracks(state.artistId, { + offset: state.offset, + limit: 15, + firstTrackId: state.initialTracks[0]?.id, + }); + + console.log('[fetchMoreArtistPopularTracks] Result:', result); + + if (result.tracks && result.tracks.length > 0) { + state.offset += result.tracks.length; + state.hasMore = result.hasMore; + + return result.tracks; + } else { + state.hasMore = false; + return []; + } + } catch (error) { + console.warn('Failed to fetch more artist popular tracks:', error); + state.hasMore = false; + return []; + } finally { + state.isFetching = false; + } + } + addToQueue(trackOrTracks) { const tracks = Array.isArray(trackOrTracks) ? trackOrTracks : [trackOrTracks]; this.queue.push(...tracks); @@ -1393,8 +1593,8 @@ export class Player { this.originalQueueBeforeShuffle = []; this.currentQueueIndex = -1; this.saveQueueState(); - if (window.monochromeUi) { - window.monochromeUi.setCurrentTrack(null); + if (UIRenderer.instance) { + UIRenderer.instance.setCurrentTrack(null); } if (window.renderQueueFunction) { window.renderQueueFunction(); @@ -1697,23 +1897,13 @@ export class Player { btn.classList.add('active'); btn.style.color = 'var(--primary)'; } else { - btn.innerHTML = ` - - - - - `; + btn.innerHTML = SVG_CLOCK(20); btn.title = 'Sleep Timer'; btn.classList.remove('active'); btn.style.color = ''; } } else { - btn.innerHTML = ` - - - - - `; + btn.innerHTML = SVG_CLOCK(20); btn.title = 'Sleep Timer'; btn.classList.remove('active'); btn.style.color = ''; diff --git a/js/playlist-generator.js b/js/playlist-generator.js index 3b22b2127..59eb0115b 100644 --- a/js/playlist-generator.js +++ b/js/playlist-generator.js @@ -4,12 +4,20 @@ import { sanitizeForFilename } from './utils.js'; * Generates M3U playlist content * @param {Object} playlist - Playlist metadata (title, artist, etc.) * @param {Array} tracks - Array of track objects - * @param {boolean} useRelativePaths - Whether to use relative paths - * @param {Function|null} pathResolver - Optional resolver for per-track relative path - * @param {string} audioExtension - Audio file extension used in generated paths + * @param {boolean} _useRelativePaths - Unused; kept for API compatibility + * @param {Function|null} pathResolver - Optional resolver for per-track relative path (used when trackPaths is null) + * @param {string} audioExtension - Audio file extension for generated paths (used when trackPaths is null) + * @param {Array|null} trackPaths - Actual per-track resolved paths; when provided, overrides pathResolver/audioExtension * @returns {string} M3U content */ -export function generateM3U(playlist, tracks, useRelativePaths = true, pathResolver = null, audioExtension = 'flac') { +export function generateM3U( + playlist, + tracks, + _useRelativePaths = true, + pathResolver = null, + audioExtension = 'flac', + trackPaths = null +) { let content = '#EXTM3U\n'; if (playlist.title) { @@ -17,13 +25,16 @@ export function generateM3U(playlist, tracks, useRelativePaths = true, pathResol } if (playlist.artist) { - content += `#ARTIST:${playlist.artist}\n`; + content += `#ARTIST:${playlist.artist?.name || playlist.artist}\n`; } const date = new Date().toISOString().split('T')[0]; content += `#DATE:${date}\n\n`; tracks.forEach((track, index) => { + const resolvedPath = trackPaths ? trackPaths[index] : null; + if (trackPaths && !resolvedPath) return; + const duration = Math.round(track.duration || 0); const artists = getTrackArtists(track); const title = track.title || 'Unknown Title'; @@ -31,9 +42,12 @@ export function generateM3U(playlist, tracks, useRelativePaths = true, pathResol content += `#EXTINF:${duration},${displayName}\n`; - const filename = getTrackFilename(track, index + 1, audioExtension); - const relativePath = typeof pathResolver === 'function' ? pathResolver(track, filename, index) : filename; - const path = useRelativePaths ? relativePath : relativePath; + const path = + resolvedPath ?? + (() => { + const filename = getTrackFilename(track, index + 1, audioExtension); + return typeof pathResolver === 'function' ? pathResolver(track, filename, index) : filename; + })(); content += `${path}\n\n`; }); @@ -45,12 +59,20 @@ export function generateM3U(playlist, tracks, useRelativePaths = true, pathResol * Generates M3U8 playlist content (UTF-8 extended) * @param {Object} playlist - Playlist metadata * @param {Array} tracks - Array of track objects - * @param {boolean} useRelativePaths - Whether to use relative paths - * @param {Function|null} pathResolver - Optional resolver for per-track relative path - * @param {string} audioExtension - Audio file extension used in generated paths + * @param {boolean} _useRelativePaths - Unused; kept for API compatibility + * @param {Function|null} pathResolver - Optional resolver for per-track relative path (used when trackPaths is null) + * @param {string} audioExtension - Audio file extension for generated paths (used when trackPaths is null) + * @param {Array|null} trackPaths - Actual per-track resolved paths; when provided, overrides pathResolver/audioExtension * @returns {string} M3U8 content */ -export function generateM3U8(playlist, tracks, useRelativePaths = true, pathResolver = null, audioExtension = 'flac') { +export function generateM3U8( + playlist, + tracks, + _useRelativePaths = true, + pathResolver = null, + audioExtension = 'flac', + trackPaths = null +) { let content = '#EXTM3U\n'; content += '#EXT-X-VERSION:3\n'; content += '#EXT-X-PLAYLIST-TYPE:VOD\n'; @@ -63,13 +85,16 @@ export function generateM3U8(playlist, tracks, useRelativePaths = true, pathReso } if (playlist.artist) { - content += `#ARTIST:${playlist.artist}\n`; + content += `#ARTIST:${playlist.artist?.name || playlist.artist}\n`; } const date = new Date().toISOString().split('T')[0]; content += `#DATE:${date}\n\n`; tracks.forEach((track, index) => { + const resolvedPath = trackPaths ? trackPaths[index] : null; + if (trackPaths && !resolvedPath) return; + const duration = Math.round(track.duration || 0); const artists = getTrackArtists(track); const title = track.title || 'Unknown Title'; @@ -77,9 +102,12 @@ export function generateM3U8(playlist, tracks, useRelativePaths = true, pathReso content += `#EXTINF:${duration}.000,${displayName}\n`; - const filename = getTrackFilename(track, index + 1, audioExtension); - const relativePath = typeof pathResolver === 'function' ? pathResolver(track, filename, index) : filename; - const path = useRelativePaths ? relativePath : relativePath; + const path = + resolvedPath ?? + (() => { + const filename = getTrackFilename(track, index + 1, audioExtension); + return typeof pathResolver === 'function' ? pathResolver(track, filename, index) : filename; + })(); content += `${path}\n\n`; }); @@ -92,40 +120,39 @@ export function generateM3U8(playlist, tracks, useRelativePaths = true, pathReso * Generates CUE sheet content for albums * @param {Object} album - Album metadata * @param {Array} tracks - Array of track objects - * @param {string} audioFilename - The main audio file name + * @param {string} _audioFilenameBase - Unused; kept for API compatibility + * @param {Array|null} trackPaths - Actual per-track resolved paths; when provided, each track gets its own FILE entry + * @param {string} audioExtension - Audio file extension for generated paths (used when trackPaths is null) * @returns {string} CUE content */ -export function generateCUE(album, tracks, audioFilename) { +export function generateCUE(album, tracks, _audioFilenameBase, trackPaths = null, audioExtension = 'flac') { const performer = album.artist?.name || album.artist || 'Unknown Artist'; const title = album.title || 'Unknown Album'; let content = `PERFORMER "${performer}"\n`; content += `TITLE "${title}"\n`; - // Add file reference - const fileExtension = audioFilename.split('.').pop().toUpperCase(); - content += `FILE "${audioFilename}" ${fileExtension}\n`; - - let currentTime = 0; - tracks.forEach((track, index) => { + const resolvedPath = trackPaths ? trackPaths[index] : null; + if (trackPaths && !resolvedPath) return; + const trackNumber = String(track.trackNumber || index + 1).padStart(2, '0'); const trackTitle = track.title || 'Unknown Track'; const trackPerformer = track.artist?.name || getTrackArtists(track) || performer; - const duration = track.duration || 0; + const path = + resolvedPath ?? + (() => { + const filename = getTrackFilename(track, index + 1, audioExtension); + return filename; + })(); + + const fileExtension = path.split('.').pop().toUpperCase(); + content += `FILE "${path}" ${fileExtension}\n`; content += ` TRACK ${trackNumber} AUDIO\n`; content += ` TITLE "${trackTitle}"\n`; content += ` PERFORMER "${trackPerformer}"\n`; - - // Calculate time in MM:SS:FF format (Frames = 75 per second) - const minutes = Math.floor(currentTime / 60); - const seconds = Math.floor(currentTime % 60); - const frames = Math.floor((currentTime % 1) * 75); - - content += ` INDEX 01 ${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(frames).padStart(2, '0')}\n`; - - currentTime += duration; + content += ` INDEX 01 00:00:00\n`; }); return content; diff --git a/js/playlist-importer.js b/js/playlist-importer.js index 89271f2db..08332c611 100644 --- a/js/playlist-importer.js +++ b/js/playlist-importer.js @@ -5,21 +5,21 @@ function isFuzzyMatch(str1, str2) { return s1.includes(s2) || s2.includes(s1); } -function findBestMatch(items, targetArtist, targetAlbum, options) { +function findBestMatch(items, targetArtist, targetAlbum, importOptions) { if (!items || items.length === 0) return null; - if (!options?.strictArtistMatch && !options?.albumMatch) return items[0]; + if (!importOptions?.strictArtistMatch && !importOptions?.strictAlbumMatch) return items[0]; return ( items.find((item) => { let artistOk = true; let albumOk = true; - if (options.strictArtistMatch && targetArtist) { + if (importOptions.strictArtistMatch && targetArtist) { const itemArtist = item.artist?.name || item.artists?.[0]?.name; if (!isFuzzyMatch(itemArtist, targetArtist)) artistOk = false; } - if (options.albumMatch && targetAlbum) { + if (importOptions.strictAlbumMatch && targetAlbum) { const itemAlbum = item.album?.title; if (itemAlbum && !isFuzzyMatch(itemAlbum, targetAlbum)) albumOk = false; } @@ -148,7 +148,9 @@ const HEADER_MAPPINGS = { }; function normalizeHeader(header) { + if (!header) return ''; return header + .replace(/^\uFEFF/, '') .toLowerCase() .trim() .replace(/[_\s]+/g, ' '); @@ -255,7 +257,13 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { const typeValue = values[mappedHeaders.type]?.toLowerCase().trim(); if (typeValue === 'album' || typeValue === 'favorite album') return 'album'; if (typeValue === 'artist' || typeValue === 'favorite artist') return 'artist'; - if (typeValue === 'track' || typeValue === 'favorite' || typeValue === 'favorite track') return 'track'; + if ( + typeValue === 'favorite' || + typeValue === 'favorite track' || + typeValue === 'track' || + typeValue === 'playlist' + ) + return 'track'; } const hasTrackName = mappedHeaders.track !== undefined && values[mappedHeaders.track]; @@ -263,6 +271,11 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { const hasAlbumName = mappedHeaders.album !== undefined && values[mappedHeaders.album]; if (hasTrackName && hasArtistName) return 'track'; + + if (hasTrackName && hasAlbumName && values[mappedHeaders.track] === values[mappedHeaders.album]) { + return hasArtistName ? 'track' : 'album'; + } + if (hasAlbumName && hasArtistName && !hasTrackName) return 'album'; if (hasArtistName && !hasTrackName && !hasAlbumName) return 'artist'; @@ -281,6 +294,8 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { const albumName = mappedHeaders.album !== undefined ? values[mappedHeaders.album] : ''; const isrc = mappedHeaders.isrc !== undefined ? values[mappedHeaders.isrc] : ''; const playlistName = mappedHeaders.playlistName !== undefined ? values[mappedHeaders.playlistName] : ''; + const typeValue = mappedHeaders.type !== undefined ? values[mappedHeaders.type]?.toLowerCase().trim() : ''; + const isFavorite = typeValue.includes('favorite'); if (onProgress) { onProgress({ @@ -313,6 +328,7 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { } if (foundTrack) { + if (isFavorite) foundTrack.isFavorite = true; tracks.push(foundTrack); if (playlistName) { if (!playlists[playlistName]) { @@ -341,6 +357,7 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { } if (foundAlbum) { + if (isFavorite) foundAlbum.isFavorite = true; albums.push(foundAlbum); } else { missingItems.push({ @@ -360,6 +377,7 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { } if (foundArtist) { + if (isFavorite) foundArtist.isFavorite = true; artists.push(foundArtist); } else { missingItems.push({ @@ -395,7 +413,17 @@ export async function parseDynamicCSV(csvText, api, onProgress, options = {}) { }; } -export async function importToLibrary(csvResult, db, onProgress) { +/** + * Imports CSV result to library + * @param {Object} csvResult - Result from parseDynamicCSV + * @param {Object} db - Database instance + * @param {Function} onProgress - Progress callback + * @param {Object} options - Import options + * @returns {Promise 0) { - const match = findBestMatch(searchResult.items, artistNames, albumName, options); + const match = findBestMatch(searchResult.items, artistNames, albumName, importOptions); if (match) tracks.push(match); else missingTracks.push({ title: trackTitle, artist: artistNames, album: albumName }); } else { diff --git a/js/podcasts-api.js b/js/podcasts-api.js new file mode 100644 index 000000000..ba0ee941e --- /dev/null +++ b/js/podcasts-api.js @@ -0,0 +1,255 @@ +// js/podcasts-api.js +// PodcastIndex.org API integration for Monochrome Music + +const PODCASTINDEX_API_BASE = 'https://api.podcastindex.org/api/1.0'; + +const PODCAST_API_KEY = 'YU5HMSDYBQQVYDF6QN4P'; +const PODCAST_API_SECRET = '8hCvpjSL7T$S7^5ftnf5MhqQwYUYVjM^fmUL3Ld$'; + +export class PodcastsAPI { + constructor() { + this.cache = new Map(); + this.cacheTimeout = 1000 * 60 * 5; + } + + async getAuthHeaders() { + const apiHeaderTime = Math.floor(Date.now() / 1000).toString(); + const combined = PODCAST_API_KEY + PODCAST_API_SECRET + apiHeaderTime; + const authHeader = await this.sha1(combined); + return { + 'User-Agent': 'MonochromeMusic/1.0', + 'X-Auth-Key': PODCAST_API_KEY, + 'X-Auth-Date': apiHeaderTime, + Authorization: authHeader, + }; + } + + async sha1(str) { + const encoder = new TextEncoder(); + const data = encoder.encode(str); + const hashBuffer = await crypto.subtle.digest('SHA-1', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + return hashHex; + } + + async fetchWithRetry(endpoint, options = {}) { + const url = `${PODCASTINDEX_API_BASE}${endpoint}`; + const cacheKey = url; + const cached = this.cache.get(cacheKey); + if (cached && Date.now() - cached.timestamp < this.cacheTimeout) { + return cached.data; + } + + try { + const headers = await this.getAuthHeaders(); + const response = await fetch(url, { + method: 'GET', + headers: headers, + signal: options.signal, + }); + + if (!response.ok) { + throw new Error(`Request failed with status ${response.status}`); + } + + const data = await response.json(); + this.cache.set(cacheKey, { data, timestamp: Date.now() }); + return data; + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('PodcastIndex API request failed:', error); + throw error; + } + } + + async searchPodcasts(query, options = {}) { + try { + const max = options.max || 20; + const clean = options.clean ? '&clean' : ''; + const data = await this.fetchWithRetry( + `/search/byterm?q=${encodeURIComponent(query)}&max=${max}${clean}&pretty`, + options + ); + + if (data.status !== 'true' || !data.feeds) { + return { items: [], total: 0 }; + } + + const podcasts = data.feeds.map((feed) => this.transformPodcast(feed)); + return { + items: podcasts, + total: data.count || podcasts.length, + }; + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('Podcast search failed:', error); + return { items: [], total: 0 }; + } + } + + async searchPodcastsByTitle(query, options = {}) { + try { + const max = options.max || 20; + const clean = options.clean ? '&clean' : ''; + const data = await this.fetchWithRetry( + `/search/bytitle?q=${encodeURIComponent(query)}&max=${max}${clean}&pretty`, + options + ); + + if (data.status !== 'true' || !data.feeds) { + return { items: [], total: 0 }; + } + + const podcasts = data.feeds.map((feed) => this.transformPodcast(feed)); + return { + items: podcasts, + total: data.count || podcasts.length, + }; + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('Podcast search by title failed:', error); + return { items: [], total: 0 }; + } + } + + async getPodcastById(id, options = {}) { + try { + const data = await this.fetchWithRetry(`/podcasts/byfeedid?id=${id}&pretty`, options); + + if (data.status !== 'true' || !data.feed) { + return null; + } + + return this.transformPodcastFull(data.feed); + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('Get podcast by ID failed:', error); + return null; + } + } + + async getPodcastEpisodes(id, options = {}) { + try { + const max = options.max || 50; + const offset = options.offset || 0; + const data = await this.fetchWithRetry( + `/episodes/byfeedid?id=${id}&max=${max}&offset=${offset}&pretty`, + options + ); + + if (data.status !== 'true' || !data.items) { + return { items: [], total: 0, hasMore: false }; + } + + const episodes = data.items.map((item) => this.transformEpisode(item)); + return { + items: episodes, + total: data.count || episodes.length, + hasMore: episodes.length === max, + }; + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('Get podcast episodes failed:', error); + return { items: [], total: 0, hasMore: false }; + } + } + + async getTrendingPodcasts(options = {}) { + try { + const max = options.max || 20; + const lang = options.lang || ''; + const cat = options.cat || ''; + const since = options.since || ''; + const params = new URLSearchParams({ max, pretty: '' }); + if (lang) params.append('lang', lang); + if (cat) params.append('cat', cat); + if (since) params.append('since', since); + const queryString = params.toString().replace(/&pretty=$/, ''); + const data = await this.fetchWithRetry(`/podcasts/trending?${queryString}`, options); + + if (data.status !== 'true' || !data.feeds) { + return { items: [], total: 0 }; + } + + const podcasts = data.feeds.map((feed) => this.transformPodcast(feed)); + return { + items: podcasts, + total: data.count || podcasts.length, + }; + } catch (error) { + if (error.name === 'AbortError') throw error; + console.error('Get trending podcasts failed:', error); + return { items: [], total: 0 }; + } + } + + async testAuth() { + console.log('Testing PodcastIndex auth...'); + try { + const response = await fetch(`${PODCASTINDEX_API_BASE}/hub/pubnotify?id=75075&pretty`, { + headers: await this.getAuthHeaders(), + }); + const data = await response.json(); + console.log('Test response:', data); + return data; + } catch (error) { + console.error('Auth test failed:', error); + } + } + + transformPodcast(feed) { + return { + id: feed.id?.toString() || '', + podcastGuid: feed.podcastGuid || '', + title: feed.title || 'Unknown Podcast', + author: feed.author || feed.ownerName || '', + description: feed.description || '', + image: feed.image || feed.artwork || '', + link: feed.link || '', + feedUrl: feed.url || '', + language: feed.language || '', + categories: feed.categories || {}, + explicit: feed.explicit || false, + episodeCount: feed.episodeCount || 0, + newestItemPublishTime: feed.newestItemPubdate || feed.newestItemPublishTime || null, + }; + } + + transformPodcastFull(feed) { + const podcast = this.transformPodcast(feed); + podcast.generator = feed.generator || ''; + podcast.locked = feed.locked || 0; + podcast.medium = feed.medium || ''; + podcast.dead = feed.dead || 0; + podcast.value = feed.value || null; + podcast.funding = feed.funding || null; + return podcast; + } + + transformEpisode(item) { + return { + id: item.id?.toString() || '', + title: item.title || 'Unknown Episode', + description: item.description || '', + link: item.link || '', + guid: item.guid || '', + datePublished: item.datePublished || 0, + datePublishedPretty: item.datePublishedPretty || '', + enclosureUrl: item.enclosureUrl || '', + enclosureType: item.enclosureType || '', + enclosureLength: item.enclosureLength || 0, + duration: item.duration || null, + explicit: item.explicit || 0, + episode: item.episode || null, + episodeType: item.episodeType || 'full', + season: item.season || null, + image: item.image || '', + feedId: item.feedId || null, + feedTitle: item.feedTitle || '', + feedImage: item.feedImage || '', + }; + } +} + +export const podcastsAPI = new PodcastsAPI(); diff --git a/js/profile.js b/js/profile.js index 2910c537b..eeec04f42 100644 --- a/js/profile.js +++ b/js/profile.js @@ -4,6 +4,7 @@ import { navigate } from './router.js'; import { MusicAPI } from './music-api.js'; import { apiSettings } from './storage.js'; import { debounce, escapeHtml } from './utils.js'; +import { Player } from './player.js'; // objects execution february 29th 2027 @@ -37,15 +38,23 @@ let currentFavoriteAlbums = []; const api = new MusicAPI(apiSettings); async function uploadImage(file) { - const formData = new FormData(); - formData.append('file', file); - try { - const response = await fetch('/upload', { method: 'POST', body: formData }); - if (!response.ok) throw new Error(`Upload failed: ${response.status}`); - const data = await response.json(); - if (!data.success) throw new Error(data.error || 'Upload failed'); - return data.url; + const fileNameWithoutSpace = file.name.replace(/\s/g, '_'); + const response = await fetch(`https://worker.uploads.monochrome.qzz.io/${fileNameWithoutSpace}`, { + method: 'PUT', + headers: { + 'x-api-key': 'if_youre_reading_this_fuck_off', + 'Content-Type': file.type || 'application/octet-stream', + }, + body: file, + }); + + if (!response.ok) { + if (response.status === 413) throw new Error('File exceeds 10MB'); + throw new Error(`Upload failed: ${response.status}`); + } + + return `https://images.monochrome.qzz.io/${await response.text()}`; } catch (error) { console.error('Upload error:', error); throw error; @@ -819,9 +828,9 @@ async function handleTrackClick(title, artist) { const results = await api.searchTracks(query, { limit: 1 }); if (results.items.length > 0) { const track = results.items[0]; - if (window.monochromePlayer) { - window.monochromePlayer.setQueue([track], 0); - window.monochromePlayer.playTrackFromQueue(); + if (Player.instance) { + Player.instance.setQueue([track], 0); + Player.instance.playTrackFromQueue(); } } else { alert('Track not found'); diff --git a/js/progressEvents.ts b/js/progressEvents.ts new file mode 100644 index 000000000..d3618b03c --- /dev/null +++ b/js/progressEvents.ts @@ -0,0 +1,43 @@ +declare global { + type MonochromeProgress = { + stage: string; + } & T; + + type MonochromeProgressMessage = { + message: string; + }; + + type MonochromeProgressListener = (progress: T) => void; +} + +export class DownloadProgress implements MonochromeProgress { + public readonly stage = 'downloading'; + + constructor( + public readonly receivedBytes: number, + public readonly totalBytes: number | undefined + ) {} +} + +export class SegmentedDownloadProgress extends DownloadProgress { + public readonly stage = 'downloading'; + + constructor( + public readonly receivedBytes: number, + public readonly totalBytes: number | undefined, + public readonly currentSegment: number, + public readonly totalSegments: number + ) { + super(receivedBytes, totalBytes); + } +} + +export class ProgressMessage implements MonochromeProgressMessage { + constructor(public readonly message: string) {} +} + +export class DownloadProgressMessage extends ProgressMessage { + constructor(message: string) { + super(message); + } +} diff --git a/js/qobuz-api.js b/js/qobuz-api.js deleted file mode 100644 index 23e083007..000000000 --- a/js/qobuz-api.js +++ /dev/null @@ -1,412 +0,0 @@ -// js/qobuz-api.js -// Qobuz API integration for Monochrome Music - -// LMFAOOOO this shit is useless now qobuz killing accounts every time a dude takes their breath - -const QOBUZ_API_BASE = 'https://qobuz.squid.wtf/api'; - -export class QobuzAPI { - constructor() { - this.baseUrl = QOBUZ_API_BASE; - } - - async fetchWithRetry(endpoint, options = {}) { - const url = `${this.baseUrl}${endpoint}`; - - try { - const response = await fetch(url, { signal: options.signal }); - - if (!response.ok) { - throw new Error(`Request failed with status ${response.status}`); - } - - const data = await response.json(); - return data; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz API request failed:', error); - throw error; - } - } - - // Search tracks - async searchTracks(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz tracks to match Tidal format - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track)); - - return { - items: tracks, - limit: data.data.tracks?.limit || tracks.length, - offset: data.data.tracks?.offset || 0, - totalNumberOfItems: data.data.tracks?.total || tracks.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz track search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Search albums - async searchAlbums(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz albums to match Tidal format - const albums = (data.data.albums?.items || []).map((album) => this.transformAlbum(album)); - - return { - items: albums, - limit: data.data.albums?.limit || albums.length, - offset: data.data.albums?.offset || 0, - totalNumberOfItems: data.data.albums?.total || albums.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz album search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Search artists - async searchArtists(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz artists to match Tidal format - const artists = (data.data.artists?.items || []).map((artist) => this.transformArtist(artist)); - - return { - items: artists, - limit: data.data.artists?.limit || artists.length, - offset: data.data.artists?.offset || 0, - totalNumberOfItems: data.data.artists?.total || artists.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz artist search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Get track details - async getTrack(_id) { - // Qobuz doesn't have a direct track endpoint - // Track metadata comes from search/album endpoints - // For playback, use getStreamUrl directly - throw new Error('Qobuz getTrack not implemented - use getStreamUrl for playback'); - } - - // Get album details - async getAlbum(id) { - try { - const data = await this.fetchWithRetry(`/get-album?album_id=${encodeURIComponent(id)}`); - - if (!data.success || !data.data) { - throw new Error('Album not found'); - } - - const album = this.transformAlbum(data.data); - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track, data.data)); - - return { album, tracks }; - } catch (error) { - console.error('Qobuz getAlbum failed:', error); - throw error; - } - } - - // Get artist details - async getArtist(id) { - try { - const artistData = await this.fetchWithRetry(`/get-artist?artist_id=${encodeURIComponent(id)}`); - - if (!artistData.success || !artistData.data) { - throw new Error('Artist not found'); - } - - // Qobuz get-artist returns { artist: {...} } nested structure - const artistInfo = artistData.data.artist || artistData.data; - if (!artistInfo) { - throw new Error('Artist info not found in response'); - } - const artist = this.transformArtist(artistInfo); - - // Get albums from the releases section - let albums = []; - let eps = []; - if (Array.isArray(artistData.data.releases)) { - // Find album releases - const albumReleases = artistData.data.releases.find((r) => r.type === 'album'); - if (albumReleases?.items) { - albums = albumReleases.items.map((album) => this.transformAlbum(album)); - } - // Find EP/single releases - const epReleases = artistData.data.releases.find((r) => r.type === 'epSingle'); - if (epReleases?.items) { - eps = epReleases.items.map((album) => this.transformAlbum(album)); - } - } - - // Get top tracks - let tracks = []; - if (Array.isArray(artistData.data.top_tracks)) { - tracks = artistData.data.top_tracks.map((track) => this.transformTrack(track)); - } - - return { ...artist, albums, eps, tracks }; - } catch (error) { - console.error('Qobuz getArtist failed:', error); - throw error; - } - } - - // Transform Qobuz track to Tidal-like format - transformTrack(track, albumData = null) { - // Qobuz uses 'performer' for the main artist, not 'artist' - const mainArtist = track.performer || track.artist; - const artistsList = track.artists || (mainArtist ? [mainArtist] : []); - - return { - id: `q:${track.id}`, - title: track.title, - duration: track.duration, - artist: mainArtist ? this.transformArtist(mainArtist) : null, - artists: artistsList.map((a) => this.transformArtist(a)), - album: albumData ? this.transformAlbum(albumData) : track.album ? this.transformAlbum(track.album) : null, - audioQuality: this.mapQuality(track.streaming_quality), - explicit: track.parental_warning || false, - trackNumber: track.track_number, - volumeNumber: track.media_number || 1, - isrc: track.isrc, - provider: 'qobuz', - originalId: track.id, - }; - } - - // Transform Qobuz album to Tidal-like format - transformAlbum(album) { - // Qobuz albums have artist (single) or artists (array) - const mainArtist = album.artist || album.artists?.[0]; - return { - id: `q:${album.id}`, - title: album.title, - artist: mainArtist ? this.transformArtist(mainArtist) : null, - artists: album.artists - ? album.artists.map((a) => this.transformArtist(a)) - : mainArtist - ? [this.transformArtist(mainArtist)] - : [], - numberOfTracks: album.tracks_count || 0, - releaseDate: album.release_date_original || album.release_date, - cover: album.image?.large || album.image?.medium || album.image?.small, - explicit: album.parental_warning || false, - type: album.album_type === 'ep' ? 'EP' : album.album_type === 'single' ? 'SINGLE' : 'ALBUM', - provider: 'qobuz', - originalId: album.id, - }; - } - - // Transform Qobuz artist to Tidal-like format - transformArtist(artist) { - if (!artist) { - return { - id: 'q:unknown', - name: 'Unknown Artist', - picture: null, - provider: 'qobuz', - originalId: null, - }; - } - // Handle different name structures: string or { display: string } - const name = typeof artist.name === 'string' ? artist.name : artist.name?.display || 'Unknown Artist'; - // Handle different image structures: image object or picture string or images.portrait - const picture = - artist.image?.large || - artist.image?.medium || - artist.image?.small || - artist.picture || - (artist.images?.portrait - ? `https://static.qobuz.com/images/artists/covers/large/${artist.images.portrait.hash}.${artist.images.portrait.format}` - : null); - return { - id: `q:${artist.id}`, - name: name, - picture: picture, - provider: 'qobuz', - originalId: artist.id, - }; - } - - // Map Qobuz quality to Tidal quality format - mapQuality(qobuzQuality) { - const qualityMap = { - MP3: 'HIGH', - FLAC: 'LOSSLESS', - HiRes: 'HI_RES_LOSSLESS', - }; - return qualityMap[qobuzQuality] || 'LOSSLESS'; - } - - // Get cover URL - getCoverUrl(coverId, size = '320') { - if (!coverId) { - return `https://picsum.photos/seed/${Math.random()}/${size}`; - } - - // Qobuz cover URLs are usually full URLs - if (typeof coverId === 'string' && coverId.startsWith('http')) { - return coverId; - } - - return coverId; - } - - // Get artist picture URL - getArtistPictureUrl(pictureUrl, size = '320') { - if (!pictureUrl) { - return `https://picsum.photos/seed/${Math.random()}/${size}`; - } - - // Qobuz picture URLs are usually full URLs - if (typeof pictureUrl === 'string' && pictureUrl.startsWith('http')) { - return pictureUrl; - } - - return pictureUrl; - } - - // Get stream URL for a track - async getStreamUrl(trackId, quality = '27') { - try { - const cleanId = trackId.replace(/^q:/, ''); - // Map Tidal quality format to Qobuz quality values - // Qobuz: 27=MP3 320kbps, 7=FLAC lossless, 6=HiRes 96/24, 5=HiRes 192/24 - const qualityMap = { - LOW: '27', - HIGH: '27', - LOSSLESS: '7', - HI_RES: '6', - HI_RES_LOSSLESS: '5', - }; - const qobuzQuality = qualityMap[quality] || quality || '27'; - const data = await this.fetchWithRetry( - `/download-music?track_id=${encodeURIComponent(cleanId)}&quality=${qobuzQuality}` - ); - - if (!data.success || !data.data?.url) { - throw new Error('Stream URL not available'); - } - - return data.data.url; - } catch (error) { - console.error('Qobuz getStreamUrl failed:', error); - throw error; - } - } - - // Similar/recommendation methods - async getSimilarArtists(_artistId) { - // Qobuz doesn't have a direct similar artists endpoint in this simplified API - return []; - } - - async getSimilarAlbums(_albumId) { - // Qobuz doesn't have a direct similar albums endpoint in this simplified API - return []; - } - - // Unified search - search all types at once - async search(query, options = {}) { - const offset = options.offset || 0; - const limit = options.limit || 10; - - try { - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { - tracks: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - albums: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - artists: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - }; - } - - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track)); - const albums = (data.data.albums?.items || []).map((album) => this.transformAlbum(album)); - const artists = (data.data.artists?.items || []).map((artist) => this.transformArtist(artist)); - - return { - tracks: { - items: tracks, - limit: data.data.tracks?.limit || tracks.length, - offset: data.data.tracks?.offset || 0, - totalNumberOfItems: data.data.tracks?.total || tracks.length, - }, - albums: { - items: albums, - limit: data.data.albums?.limit || albums.length, - offset: data.data.albums?.offset || 0, - totalNumberOfItems: data.data.albums?.total || albums.length, - }, - artists: { - items: artists, - limit: data.data.artists?.limit || artists.length, - offset: data.data.artists?.offset || 0, - totalNumberOfItems: data.data.artists?.total || artists.length, - }, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz search failed:', error); - return { - tracks: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - albums: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - artists: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - }; - } - } - - // Get next page helper - getNextPage(currentOffset, limit, total) { - const nextOffset = currentOffset + limit; - return nextOffset < total ? nextOffset : null; - } - - // Get previous page helper - getPreviousPage(currentOffset, limit) { - const prevOffset = currentOffset - limit; - return prevOffset >= 0 ? prevOffset : null; - } -} - -export const qobuzAPI = new QobuzAPI(); diff --git a/js/readableStreamIterator.ts b/js/readableStreamIterator.ts new file mode 100644 index 000000000..fe3880266 --- /dev/null +++ b/js/readableStreamIterator.ts @@ -0,0 +1,28 @@ +/** + * Converts a ReadableStream into an async iterable iterator. + * @template T The type of data chunks yielded from the stream. + * @param stream The ReadableStream to convert into an async iterable. + * @yields Chunks of data from the stream as they become available. + * @example + * ```typescript + * const response = await fetch('https://example.com/data'); + * for await (const chunk of readableStreamIterator(response.body)) { + * console.log(chunk); + * } + * ``` + */ +export async function* readableStreamIterator(stream: ReadableStream): AsyncIterableIterator { + const reader = stream.getReader(); + + while (true) { + const { value, done } = await reader.read(); + + if (value) { + yield value; + } + + if (done) { + break; + } + } +} diff --git a/js/router.js b/js/router.js index 708557f69..e273e9a25 100644 --- a/js/router.js +++ b/js/router.js @@ -31,14 +31,11 @@ export function createRouter(ui) { const param = parts.slice(1).join('/'); // Helper to extract provider prefix and ID from params - // Supports formats like: /track/t/123 (Tidal), /track/q/123 (Qobuz), /track/123 (default) + // Supports formats like: /track/t/123 (Tidal), /track/123 (default) const extractProviderAndId = (p) => { if (p.startsWith('t/')) { return { provider: 'tidal', id: p.slice(2) }; } - if (p.startsWith('q/')) { - return { provider: 'qobuz', id: p.slice(2) }; - } return { provider: null, id: p }; }; @@ -101,9 +98,19 @@ export function createRouter(ui) { await ui.renderUnreleasedPage(); } break; + case 'podcasts': + if (param) { + await ui.renderPodcastPage(param); + } else { + await ui.renderPodcastsBrowsePage(); + } + break; case 'home': await ui.renderHomePage(); break; + case 'donate': + ui.showPage('donate'); + break; case 'user': if (param && param.startsWith('@') && !param.includes('/')) { await loadProfile(decodeURIComponent(param.slice(1))); diff --git a/js/settings.js b/js/settings.js index c46d354d0..ceea10df5 100644 --- a/js/settings.js +++ b/js/settings.js @@ -10,14 +10,12 @@ import { cardSettings, waveformSettings, replayGainSettings, - smoothScrollingSettings, downloadQualitySettings, losslessContainerSettings, coverArtSizeSettings, qualityBadgeSettings, trackDateSettings, visualizerSettings, - bulkDownloadSettings, playlistSettings, equalizerSettings, listenBrainzSettings, @@ -33,11 +31,11 @@ import { pwaUpdateSettings, contentBlockingSettings, musicProviderSettings, + gaplessPlaybackSettings, analyticsSettings, modalSettings, } from './storage.js'; import { audioContextManager, EQ_PRESETS } from './audio-context.js'; -import { getButterchurnPresets } from './visualizers/butterchurn.js'; import { db } from './db.js'; import { authManager } from './accounts/auth.js'; import { syncManager } from './accounts/pocketbase.js'; @@ -45,7 +43,12 @@ import { saveFirebaseConfig, clearFirebaseConfig } from './accounts/config.js'; import { Share } from '@capacitor/share'; import { Filesystem, Directory } from '@capacitor/filesystem'; -export function initializeSettings(scrobbler, player, api, ui) { +async function getButterchurnPresets(...args) { + const butterchurnModule = await import('./visualizers/butterchurn.js'); + return butterchurnModule.getButterchurnPresets(...args); +} + +export async function initializeSettings(scrobbler, player, api, ui) { // Restore last active settings tab const savedTab = settingsUiState.getActiveTab(); const settingsTab = document.querySelector(`.settings-tab[data-tab="${savedTab}"]`); @@ -61,7 +64,7 @@ export function initializeSettings(scrobbler, player, api, ui) { // Email Auth UI Logic const toggleEmailBtn = document.getElementById('toggle-email-auth-btn'); - const cancelEmailBtn = document.getElementById('cancel-email-auth-btn'); + const authModalCloseBtn = document.getElementById('email-auth-modal-close'); const authModal = document.getElementById('email-auth-modal'); const emailInput = document.getElementById('auth-email'); const passwordInput = document.getElementById('auth-password'); @@ -75,14 +78,10 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } - if (cancelEmailBtn && authModal) { - cancelEmailBtn.addEventListener('click', () => { - authModal.classList.remove('active'); - }); - - authModal.querySelector('.modal-overlay').addEventListener('click', () => { - authModal.classList.remove('active'); - }); + if (authModal) { + const closeAuthModal = () => authModal.classList.remove('active'); + authModalCloseBtn?.addEventListener('click', closeAuthModal); + authModal.querySelector('.modal-overlay')?.addEventListener('click', closeAuthModal); } if (signInBtn) { @@ -465,6 +464,8 @@ export function initializeSettings(scrobbler, player, api, ui) { const lbToggle = document.getElementById('listenbrainz-enabled-toggle'); const lbTokenSetting = document.getElementById('listenbrainz-token-setting'); const lbCustomUrlSetting = document.getElementById('listenbrainz-custom-url-setting'); + const lbLoveSetting = document.getElementById('listenbrainz-love-setting'); + const lbLoveToggle = document.getElementById('listenbrainz-love-toggle'); const lbTokenInput = document.getElementById('listenbrainz-token-input'); const lbCustomUrlInput = document.getElementById('listenbrainz-custom-url-input'); @@ -473,8 +474,10 @@ export function initializeSettings(scrobbler, player, api, ui) { if (lbToggle) lbToggle.checked = isEnabled; if (lbTokenSetting) lbTokenSetting.style.display = isEnabled ? 'flex' : 'none'; if (lbCustomUrlSetting) lbCustomUrlSetting.style.display = isEnabled ? 'flex' : 'none'; + if (lbLoveSetting) lbLoveSetting.style.display = isEnabled ? 'flex' : 'none'; if (lbTokenInput) lbTokenInput.value = listenBrainzSettings.getToken(); if (lbCustomUrlInput) lbCustomUrlInput.value = listenBrainzSettings.getCustomUrl(); + if (lbLoveToggle) lbLoveToggle.checked = listenBrainzSettings.shouldLoveOnLike(); }; updateListenBrainzUI(); @@ -499,6 +502,12 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } + if (lbLoveToggle) { + lbLoveToggle.addEventListener('change', (e) => { + listenBrainzSettings.setLoveOnLike(e.target.checked); + }); + } + // ======================================== // Maloja Settings // ======================================== @@ -788,29 +797,129 @@ export function initializeSettings(scrobbler, player, api, ui) { // Streaming Quality setting const streamingQualitySetting = document.getElementById('streaming-quality-setting'); if (streamingQualitySetting) { - const savedQuality = localStorage.getItem('playback-quality') || 'HI_RES_LOSSLESS'; - streamingQualitySetting.value = savedQuality; - player.setQuality(savedQuality); + const savedAdaptiveQuality = localStorage.getItem('adaptive-playback-quality') || 'auto'; + + // Map the stored auto state to the dropdown, or if it doesn't match an option, use the playback-quality value + const optionExists = Array.from(streamingQualitySetting.options).some( + (opt) => opt.value === savedAdaptiveQuality + ); + streamingQualitySetting.value = optionExists + ? savedAdaptiveQuality + : localStorage.getItem('playback-quality') || 'auto'; + + // Apply initially + if (player.forceQuality) player.forceQuality(streamingQualitySetting.value); + const apiQuality = streamingQualitySetting.value === 'auto' ? 'HI_RES_LOSSLESS' : streamingQualitySetting.value; + player.setQuality(localStorage.getItem('playback-quality') || apiQuality); streamingQualitySetting.addEventListener('change', (e) => { - const newQuality = e.target.value; - player.setQuality(newQuality); - localStorage.setItem('playback-quality', newQuality); + const val = e.target.value; + + // Set adaptive DASH quality + localStorage.setItem('adaptive-playback-quality', val); + if (player.forceQuality) player.forceQuality(val); + + // Set fallback API quality + const newApiQuality = val === 'auto' ? 'HI_RES_LOSSLESS' : val; + player.setQuality(newApiQuality); + localStorage.setItem('playback-quality', newApiQuality); }); } // Download Quality setting const downloadQualitySetting = document.getElementById('download-quality-setting'); if (downloadQualitySetting) { + // Assign categories to the static (native) options already in the HTML + const staticCategories = { + DOLBY_ATMOS: 'Spatial', + HI_RES_LOSSLESS: 'Lossless', + LOSSLESS: 'Lossless', + HIGH: 'AAC', + LOW: 'AAC', + }; + + // Collect static options first (preserving their original order) + const allOptions = Array.from(downloadQualitySetting.options).map((opt) => ({ + value: opt.value, + text: opt.textContent, + category: staticCategories[opt.value] || 'Other', + })); + + // Append custom (ffmpeg-transcoded) format options + for (const [key, fmt] of Object.entries(customFormats)) { + allOptions.push({ value: key, text: fmt.displayName, category: fmt.category }); + } + + // Sort by category order first, then by bitrate descending within each category + // so higher-quality options always appear before lower-quality ones. + // Options without an explicit kbps value (lossless) use Infinity so they + // sort to the top; ties fall back to display-name descending. + const getBitrate = (text) => { + const m = text.match(/(\d+)\s*kbps/i); + return m ? parseInt(m[1], 10) : Infinity; + }; + const categoryOrder = ['Spatial', 'Lossless', 'AAC', 'MP3', 'OGG']; + allOptions.sort((a, b) => { + if (a.category == b.category && a.category === 'Lossless') return 0; // Preserve original order for lossless options + const ai = categoryOrder.indexOf(a.category); + const bi = categoryOrder.indexOf(b.category); + const categoryDiff = (ai === -1 ? categoryOrder.length : ai) - (bi === -1 ? categoryOrder.length : bi); + if (categoryDiff !== 0) return categoryDiff; + const bitrateA = getBitrate(a.text); + const bitrateB = getBitrate(b.text); + if (bitrateA !== bitrateB) return bitrateB - bitrateA; + return b.text.localeCompare(a.text); + }); + + // Rebuild the select with optgroup elements per category + downloadQualitySetting.innerHTML = ''; + let currentGroup = null; + let currentCategory = null; + for (const opt of allOptions) { + if (opt.category !== currentCategory) { + currentCategory = opt.category; + currentGroup = document.createElement('optgroup'); + currentGroup.label = opt.category; + downloadQualitySetting.appendChild(currentGroup); + } + const option = document.createElement('option'); + option.value = opt.value; + option.textContent = opt.text; + currentGroup.appendChild(option); + } + downloadQualitySetting.value = downloadQualitySettings.getQuality(); downloadQualitySetting.addEventListener('change', (e) => { downloadQualitySettings.setQuality(e.target.value); + updateLosslessContainerVisibility(); }); } const losslessContainerSetting = document.getElementById('lossless-container-setting'); + const losslessContainerSettingItem = losslessContainerSetting?.closest('.setting-item'); + + /** Shows/hides the Lossless Container setting based on the selected quality */ + function updateLosslessContainerVisibility() { + if (!losslessContainerSettingItem) return; + const quality = downloadQualitySettings.getQuality(); + const isLossless = quality === 'LOSSLESS' || quality === 'HI_RES_LOSSLESS'; + losslessContainerSettingItem.style.display = isLossless ? '' : 'none'; + } + if (losslessContainerSetting) { + const noChangeOption = losslessContainerSetting.querySelector('option:last-child'); + noChangeOption.remove(); + + for (const [internalName, { displayName }] of Object.entries(containerFormats)) { + const option = document.createElement('option'); + option.value = internalName; + option.textContent = displayName; + losslessContainerSetting.appendChild(option); + } + + losslessContainerSetting.append(noChangeOption); + losslessContainerSetting.value = losslessContainerSettings.getContainer(); losslessContainerSetting.addEventListener('change', (e) => { @@ -818,6 +927,8 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } + updateLosslessContainerVisibility(); + // Cover Art Size setting const coverArtSizeSetting = document.getElementById('cover-art-size-setting'); if (coverArtSizeSetting) { @@ -848,11 +959,177 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } - const zippedBulkDownloadsToggle = document.getElementById('zipped-bulk-downloads-toggle'); - if (zippedBulkDownloadsToggle) { - zippedBulkDownloadsToggle.checked = !bulkDownloadSettings.shouldForceIndividual(); - zippedBulkDownloadsToggle.addEventListener('change', (e) => { - bulkDownloadSettings.setForceIndividual(!e.target.checked); + const forceZipBlobToggle = document.getElementById('force-zip-blob-toggle'); + const forceZipBlobSettingItem = forceZipBlobToggle?.closest('.setting-item'); + const hasFileSystemAccess = + 'showSaveFilePicker' in window && + typeof FileSystemFileHandle !== 'undefined' && + 'createWritable' in FileSystemFileHandle.prototype; + const hasFolderPicker = 'showDirectoryPicker' in window; + + const rememberFolderSetting = document.getElementById('remember-folder-setting'); + const rememberFolderToggle = document.getElementById('remember-folder-toggle'); + const resetSavedFolderSetting = document.getElementById('reset-saved-folder-setting'); + const resetSavedFolderBtn = document.getElementById('reset-saved-folder-btn'); + const singleToFolderSetting = document.getElementById('single-to-folder-setting'); + const singleToFolderToggle = document.getElementById('single-to-folder-toggle'); + + /** Shows/hides the Force ZIP as Blob setting based on method and browser support */ + function updateForceZipBlobVisibility() { + if (!forceZipBlobSettingItem) return; + const method = modernSettings.bulkDownloadMethod; + // Only relevant when zip method is selected and the browser supports streaming + const visible = method === 'zip' && hasFileSystemAccess; + forceZipBlobSettingItem.style.display = visible ? '' : 'none'; + } + + /** Shows/hides folder-picker-specific and folder-method settings */ + async function updateFolderMethodVisibility() { + const method = modernSettings.bulkDownloadMethod; + const isFolderMethod = method === 'folder'; + const isFolderOrLocal = isFolderMethod || method === 'local'; + + if (rememberFolderSetting) { + rememberFolderSetting.style.display = isFolderMethod && hasFolderPicker ? '' : 'none'; + } + + // Reset button: only visible when folder method + remember enabled + valid saved handle exists + if (resetSavedFolderSetting) { + let showReset = false; + if (isFolderMethod && hasFolderPicker && modernSettings.rememberBulkDownloadFolder) { + const savedHandle = await db.getSetting('bulk_download_folder_handle'); + showReset = !!savedHandle; + } + resetSavedFolderSetting.style.display = showReset ? '' : 'none'; + } + + if (singleToFolderSetting) { + singleToFolderSetting.style.display = isFolderOrLocal ? '' : 'none'; + } + } + + const bulkDownloadMethod = document.getElementById('bulk-download-method'); + if (bulkDownloadMethod) { + // Remove the folder picker option if the browser doesn't support it + if (!hasFolderPicker) { + const folderOption = bulkDownloadMethod.querySelector('option[value="folder"]'); + if (folderOption) { + folderOption.remove(); + } + const localOption = bulkDownloadMethod.querySelector('option[value="local"]'); + if (localOption) { + localOption.remove(); + } + // If the stored method is 'folder' or 'local' without native support, fall back to 'zip' + const currentMethod = modernSettings.bulkDownloadMethod; + if (currentMethod === 'folder' || currentMethod === 'local') { + modernSettings.bulkDownloadMethod = 'zip'; + } + } + bulkDownloadMethod.value = modernSettings.bulkDownloadMethod; + bulkDownloadMethod.addEventListener('change', async (e) => { + const previousMethod = modernSettings.bulkDownloadMethod; + const newMethod = e.target.value; + modernSettings.bulkDownloadMethod = newMethod; + + // When switching to 'local', prompt to select the local media folder if not yet configured + if (newMethod === 'local') { + const existingHandle = await db.getSetting('local_folder_handle'); + if (!existingHandle) { + let picked = false; + try { + const isNeutralino = + window.Neutralino && (window.NL_MODE || window.location.search.includes('mode=neutralino')); + if (isNeutralino) { + const path = await window.Neutralino.os.showFolderDialog('Select Local Media Folder'); + if (path) { + picked = true; + const handle = { + name: path.split(/[/\\]/).pop() || path, + isNeutralino: true, + path, + }; + await db.saveSetting('local_folder_handle', handle); + } + } else if (hasFolderPicker) { + const handle = await window.showDirectoryPicker({ mode: 'readwrite' }); + if (handle) { + picked = true; + await db.saveSetting('local_folder_handle', handle); + } + } + } catch { + // User cancelled the picker + } + + if (!picked) { + // Revert to the previous method since no folder was selected. + // Guard against the edge case where the previousMethod option + // no longer exists in the dropdown (e.g. removed due to no API support). + if (bulkDownloadMethod.querySelector(`option[value="${previousMethod}"]`)) { + modernSettings.bulkDownloadMethod = previousMethod; + bulkDownloadMethod.value = previousMethod; + } else { + // Fall back to zip which is always present + modernSettings.bulkDownloadMethod = 'zip'; + bulkDownloadMethod.value = 'zip'; + } + } + } + } + await modernSettings.waitPending(); + + updateForceZipBlobVisibility(); + await updateFolderMethodVisibility(); + }); + } + + if (rememberFolderToggle) { + rememberFolderToggle.checked = modernSettings.rememberBulkDownloadFolder; + rememberFolderToggle.addEventListener('change', async (e) => { + modernSettings.rememberBulkDownloadFolder = !!e.target.checked; + await modernSettings.waitPending(); + await updateFolderMethodVisibility(); + }); + } + + if (resetSavedFolderBtn) { + resetSavedFolderBtn.addEventListener('click', async () => { + await db.saveSetting('bulk_download_folder_handle', null); + await updateFolderMethodVisibility(); + }); + } + + if (singleToFolderToggle) { + singleToFolderToggle.checked = modernSettings.downloadSinglesToFolder; + singleToFolderToggle.addEventListener('change', (e) => { + modernSettings.downloadSinglesToFolder = !!e.target.checked; + }); + } + + if (forceZipBlobToggle) { + forceZipBlobToggle.checked = modernSettings.forceZipBlob; + forceZipBlobToggle.addEventListener('change', (e) => { + modernSettings.forceZipBlob = !!e.target.checked; + }); + } + + updateForceZipBlobVisibility(); + updateFolderMethodVisibility(); + + const includeCoverToggle = document.getElementById('include-cover-toggle'); + if (includeCoverToggle) { + includeCoverToggle.checked = playlistSettings.shouldIncludeCover(); + includeCoverToggle.addEventListener('change', (e) => { + playlistSettings.setIncludeCover(e.target.checked); + }); + } + + const gaplessPlaybackToggle = document.getElementById('gapless-playback-toggle'); + if (gaplessPlaybackToggle) { + gaplessPlaybackToggle.checked = gaplessPlaybackSettings.isEnabled(); + gaplessPlaybackToggle.addEventListener('change', (e) => { + gaplessPlaybackSettings.setEnabled(e.target.checked); }); } @@ -2108,17 +2385,6 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } - // Smooth Scrolling Toggle - const smoothScrollingToggle = document.getElementById('smooth-scrolling-toggle'); - if (smoothScrollingToggle) { - smoothScrollingToggle.checked = smoothScrollingSettings.isEnabled(); - smoothScrollingToggle.addEventListener('change', (e) => { - smoothScrollingSettings.setEnabled(e.target.checked); - - window.dispatchEvent(new CustomEvent('smooth-scrolling-toggle', { detail: { enabled: e.target.checked } })); - }); - } - // Visualizer Sensitivity const visualizerSensitivitySlider = document.getElementById('visualizer-sensitivity-slider'); const visualizerSensitivityValue = document.getElementById('visualizer-sensitivity-value'); @@ -2188,7 +2454,7 @@ export function initializeSettings(scrobbler, player, api, ui) { const butterchurnDurationInput = document.getElementById('butterchurn-duration-input'); const butterchurnRandomizeToggle = document.getElementById('butterchurn-randomize-toggle'); - const updateButterchurnSettingsVisibility = () => { + const updateButterchurnSettingsVisibility = async () => { const isEnabled = visualizerEnabledToggle ? visualizerEnabledToggle.checked : false; const isButterchurn = visualizerPresetSelect ? visualizerPresetSelect.value === 'butterchurn' : false; const show = isEnabled && isButterchurn; @@ -2204,7 +2470,7 @@ export function initializeSettings(scrobbler, player, api, ui) { if (butterchurnRandomizeSetting) butterchurnRandomizeSetting.style.display = showSubSettings ? 'flex' : 'none'; // Populate preset list using module-level cache (works even before visualizer initializes) - const { keys: presetNames } = getButterchurnPresets(); + const { keys: presetNames } = await getButterchurnPresets(); const select = butterchurnSpecificPresetSelect; if (select && presetNames.length > 0) { @@ -2239,7 +2505,7 @@ export function initializeSettings(scrobbler, player, api, ui) { } }; - const updateVisualizerSettingsVisibility = (enabled) => { + const updateVisualizerSettingsVisibility = async (enabled) => { const display = enabled ? 'flex' : 'none'; if (visualizerModeSetting) visualizerModeSetting.style.display = display; if (visualizerSmartIntensitySetting) visualizerSmartIntensitySetting.style.display = display; @@ -2247,7 +2513,7 @@ export function initializeSettings(scrobbler, player, api, ui) { if (visualizerPresetSetting) visualizerPresetSetting.style.display = display; // Also update Butterchurn specific visibility - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }; // Initialize preset select value early so visibility logic works correctly on load @@ -2258,24 +2524,24 @@ export function initializeSettings(scrobbler, player, api, ui) { if (visualizerEnabledToggle) { visualizerEnabledToggle.checked = visualizerSettings.isEnabled(); - updateVisualizerSettingsVisibility(visualizerEnabledToggle.checked); + await updateVisualizerSettingsVisibility(visualizerEnabledToggle.checked); - visualizerEnabledToggle.addEventListener('change', (e) => { + visualizerEnabledToggle.addEventListener('change', async (e) => { visualizerSettings.setEnabled(e.target.checked); - updateVisualizerSettingsVisibility(e.target.checked); + await updateVisualizerSettingsVisibility(e.target.checked); }); } // Visualizer Preset Select if (visualizerPresetSelect) { // value set above - visualizerPresetSelect.addEventListener('change', (e) => { + visualizerPresetSelect.addEventListener('change', async (e) => { const val = e.target.value; visualizerSettings.setPreset(val); if (ui && ui.visualizer) { ui.visualizer.setPreset(val); } - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); //Since changing the preset breaks the visualizer, a location.reload() is added to make sure that it works window.location.reload(); @@ -2284,9 +2550,9 @@ export function initializeSettings(scrobbler, player, api, ui) { if (butterchurnCycleToggle) { butterchurnCycleToggle.checked = visualizerSettings.isButterchurnCycleEnabled(); - butterchurnCycleToggle.addEventListener('change', (e) => { + butterchurnCycleToggle.addEventListener('change', async (e) => { visualizerSettings.setButterchurnCycleEnabled(e.target.checked); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }); } @@ -2318,30 +2584,30 @@ export function initializeSettings(scrobbler, player, api, ui) { } // Refresh settings when presets are loaded asynchronously - window.addEventListener('butterchurn-presets-loaded', () => { + window.addEventListener('butterchurn-presets-loaded', async () => { console.log('[Settings] Butterchurn presets loaded event received'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }); // Check if presets already cached and update immediately - const { keys: cachedKeys } = getButterchurnPresets(); + const { keys: cachedKeys } = await getButterchurnPresets(); if (cachedKeys.length > 0) { console.log('[Settings] Presets already cached, updating dropdown immediately'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); } // Watch for appearance tab becoming active and refresh presets const appearanceTabContent = document.getElementById('settings-tab-appearance'); if (appearanceTabContent) { - const observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { + const observer = new MutationObserver(async (mutations) => { + for (const mutation of mutations) { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { if (appearanceTabContent.classList.contains('active')) { console.log('[Settings] Appearance tab became active, refreshing presets'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); } } - }); + } }); observer.observe(appearanceTabContent, { attributes: true }); } @@ -2466,15 +2732,6 @@ export function initializeSettings(scrobbler, player, api, ui) { }); } - const sidebarShowDownloadToggle = document.getElementById('sidebar-show-download-bottom-toggle'); - if (sidebarShowDownloadToggle) { - sidebarShowDownloadToggle.checked = sidebarSectionSettings.shouldShowDownload(); - sidebarShowDownloadToggle.addEventListener('change', (e) => { - sidebarSectionSettings.setShowDownload(e.target.checked); - sidebarSectionSettings.applySidebarVisibility(); - }); - } - const sidebarShowDiscordToggle = document.getElementById('sidebar-show-discordbtn-toggle'); if (sidebarShowDiscordToggle) { sidebarShowDiscordToggle.checked = sidebarSectionSettings.shouldShowDiscord(); @@ -2608,18 +2865,18 @@ export function initializeSettings(scrobbler, player, api, ui) { // Filename template setting const filenameTemplate = document.getElementById('filename-template'); if (filenameTemplate) { - filenameTemplate.value = localStorage.getItem('filename-template') || '{trackNumber} - {artist} - {title}'; + filenameTemplate.value = modernSettings.filenameTemplate; filenameTemplate.addEventListener('change', (e) => { - localStorage.setItem('filename-template', e.target.value); + modernSettings.filenameTemplate = String(e.target.value); }); } // ZIP folder template const zipFolderTemplate = document.getElementById('zip-folder-template'); if (zipFolderTemplate) { - zipFolderTemplate.value = localStorage.getItem('zip-folder-template') || '{albumTitle} - {albumArtist}'; + zipFolderTemplate.value = modernSettings.folderTemplate; zipFolderTemplate.addEventListener('change', (e) => { - localStorage.setItem('zip-folder-template', e.target.value); + modernSettings.folderTemplate = String(e.target.value); }); } @@ -2710,8 +2967,32 @@ export function initializeSettings(scrobbler, player, api, ui) { if (!button) return; const li = button.closest('li'); - const index = parseInt(li.dataset.index, 10); - const type = li.dataset.type || 'api'; // Default to api if not present + const type = button.dataset.type || li?.dataset.type || 'api'; + + if (button.classList.contains('add-instance')) { + const url = prompt(`Enter custom ${type.toUpperCase()} instance URL (e.g. https://my-instance.com):`); + if (url && url.trim()) { + let formattedUrl = url.trim(); + if (!formattedUrl.startsWith('http')) { + formattedUrl = 'https://' + formattedUrl; + } + api.settings.addUserInstance(type, formattedUrl); + ui.renderApiSettings(); + } + return; + } + + if (button.classList.contains('delete-instance')) { + const url = li.dataset.url; + if (url && confirm(`Delete custom instance ${url}?`)) { + api.settings.removeUserInstance(type, url); + ui.renderApiSettings(); + } + return; + } + + const index = parseInt(li?.dataset.index, 10); + if (isNaN(index)) return; const instances = await api.settings.getInstances(type); @@ -3014,7 +3295,20 @@ export function initializeSettings(scrobbler, player, api, ui) { // Clear IndexedDB - try to clear individual stores, fallback to deleting database try { - const stores = ['tracks', 'albums', 'artists', 'playlists', 'settings', 'history']; + const stores = [ + 'favorites_tracks', + 'favorites_videos', + 'favorites_albums', + 'favorites_artists', + 'favorites_playlists', + 'favorites_mixes', + 'history_tracks', + 'user_playlists', + 'user_folders', + 'settings', + 'pinned_items', + ]; + for (const storeName of stores) { try { await db.performTransaction(storeName, 'readwrite', (store) => store.clear()); @@ -3026,7 +3320,7 @@ export function initializeSettings(scrobbler, player, api, ui) { console.log('Could not clear IndexedDB stores:', dbError); // Try to delete the entire database as fallback try { - const deleteRequest = indexedDB.deleteDatabase('monochromeDB'); + const deleteRequest = indexedDB.deleteDatabase('MonochromeDB'); await new Promise((resolve, reject) => { deleteRequest.onsuccess = resolve; deleteRequest.onerror = reject; diff --git a/js/side-panel.js b/js/side-panel.js index 323e85fff..c3b6d8f31 100644 --- a/js/side-panel.js +++ b/js/side-panel.js @@ -6,7 +6,64 @@ export class SidePanelManager { this.titleElement = document.getElementById('side-panel-title'); this.controlsElement = document.getElementById('side-panel-controls'); this.contentElement = document.getElementById('side-panel-content'); + this.resizerElement = document.getElementById('side-panel-resizer'); this.currentView = null; // 'queue' or 'lyrics' + this.isResizing = false; + + if (this.resizerElement) { + this.initResizer(); + } + } + + initResizer() { + this.resizerElement.addEventListener('mousedown', this.startResize.bind(this)); + + // Restore saved width if available + const savedWidth = localStorage.getItem('side-panel-width'); + if (savedWidth) { + this.panel.style.setProperty('--side-panel-width', savedWidth + 'px'); + } + } + + startResize(e) { + e.preventDefault(); + this.isResizing = true; + this.panel.style.transition = 'none'; // Disable transition for smooth resizing + document.body.style.cursor = 'ew-resize'; + + this.resizeBind = this.resize.bind(this); + this.stopResizeBind = this.stopResize.bind(this); + + document.addEventListener('mousemove', this.resizeBind); + document.addEventListener('mouseup', this.stopResizeBind); + } + + resize(e) { + if (!this.isResizing) return; + // The panel is on the right side. Screen width - mouse X = desired width. + const minWidth = 300; + const maxWidth = window.innerWidth * 0.9; + let newWidth = window.innerWidth - e.clientX; + + if (newWidth < minWidth) newWidth = minWidth; + if (newWidth > maxWidth) newWidth = maxWidth; + + this.panel.style.setProperty('--side-panel-width', `${newWidth}px`); + } + + stopResize() { + this.isResizing = false; + this.panel.style.transition = ''; // Restore transitions + document.body.style.cursor = ''; + + document.removeEventListener('mousemove', this.resizeBind); + document.removeEventListener('mouseup', this.stopResizeBind); + + // Save the width + const currentWidth = this.panel.style.getPropertyValue('--side-panel-width').replace('px', ''); + if (currentWidth) { + localStorage.setItem('side-panel-width', currentWidth); + } } open(view, title, renderControlsCallback, renderContentCallback, forceOpen = false) { diff --git a/js/smooth-scrolling.js b/js/smooth-scrolling.js deleted file mode 100644 index 8407c7830..000000000 --- a/js/smooth-scrolling.js +++ /dev/null @@ -1,100 +0,0 @@ -//js/smooth-scrolling.js -import { smoothScrollingSettings } from './storage.js'; - -let lenis = null; -let lenisLoaded = false; -let lenisLoading = false; - -async function loadLenisScript() { - if (lenisLoaded) return true; - if (lenisLoading) { - return new Promise((resolve) => { - const checkLoaded = setInterval(() => { - if (!lenisLoading) { - clearInterval(checkLoaded); - resolve(lenisLoaded); - } - }, 100); - }); - } - - lenisLoading = true; - - try { - await new Promise((resolve, reject) => { - const script = document.createElement('script'); - script.src = 'https://unpkg.com/@studio-freight/lenis'; - script.onload = resolve; - script.onerror = reject; - document.head.appendChild(script); - }); - - lenisLoaded = true; - lenisLoading = false; - console.log('βœ“ Lenis loaded successfully'); - return true; - } catch (error) { - console.error('βœ— Failed to load Lenis:', error); - lenisLoaded = false; - lenisLoading = false; - return false; - } -} - -async function initializeSmoothScrolling() { - if (lenis) return; // Already initialized - - const loaded = await loadLenisScript(); - if (!loaded) return; - - lenis = new window.Lenis({ - wrapper: document.querySelector('.main-content'), - content: document.querySelector('.main-content'), - lerp: 0.1, - smoothWheel: true, - smoothTouch: false, - normalizeWheel: true, - wheelMultiplier: 0.8, - }); - - function raf(time) { - if (lenis) { - lenis.raf(time); - requestAnimationFrame(raf); - } - } - - requestAnimationFrame(raf); -} - -function destroySmoothScrolling() { - if (lenis) { - lenis.destroy(); - lenis = null; - } -} - -async function setupSmoothScrolling() { - // Check if smooth scrolling is enabled - const smoothScrollingEnabled = smoothScrollingSettings.isEnabled(); - - if (smoothScrollingEnabled) { - await initializeSmoothScrolling(); - } - - // Listen for toggle changes - window.addEventListener('smooth-scrolling-toggle', async function (e) { - if (e.detail.enabled) { - await initializeSmoothScrolling(); - } else { - destroySmoothScrolling(); - } - }); -} - -// Initialize when DOM is ready -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', setupSmoothScrolling); -} else { - setupSmoothScrolling(); -} diff --git a/js/storage.js b/js/storage.js index dc1cbc8ff..6f8a0a416 100644 --- a/js/storage.js +++ b/js/storage.js @@ -1,4 +1,7 @@ //storage.js + +import { SVG_RIGHT_ARROW } from './icons'; + export const apiSettings = { STORAGE_KEY: 'monochrome-api-instances-v9', INSTANCES_URLS: [ @@ -6,9 +9,25 @@ export const apiSettings = { 'https://tidal-uptime.props-76styles.workers.dev/', ], defaultInstances: { api: [], streaming: [] }, + userInstances: null, instancesLoaded: false, _loadPromise: null, + _loadUserInstances() { + if (this.userInstances) return this.userInstances; + try { + const stored = localStorage.getItem('monochrome-user-api-instances-v1'); + this.userInstances = stored ? JSON.parse(stored) : { api: [], streaming: [] }; + } catch { + this.userInstances = { api: [], streaming: [] }; + } + return this.userInstances; + }, + + _saveUserInstances() { + localStorage.setItem('monochrome-user-api-instances-v1', JSON.stringify(this.userInstances)); + }, + async loadInstancesFromGitHub() { if (this.instancesLoaded) { return this.defaultInstances; @@ -39,8 +58,8 @@ export const apiSettings = { let data = null; let fetchError = null; - // Shuffle URLs to pick a random one first - const urls = [...this.INSTANCES_URLS].sort(() => Math.random() - 0.5); + // Prefer first URL, only try others as fallback + const urls = [...this.INSTANCES_URLS]; for (const url of urls) { try { @@ -58,27 +77,25 @@ export const apiSettings = { console.error('Failed to load instances from all uptime APIs:', fetchError); this.defaultInstances = { api: [ - { url: 'https://eu-central.monochrome.tf', version: '2.4' }, - { url: 'https://us-west.monochrome.tf', version: '2.4' }, - { url: 'https://arran.monochrome.tf', version: '2.4' }, - { url: 'https://triton.squid.wtf', version: '2.4' }, - { url: 'https://api.monochrome.tf', version: '2.3' }, + { url: 'https://hifi.geeked.wtf', version: '2.7' }, + { url: 'https://eu-central.monochrome.tf', version: '2.7' }, + { url: 'https://us-west.monochrome.tf', version: '2.7' }, + { url: 'https://api.monochrome.tf', version: '2.5' }, { url: 'https://monochrome-api.samidy.com', version: '2.3' }, - { url: 'https://maus.qqdl.site', version: '2.2' }, - { url: 'https://vogel.qqdl.site', version: '2.2' }, - { url: 'https://katze.qqdl.site', version: '2.2' }, - { url: 'https://hund.qqdl.site', version: '2.2' }, + { url: 'https://maus.qqdl.site', version: '2.6' }, + { url: 'https://vogel.qqdl.site', version: '2.6' }, + { url: 'https://katze.qqdl.site', version: '2.6' }, + { url: 'https://hund.qqdl.site', version: '2.6' }, { url: 'https://tidal.kinoplus.online', version: '2.2' }, { url: 'https://wolf.qqdl.site', version: '2.2' }, ], streaming: [ - { url: 'https://arran.monochrome.tf', version: '2.4' }, - { url: 'https://triton.squid.wtf', version: '2.4' }, - { url: 'https://maus.qqdl.site', version: '2.2' }, - { url: 'https://vogel.qqdl.site', version: '2.2' }, - { url: 'https://katze.qqdl.site', version: '2.2' }, - { url: 'https://hund.qqdl.site', version: '2.2' }, - { url: 'https://wolf.qqdl.site', version: '2.2' }, + { url: 'https://hifi.geeked.wtf', version: '2.7' }, + { url: 'https://maus.qqdl.site', version: '2.6' }, + { url: 'https://vogel.qqdl.site', version: '2.6' }, + { url: 'https://katze.qqdl.site', version: '2.6' }, + { url: 'https://hund.qqdl.site', version: '2.6' }, + { url: 'https://wolf.qqdl.site', version: '2.6' }, ], }; this.instancesLoaded = true; @@ -88,14 +105,17 @@ export const apiSettings = { let groupedInstances = { api: [], streaming: [] }; + const isBlockedInstance = (item) => { + const url = typeof item === 'string' ? item : item.url; + return url && /\.squid\.wtf/i.test(url); + }; + if (data.api && Array.isArray(data.api)) { - groupedInstances.api = data.api.filter((instance) => !instance.url.includes('spotisaver.net')); + groupedInstances.api = data.api.filter((item) => !isBlockedInstance(item)); } if (data.streaming && Array.isArray(data.streaming)) { - groupedInstances.streaming = data.streaming.filter( - (instance) => !instance.url.includes('spotisaver.net') - ); + groupedInstances.streaming = data.streaming.filter((item) => !isBlockedInstance(item)); } else if (groupedInstances.api.length > 0) { groupedInstances.streaming = [...groupedInstances.api]; } @@ -126,14 +146,52 @@ export const apiSettings = { let instancesObj; instancesObj = await this.loadInstancesFromGitHub(); + const userInst = this._loadUserInstances(); + + const defaultUrls = instancesObj[type] || instancesObj.api || []; + const userUrls = userInst[type] || []; - const targetUrls = instancesObj[type] || instancesObj.api || []; - if (targetUrls.length === 0) return []; + const combined = [ + ...userUrls.map((u) => (typeof u === 'string' ? { url: u, isUser: true } : { ...u, isUser: true })), + ...defaultUrls, + ]; - return targetUrls; + if (combined.length === 0) return []; + + return combined; + }, + + addUserInstance(type, url) { + const userInst = this._loadUserInstances(); + if (!userInst[type]) userInst[type] = []; + + if (!userInst[type].some((u) => (typeof u === 'string' ? u === url : u.url === url))) { + userInst[type].push({ url, isUser: true, version: 'custom' }); + this._saveUserInstances(); + return true; + } + return false; + }, + + removeUserInstance(type, url) { + const userInst = this._loadUserInstances(); + if (!userInst[type]) return false; + + const initialLength = userInst[type].length; + userInst[type] = userInst[type].filter((u) => (typeof u === 'string' ? u !== url : u.url !== url)); + + if (userInst[type].length !== initialLength) { + this._saveUserInstances(); + return true; + } + return false; }, async refreshInstances() { + this.instancesLoaded = false; + this._loadPromise = null; + localStorage.removeItem(this.STORAGE_KEY); + const instances = await this.loadInstancesFromGitHub(); const shuffle = (array) => { @@ -144,12 +202,26 @@ export const apiSettings = { return array; }; + const prioritySort = (array) => { + const getUrl = (item) => (typeof item === 'string' ? item : item.url || ''); + const top = []; + const middle = []; + const bottom = []; + for (const item of array) { + const url = getUrl(item); + if (url.includes('hifi.geeked.wtf')) top.push(item); + else if (url.includes('.qqdl.site')) bottom.push(item); + else middle.push(item); + } + return [...top, ...shuffle(middle), ...shuffle(bottom)]; + }; + if (instances.api && instances.api.length) { - instances.api = shuffle([...instances.api]); + instances.api = prioritySort([...instances.api]); } if (instances.streaming && instances.streaming.length) { - instances.streaming = shuffle([...instances.streaming]); + instances.streaming = prioritySort([...instances.streaming]); } this.saveInstances(instances); @@ -160,9 +232,23 @@ export const apiSettings = { saveInstances(instances, type) { if (type) { try { + this._loadUserInstances(); + const userInst = instances.filter((i) => i.isUser); + const defaultInst = instances.filter((i) => !i.isUser); + + this.userInstances[type] = userInst; + this._saveUserInstances(); + const stored = localStorage.getItem(this.STORAGE_KEY); let fullObj = stored ? JSON.parse(stored) : { api: [], streaming: [] }; - fullObj[type] = instances; + + if (fullObj && fullObj.data) { + fullObj.data[type] = defaultInst; + } else { + if (!fullObj) fullObj = { api: [], streaming: [] }; + fullObj[type] = defaultInst; + } + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(fullObj)); } catch (e) { console.error('Failed to save instances:', e); @@ -421,6 +507,23 @@ export const nowPlayingSettings = { }, }; +export const gaplessPlaybackSettings = { + STORAGE_KEY: 'gapless-playback-enabled', + + isEnabled() { + try { + const val = localStorage.getItem(this.STORAGE_KEY); + return val === null ? true : val === 'true'; + } catch { + return true; + } + }, + + setEnabled(enabled) { + localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false'); + }, +}; + export const fullscreenCoverClickSettings = { STORAGE_KEY: 'fullscreen-cover-click-action', @@ -539,7 +642,13 @@ export const downloadQualitySettings = { STORAGE_KEY: 'download-quality', getQuality() { try { - return localStorage.getItem(this.STORAGE_KEY) || 'HI_RES_LOSSLESS'; + const stored = localStorage.getItem(this.STORAGE_KEY) || 'HI_RES_LOSSLESS'; + // Migrate legacy value to renamed format + if (stored === 'MP3_320') { + this.setQuality('FFMPEG_MP3_320'); + return 'FFMPEG_MP3_320'; + } + return stored; } catch { return 'HI_RES_LOSSLESS'; } @@ -553,7 +662,8 @@ export const losslessContainerSettings = { STORAGE_KEY: 'lossless-container', getContainer() { try { - return localStorage.getItem(this.STORAGE_KEY) || 'flac'; + const stored = localStorage.getItem(this.STORAGE_KEY) || 'flac'; + return stored; } catch { return 'flac'; } @@ -593,22 +703,6 @@ export const waveformSettings = { }, }; -export const smoothScrollingSettings = { - STORAGE_KEY: 'smooth-scrolling-enabled', - - isEnabled() { - try { - return localStorage.getItem(this.STORAGE_KEY) === 'true'; - } catch { - return false; - } - }, - - setEnabled(enabled) { - localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false'); - }, -}; - export const qualityBadgeSettings = { STORAGE_KEY: 'show-quality-badges', @@ -643,22 +737,6 @@ export const trackDateSettings = { }, }; -export const bulkDownloadSettings = { - STORAGE_KEY: 'force-individual-downloads', - - shouldForceIndividual() { - try { - return localStorage.getItem(this.STORAGE_KEY) === 'true'; - } catch { - return false; - } - }, - - setForceIndividual(enabled) { - localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false'); - }, -}; - export const playlistSettings = { M3U_KEY: 'playlist-generate-m3u', M3U8_KEY: 'playlist-generate-m3u8', @@ -667,6 +745,7 @@ export const playlistSettings = { JSON_KEY: 'playlist-generate-json', RELATIVE_PATHS_KEY: 'playlist-relative-paths', SEPARATE_DISCS_KEY: 'playlist-separate-discs-in-zip', + INCLUDE_COVER_KEY: 'playlist-include-cover', shouldGenerateM3U() { try { @@ -754,6 +833,19 @@ export const playlistSettings = { setSeparateDiscsInZip(enabled) { localStorage.setItem(this.SEPARATE_DISCS_KEY, enabled ? 'true' : 'false'); }, + + shouldIncludeCover() { + try { + const val = localStorage.getItem(this.INCLUDE_COVER_KEY); + return val === null ? true : val === 'true'; + } catch { + return true; + } + }, + + setIncludeCover(enabled) { + localStorage.setItem(this.INCLUDE_COVER_KEY, enabled ? 'true' : 'false'); + }, }; export const visualizerSettings = { @@ -1454,8 +1546,7 @@ export const sidebarSettings = { document.body.classList.add('sidebar-collapsed'); const toggleBtn = document.getElementById('sidebar-toggle'); if (toggleBtn) { - toggleBtn.innerHTML = - ''; + toggleBtn.innerHTML = SVG_RIGHT_ARROW(20); } } }, @@ -1465,6 +1556,7 @@ export const listenBrainzSettings = { ENABLED_KEY: 'listenbrainz-enabled', TOKEN_KEY: 'listenbrainz-token', CUSTOM_URL_KEY: 'listenbrainz-custom-url', + LOVE_ON_LIKE_KEY: 'listenbrainz-love-on-like', isEnabled() { try { @@ -1501,6 +1593,18 @@ export const listenBrainzSettings = { setCustomUrl(url) { localStorage.setItem(this.CUSTOM_URL_KEY, url); }, + + shouldLoveOnLike() { + try { + return localStorage.getItem(this.LOVE_ON_LIKE_KEY) === 'true'; + } catch { + return false; + } + }, + + setLoveOnLike(enabled) { + localStorage.setItem(this.LOVE_ON_LIKE_KEY, enabled ? 'true' : 'false'); + }, }; export const malojaSettings = { @@ -1704,7 +1808,6 @@ export const sidebarSectionSettings = { SHOW_DONATE_KEY: 'sidebar-show-donate', SHOW_SETTINGS_KEY: 'sidebar-show-settings', SHOW_ABOUT_KEY: 'sidebar-show-about', - SHOW_DOWNLOAD_KEY: 'sidebar-show-download', SHOW_DISCORD_KEY: 'sidebar-show-discord', SHOW_GITHUB_KEY: 'sidebar-show-github', ORDER_KEY: 'sidebar-menu-order', @@ -1716,7 +1819,6 @@ export const sidebarSectionSettings = { 'sidebar-nav-donate', 'sidebar-nav-settings', 'sidebar-nav-about-bottom', - 'sidebar-nav-download-bottom', 'sidebar-nav-discordbtn', 'sidebar-nav-githubbtn', ], @@ -1817,19 +1919,6 @@ export const sidebarSectionSettings = { localStorage.setItem(this.SHOW_ABOUT_KEY, enabled ? 'true' : 'false'); }, - shouldShowDownload() { - try { - const val = localStorage.getItem(this.SHOW_DOWNLOAD_KEY); - return val === null ? true : val === 'true'; - } catch { - return true; - } - }, - - setShowDownload(enabled) { - localStorage.setItem(this.SHOW_DOWNLOAD_KEY, enabled ? 'true' : 'false'); - }, - shouldShowDiscord() { try { const val = localStorage.getItem(this.SHOW_DISCORD_KEY); @@ -1914,7 +2003,6 @@ export const sidebarSectionSettings = { { id: 'sidebar-nav-donate', check: this.shouldShowDonate() }, { id: 'sidebar-nav-settings', check: this.shouldShowSettings() }, { id: 'sidebar-nav-about-bottom', check: this.shouldShowAbout() }, - { id: 'sidebar-nav-download-bottom', check: this.shouldShowDownload() }, { id: 'sidebar-nav-discordbtn', check: this.shouldShowDiscord() }, { id: 'sidebar-nav-githubbtn', check: this.shouldShowGithub() }, ]; @@ -2607,6 +2695,14 @@ export const keyboardShortcuts = { alt: false, description: 'Toggle visualizer auto-cycle', }, + multiSelectToggle: { + key: 'control', + shift: false, + ctrl: true, + alt: false, + description: 'Toggle track selection (individual)', + }, + multiSelectRange: { key: 'shift', shift: true, ctrl: false, alt: false, description: 'Select track range' }, }, getShortcuts() { diff --git a/js/taglib.ts b/js/taglib.ts index c70ef5329..8866aa2eb 100644 --- a/js/taglib.ts +++ b/js/taglib.ts @@ -1,76 +1,190 @@ -import { TagLib } from 'taglib-wasm'; -import { fetchBlobURL } from './utils'; -import _TagLibWasm from '!/taglib-wasm/dist/taglib-web.wasm?url'; +import { doTimed, doTimedAsync } from './doTimed'; import type { - TagLibWorkerMessageType, AddMetadataMessage, - GetMetadataMessage, TagLibFileResponse, TagLibMetadataResponse, - TagLibMetadata, TagLibReadMetadata, + TagLibReadTypes, + TagLibWriteTypes, } from './taglib.types'; import TagLibWorker from './taglib.worker?worker'; -let tagLib: Promise | null = null; +export async function withTimeout(callback: () => Promise, timeout: number): Promise { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + reject(new Error(`Operation timed out after ${timeout} ms`)); + }, timeout); -async function fetchTagLib(): Promise { - return fetchTagLib.blobUrl || (fetchTagLib.blobUrl = await fetchBlobURL(_TagLibWasm)); + callback() + .then((result) => { + clearTimeout(timer); + resolve(result); + }) + .catch((err) => { + clearTimeout(timer); + reject(err); + }); + }); } -namespace fetchTagLib { - export let blobUrl = ''; +function toUint8Array(audioData: ArrayBufferLike | Uint8Array) { + if (audioData instanceof Uint8Array) { + return audioData; + } + + return doTimed( + `Converting audio data (${(audioData as any)?.constructor?.name}) to Uint8Array`, + () => new Uint8Array(audioData) + ); } -export { fetchTagLib }; +async function convertInputToTaglib( + audioData: TagLibReadTypes | TagLibWriteTypes, + direct: boolean = false +): Promise { + if ('FileSystemFileEntry' in globalThis && audioData instanceof FileSystemFileEntry) { + audioData = await doTimedAsync('Getting File from FileSystemFileEntry', async () => { + const file = await new Promise((resolve) => + (audioData as FileSystemFileEntry).file((f) => resolve(f)) + ); + return toUint8Array(new Uint8Array(await file.arrayBuffer())); + }); + } -export async function addMetadataWithTagLib( - audioData: Uint8Array, - data: Omit -) { - if (!(audioData instanceof Uint8Array)) { - audioData = new Uint8Array(audioData); + if ((audioData instanceof Blob || audioData instanceof File) && !direct) { + return (await doTimedAsync( + `Reading ${audioData instanceof File ? 'File' : 'Blob'} as Uint8Array`, + async () => new Uint8Array(await audioData.arrayBuffer()) + )) as R; + } else if ('FileSystemFileHandle' in globalThis && audioData instanceof FileSystemFileHandle && !direct) { + return (await doTimedAsync('Reading File from FileSystemHandle as Uint8Array', async () => { + const file = await audioData.getFile(); + const arrayBuffer = await file.arrayBuffer(); + return await toUint8Array(arrayBuffer); + })) as R; + } else if ( + !(audioData instanceof Uint8Array) && + !(audioData instanceof Blob) && + !(audioData instanceof File) && + !('FileSystemFileEntry' in globalThis && audioData instanceof FileSystemFileEntry) && + !('FileSystemFileHandle' in globalThis && audioData instanceof FileSystemFileHandle) + ) { + return toUint8Array(audioData as any) as R; } - const worker = new TagLibWorker(); - const wasmUrl = await fetchTagLib(); - - return new Promise((resolve, reject) => { - worker.onmessage = (e: MessageEvent) => { - const { data, error } = e.data; - - if (error) { - reject(new Error(error)); - } else { - resolve(data!); - } - }; - worker.onerror = reject; - worker.onmessageerror = reject; - worker.postMessage({ ...data, type: 'Add', wasmUrl, audioData }, [audioData.buffer]); - }); + return audioData as R; } -export async function getMetadataWithTagLib(audioData: Uint8Array) { - if (!(audioData instanceof Uint8Array)) { - audioData = new Uint8Array(audioData); +const workerModule = import('./taglib.worker.js'); + +export async function addMetadataWithTagLib( + audioData: TagLibWriteTypes, + data: Omit, + filename?: string, + direct: boolean = false, + returnBlob: boolean = false, + timeout: number = 10000 +) { + audioData = await convertInputToTaglib(audioData, direct); + + if (direct) { + const { addMetadataToAudio } = await workerModule; + + return await doTimedAsync('Adding metadata with taglib-ts (direct)', () => + addMetadataToAudio({ + ...data, + filename, + audioData, + returnType: returnBlob && direct ? 'blob' : 'uint8array', + }) + ); + } else { + const worker = new TagLibWorker(); + + try { + return await doTimedAsync( + 'Adding metadata with taglib-ts (worker)', + async () => + await withTimeout( + () => + new Promise((resolve, reject) => { + worker.onmessage = (e: MessageEvent) => { + const { data, error } = e.data; + + if (error) { + reject(new Error(error)); + } else { + resolve(data!); + } + }; + worker.onerror = reject; + worker.onmessageerror = reject; + + const transferables: Transferable[] = []; + if ((audioData as any)?.buffer instanceof ArrayBuffer) { + transferables.push((audioData as any).buffer); + } + + if ((data as any).cover?.data?.buffer instanceof ArrayBuffer) { + transferables.push((data as any).cover.data.buffer); + } + + worker.postMessage({ ...data, type: 'Add', audioData, filename }, transferables); + }), + timeout + ) + ); + } finally { + worker.terminate(); + } } +} - const worker = new Worker(new URL(TagLibWorker, import.meta.url), { type: 'module' }); - const wasmUrl = await fetchTagLib(); - - return new Promise((resolve, reject) => { - worker.onmessage = (e: MessageEvent) => { - const { data, error } = e.data; - - if (error) { - reject(new Error(error)); - } else { - resolve(data!); - } - }; - worker.onerror = reject; - worker.onmessageerror = reject; - worker.postMessage({ type: 'Get', wasmUrl, audioData }, [audioData.buffer]); - }); +export async function getMetadataWithTagLib( + audioData: TagLibReadTypes, + filename?: string, + direct: boolean = false, + timeout: number = 10000 +) { + audioData = await convertInputToTaglib(audioData, direct); + + if (direct) { + const { getMetadataFromAudio } = await workerModule; + + return await doTimedAsync('Getting metadata with taglib-ts (direct)', () => + getMetadataFromAudio({ filename, audioData }) + ); + } else { + const worker = new TagLibWorker(); + + try { + return await doTimedAsync('Getting metadata with taglib-ts (worker)', () => + withTimeout( + () => + new Promise((resolve, reject) => { + worker.onmessage = (e: MessageEvent) => { + const { data, error } = e.data; + + if (error) { + reject(new Error(error)); + } else { + resolve(data!); + } + }; + worker.onerror = reject; + worker.onmessageerror = reject; + + const transferables: Transferable[] = []; + if ((audioData as any)?.buffer instanceof ArrayBuffer) { + transferables.push((audioData as any).buffer); + } + worker.postMessage({ type: 'Get', audioData, filename }, transferables); + }), + timeout + ) + ); + } finally { + worker.terminate(); + } + } } diff --git a/js/taglib.types.ts b/js/taglib.types.ts index 5af538d4b..187d29b37 100644 --- a/js/taglib.types.ts +++ b/js/taglib.types.ts @@ -1,9 +1,11 @@ +import type { FileRef } from '!/@dantheman827/taglib-ts/src/fileRef'; + export type TagLibWorkerMessageType = 'Add' | 'Get'; -export interface TagLibWorkerMessage { +export interface TagLibWorkerMessage { type: TagLibWorkerMessageType; - wasmUrl: string; - audioData: Uint8Array; + audioData: T; + filename?: string; } export interface TagLibWorkerResponse { @@ -37,6 +39,21 @@ export interface TagLibMetadata { isrc?: string; explicit?: boolean; lyrics?: string; + upc?: string; + stik?: Mp4Stik; + extra?: Record; +} + +export enum Mp4Stik { + HomeVideo = 0, + Normal = 1, + Audiobook = 2, + WhackedBookmark = 5, + MusicVideo = 6, + Movie = 9, + ShortFilm = 9, + TVShow = 10, + Booklet = 11, } export interface TagLibReadMetadata extends TagLibMetadata { @@ -50,6 +67,19 @@ export type AddMetadataMessage = TagLibWorkerMessage & { type: 'Add'; } & TagLibMetadata; -export type GetMetadataMessage = TagLibWorkerMessage & { +export type GetMetadataMessage = TagLibWorkerMessage & { type: 'Get'; }; + +export type TagLibReadTypes = Uint8Array | Blob | File | FileSystemFileHandle | FileSystemFileEntry; +export type TagLibWriteTypes = Uint8Array; + +export type _AddMetadataMessage = Omit & { + audioRef?: FileRef | null; + audioData?: Uint8Array; + returnType?: 'blob' | 'uint8array'; +}; +export type _GetMetadataMessage = Omit & { + audioRef?: FileRef | null; + audioData?: TagLibReadTypes; +}; diff --git a/js/taglib.worker.ts b/js/taglib.worker.ts index 44ec70697..8b01a15b4 100644 --- a/js/taglib.worker.ts +++ b/js/taglib.worker.ts @@ -1,27 +1,44 @@ // filepath: /workspaces/monochrome/js/taglib.worker.ts declare var self: DedicatedWorkerGlobalScope; -import { TagLib, type PictureType } from 'taglib-wasm'; +import { ByteVector } from '!/@dantheman827/taglib-ts/src/byteVector.js'; +import { Mp4Tag, Mp4Item } from '!/@dantheman827/taglib-ts/src/mp4/mp4Tag.js'; +import { Variant } from '!/@dantheman827/taglib-ts/src/toolkit/variant.js'; import { doTimed, doTimedAsync } from './doTimed'; -import type { - AddMetadataMessage, - GetMetadataMessage, - TagLibFileResponse, - TagLibMetadata, - TagLibMetadataResponse, - TagLibReadMetadata, - TagLibWorkerMessage, - TagLibWorkerResponse, +import { + Mp4Stik, + type _AddMetadataMessage, + type _GetMetadataMessage, + type AddMetadataMessage, + type GetMetadataMessage, + type TagLibFileResponse, + type TagLibMetadata, + type TagLibMetadataResponse, + type TagLibReadMetadata, + type TagLibWorkerMessage, + type TagLibWorkerResponse, } from './taglib.types'; - -const PICTURE_TYPE_VALUES = { - FrontCover: 3, -}; - -async function addMetadataToAudio(message: AddMetadataMessage): Promise { +import { File as TagLibFile } from '!/@dantheman827/taglib-ts/src/file.js'; +import { FileRef } from '!/@dantheman827/taglib-ts/src/fileRef.js'; +import { ChunkedByteVectorStream } from '!/@dantheman827/taglib-ts/src/toolkit/chunkedByteVectorStream.js'; +import { ReadStyle } from '!/@dantheman827/taglib-ts/src/toolkit/types'; +import { BlobStream } from '!/@dantheman827/taglib-ts/src/toolkit/blobStream.js'; +import { FileSystemFileHandleStream } from '!/@dantheman827/taglib-ts/src/toolkit/fileSystemFileHandleStream.js'; + +// Imported to ensure support is bundled in this chunk, even if not directly used +import { FlacFile } from '!/@dantheman827/taglib-ts/src/flac/flacFile.js'; +import { MpegFile } from '!/@dantheman827/taglib-ts/src/mpeg/mpegFile.js'; +import { Mp4File } from '!/@dantheman827/taglib-ts/src/mp4/mp4File.js'; +import { OggFile } from '!/@dantheman827/taglib-ts/src/ogg/oggFile.js'; +import { OggVorbisFile } from '!/@dantheman827/taglib-ts/src/ogg/vorbis/vorbisFile.js'; + +export const isWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; + +export async function addMetadataToAudio(message: _AddMetadataMessage): Promise { const { - wasmUrl, audioData, + audioRef, + filename, title, artist, albumTitle, @@ -36,271 +53,309 @@ async function addMetadataToAudio(message: AddMetadataMessage): Promise { - const tagLib = await TagLib.initialize({ - wasmUrl: wasmUrl, - }); - return await tagLib.open(audioData); - }); + const ref = + audioRef ?? + (await doTimedAsync( + `Opening file (${audioData.constructor.name})`, + async () => await getFileRefFromAudioData(audioData) + )); - try { - doTimed('Tagging file', () => { - const isMp4 = file.isMP4(); - const media = file.audioProperties(); - const needsCombinedTrackDisc = isMp4 || media.containerFormat.toLowerCase() === 'mp3'; + if (!ref || !ref.isValid) { + console.warn('taglib-ts: failed to open file'); + return audioData; + } - if (title) { - file.setProperty('TITLE', title); - } + const underlying = ref.file(); + const isMp4 = underlying instanceof Mp4File; + const isMpeg = underlying instanceof MpegFile; + const needsCombinedTrackDisc = isMp4 || isMpeg; - if (artist) { - file.setProperty('ARTIST', artist); - } + doTimed('Tagging file', () => { + const props = ref.properties(); - if (albumTitle) { - file.setProperty('ALBUM', albumTitle); - } + if (title) props.replace('TITLE', [title]); + if (artist) props.replace('ARTIST', [artist]); + if (albumTitle) props.replace('ALBUM', [albumTitle]); + if (albumArtist || artist) props.replace('ALBUMARTIST', [albumArtist || artist!]); - const _albumArtist = albumArtist || artist; - if (_albumArtist) { - file.setProperty('ALBUMARTIST', _albumArtist); - } + if (trackNumber) { + const trackStr = + needsCombinedTrackDisc && totalTracks ? `${trackNumber}/${totalTracks}` : String(trackNumber); + props.replace('TRACKNUMBER', [trackStr]); + } + if (!needsCombinedTrackDisc && totalTracks) { + props.replace('TRACKTOTAL', [String(totalTracks)]); + } - if (trackNumber) { - let trackString = String(trackNumber); + if (discNumber) { + const discStr = needsCombinedTrackDisc && totalDiscs ? `${discNumber}/${totalDiscs}` : String(discNumber); + props.replace('DISCNUMBER', [discStr]); + } + if (!needsCombinedTrackDisc && totalDiscs) { + props.replace('DISCTOTAL', [String(totalDiscs)]); + } - if (needsCombinedTrackDisc && trackNumber && totalTracks) { - trackString = `${trackNumber}/${totalTracks}`; - } + if (bpm != null && Number.isFinite(bpm)) { + props.replace('BPM', [String(Math.round(bpm))]); + } - if (needsCombinedTrackDisc) { - file.setProperty('TRACKNUMBER', trackString); - } else { - file.setProperty('TRACKNUMBER', String(trackNumber)); - } - } + if (replayGain) { + const { albumReplayGain, albumPeakAmplitude, trackReplayGain, trackPeakAmplitude } = replayGain; + if (albumReplayGain != null) props.replace('REPLAYGAIN_ALBUM_GAIN', [String(albumReplayGain)]); + if (albumPeakAmplitude != null) props.replace('REPLAYGAIN_ALBUM_PEAK', [String(albumPeakAmplitude)]); + if (trackReplayGain != null) props.replace('REPLAYGAIN_TRACK_GAIN', [String(trackReplayGain)]); + if (trackPeakAmplitude != null) props.replace('REPLAYGAIN_TRACK_PEAK', [String(trackPeakAmplitude)]); + } - if (!needsCombinedTrackDisc && totalTracks) { - file.setProperty('TRACKTOTAL', String(totalTracks)); + if (releaseDate) { + try { + const year = Number(releaseDate.split('-')[0]); + if (!isNaN(year)) props.replace('DATE', [String(year)]); + } catch { + // Invalid date, skip } + } - if (discNumber) { - let discString = String(discNumber); - - if (needsCombinedTrackDisc && discNumber && totalDiscs) { - discString = `${discNumber}/${totalDiscs}`; - } - - if (needsCombinedTrackDisc) { - file.setProperty('DISCNUMBER', discString); - } else { - file.setProperty('DISCNUMBER', String(discNumber)); - } + if (copyright) props.replace('COPYRIGHT', [copyright]); + if (isrc) props.replace('ISRC', [isrc]); + if (isrc && isMp4) { + const mp4Tag = (underlying as Mp4File).tag() as Mp4Tag; + mp4Tag.setItem('xid ', Mp4Item.fromStringList([`:isrc:${isrc}`])); + } + if (upc) props.replace('UPC', [upc]); + if (lyrics) props.replace('LYRICS', [lyrics.replace(/\r/g, '').replace(/\n/g, '\r\n')]); + + if (explicit !== undefined) { + if (isMp4) { + // rtng is a byte item β€” must be set directly on the Mp4Tag + const mp4Tag = (underlying as Mp4File).tag() as Mp4Tag; + mp4Tag.setItem('rtng', Mp4Item.fromByte(explicit ? 1 : 0)); + } else { + props.replace('ITUNESADVISORY', [explicit ? '1' : '0']); } + } - if (!needsCombinedTrackDisc && totalDiscs) { - file.setProperty('DISCTOTAL', String(totalDiscs)); - } + if (stik != null && isMp4) { + const mp4Tag = (underlying as Mp4File).tag() as Mp4Tag; + mp4Tag.setItem('stik', Mp4Item.fromByte(stik)); + } - if (bpm != null && Number.isFinite(bpm)) { - file.setProperty('BPM', String(Math.round(bpm))); - } + for (const [key, value] of Object.entries(extra || {})) { + if (value) props.replace(key, [value]); + } - if (replayGain) { - const { albumReplayGain, albumPeakAmplitude, trackReplayGain, trackPeakAmplitude } = replayGain; - if (albumReplayGain) file.setProperty('REPLAYGAIN_ALBUM_GAIN', String(albumReplayGain)); - if (albumPeakAmplitude) file.setProperty('REPLAYGAIN_ALBUM_PEAK', String(albumPeakAmplitude)); - if (trackReplayGain) file.setProperty('REPLAYGAIN_TRACK_GAIN', String(trackReplayGain)); - if (trackPeakAmplitude) file.setProperty('REPLAYGAIN_TRACK_PEAK', String(trackPeakAmplitude)); - } + ref.setProperties(props); - if (releaseDate) { - try { - const year = Number(releaseDate.split('-')[0]); - if (!isNaN(year)) { - file.setProperty('DATE', String(year)); - } - } catch { - // Invalid date, skip - } - } + if (cover) { + const pictureMap = new Map(); + pictureMap.set('data', Variant.fromByteVector(ByteVector.fromByteArray(cover.data))); + pictureMap.set('mimeType', Variant.fromString(cover.type)); + pictureMap.set('pictureType', Variant.fromInt(3)); // FrontCover + ref.setComplexProperties('PICTURE', [pictureMap]); + } + }); - if (copyright) { - file.setProperty('COPYRIGHT', copyright); - } + await doTimedAsync('Saving in-memory buffer', async () => { + await ref.save(); + }); - if (isrc) { - file.setProperty('ISRC', isrc); + const file = ref.file() as TagLibFile; + if (!file) return audioData; + const stream = file.stream(); + + if (stream instanceof ChunkedByteVectorStream) { + const data = doTimed( + 'Converting saved file to ' + (returnType == 'blob' ? 'Blob' : 'Uint8Array'), + () => stream.data().data + ); + if (returnType === 'blob') { + const blob = new Blob([data as BlobPart], { type: 'application/octet-stream' }); + return blob; + } + return data; + } else if (stream instanceof BlobStream) { + const blob = doTimed('Converting saved file to ' + (returnType == 'blob' ? 'Blob' : 'Uint8Array'), () => + stream.toBlob() + ); + if (returnType === 'blob') { + return blob; + } + const arrayBuffer = await doTimed('Reading Blob as ArrayBuffer', async () => await blob.arrayBuffer()); + return new Uint8Array(arrayBuffer); + } - if (isMp4) { - file.setMP4Item('xid ', `:isrc:${isrc}`); - } - } + console.warn('taglib-ts: unexpected stream type after saving file', stream); + return audioData; +} - if (explicit) { - if (isMp4) { - file.setMP4Item('rtng', '1'); - } else { - file.setProperty('ITUNESADVISORY', '1'); - } - } +export async function getMetadataFromAudio(message: _GetMetadataMessage): Promise { + const { audioData, audioRef, filename } = message; + const data: TagLibReadMetadata = { duration: 0 }; - if (lyrics) { - file.setProperty('LYRICS', lyrics.replace(/\r/g, '').replace(/\n/g, '\r\n')); - } + const ref = + audioRef ?? + (await doTimedAsync( + `Opening file (${audioData.constructor.name})`, + async () => await getFileRefFromAudioData(audioData) + )); - if (cover) { - file.setPictures([ - { - mimeType: cover.type, - data: cover.data, - type: 'FrontCover', - description: 'Cover Art', - }, - ]); - } - }); + if (!ref || !ref.isValid) return data; - await doTimedAsync('Saving in-memory buffer', () => file.save()); + const underlying = ref.file(); + const isMp4 = underlying instanceof Mp4File; + const ap = ref.audioProperties(); - return file.getFileBuffer(); - } catch (err) { - console.error(err); - } finally { - file.dispose(); - } + if (ap) data.duration = ap.lengthInSeconds; - return audioData; -} + const props = ref.properties(); -async function getMetadataFromAudio(message: GetMetadataMessage): Promise { - const { wasmUrl, audioData } = message; - const data: TagLibReadMetadata = { - duration: 0, - }; + data.title = props.get('TITLE')?.[0] || undefined; + data.artist = props.get('ARTIST')?.[0] || undefined; + data.albumTitle = props.get('ALBUM')?.[0] || undefined; + data.albumArtist = props.get('ALBUMARTIST')?.[0] || undefined; - const file = await doTimedAsync('Open file with taglib', async () => { - const tagLib = await TagLib.initialize({ - wasmUrl: wasmUrl, - }); - return await tagLib.open(audioData); - }); + const trackStr = props.get('TRACKNUMBER')?.[0] ?? ''; + const [trackNum, trackTotal] = trackStr.split('/').map((t) => Number(t.trim() || 0) || undefined); + data.trackNumber = trackNum || undefined; + data.totalTracks = trackTotal ?? (Number(props.get('TRACKTOTAL')?.[0] || 0) || undefined); - try { - const pictures = file.getPictures(); - const isMp4 = file.isMP4(); - const media = file.audioProperties(); - - data.duration = media.duration; - - data.title = file.getProperty('TITLE') || undefined; - data.artist = file.getProperty('ARTIST') || undefined; - data.albumTitle = file.getProperty('ALBUM') || undefined; - data.albumArtist = file.getProperty('ALBUMARTIST') || undefined; - const [trackNumber, trackTotal] = file - .getProperty('TRACKNUMBER') - ?.split('/') - .map((t) => Number(t.trim() || 0) || undefined); - data.trackNumber = trackNumber || undefined; - data.totalTracks = trackTotal ? trackTotal : Number(file.getProperty('TRACKTOTAL') || 0) || undefined; - - const [discNumber, discTotal] = file - .getProperty('DISCNUMBER') - ?.split('/') - .map((t) => Number(t.trim() || 0) || undefined); - data.discNumber = Number(file.getProperty('DISCNUMBER') || 0) || undefined; - - data.bpm = Number(file.getProperty('BPM') || 0) || undefined; - data.copyright = file.getProperty('COPYRIGHT') || undefined; - data.lyrics = file.getProperty('LYRICS') || undefined; - data.releaseDate = file.getProperty('DATE') || undefined; - - const [replayGainAlbumGain, replayGainAlbumPeak, replayGainTrackGain, replayGainTrackPeak] = [ - file.getProperty('REPLAYGAIN_ALBUM_GAIN'), - file.getProperty('REPLAYGAIN_ALBUM_PEAK'), - file.getProperty('REPLAYGAIN_TRACK_GAIN'), - file.getProperty('REPLAYGAIN_TRACK_PEAK'), - ]; - - const replayGain: TagLibMetadata['replayGain'] = {}; - if (replayGainAlbumGain) replayGain.albumReplayGain = replayGainAlbumGain; - if (replayGainAlbumPeak) replayGain.albumPeakAmplitude = Number(replayGainAlbumPeak); - if (replayGainTrackGain) replayGain.trackReplayGain = replayGainTrackGain; - if (replayGainTrackPeak) replayGain.trackPeakAmplitude = Number(replayGainTrackPeak); - if (Object.keys(replayGain).length > 0) { - data.replayGain = replayGain; - } + const discStr = props.get('DISCNUMBER')?.[0] ?? ''; + const [discNum, discTotal] = discStr.split('/').map((t) => Number(t.trim() || 0) || undefined); + data.discNumber = discNum || undefined; + if (!data.totalDiscs) { + data.totalDiscs = discTotal ?? (Number(props.get('DISCTOTAL')?.[0] || 0) || undefined); + } - data.isrc = (isMp4 && file.getMP4Item('xid ')?.split(':').at(-1)) || file.getProperty('ISRC') || undefined; - data.explicit = (isMp4 && file.getMP4Item('rtng') === '1') || file.getProperty('ITUNESADVISORY') === '1'; + data.bpm = Number(props.get('BPM')?.[0] || 0) || undefined; + data.copyright = props.get('COPYRIGHT')?.[0] || undefined; + data.lyrics = props.get('LYRICS')?.[0] || undefined; + data.releaseDate = props.get('DATE')?.[0] || undefined; + + const replayGain: TagLibMetadata['replayGain'] = {}; + const albumGain = props.get('REPLAYGAIN_ALBUM_GAIN')?.[0]; + const albumPeak = props.get('REPLAYGAIN_ALBUM_PEAK')?.[0]; + const trackGain = props.get('REPLAYGAIN_TRACK_GAIN')?.[0]; + const trackPeak = props.get('REPLAYGAIN_TRACK_PEAK')?.[0]; + if (albumGain) replayGain.albumReplayGain = albumGain; + if (albumPeak) replayGain.albumPeakAmplitude = Number(albumPeak); + if (trackGain) replayGain.trackReplayGain = trackGain; + if (trackPeak) replayGain.trackPeakAmplitude = Number(trackPeak); + if (Object.keys(replayGain).length > 0) data.replayGain = replayGain; + + data.isrc = props.get('ISRC')?.[0] || undefined; + + if (isMp4) { + const mp4Tag = (underlying as Mp4File).tag() as Mp4Tag; + data.explicit = mp4Tag.item('rtng')?.toByte() === 1; + } else { + data.explicit = props.get('ITUNESADVISORY')?.[0] === '1'; + } - if (pictures.length > 0) { - const picture = pictures.filter((p) => p.type === 'FrontCover')[0]; - if (picture) { - data.cover = { - data: picture.data, - type: picture.mimeType, - }; - } + const pictures = ref.complexProperties('PICTURE'); + if (pictures.length > 0) { + const pic = pictures[0]; + const picData = pic.get('data')?.toByteVector(); + const mimeType = pic.get('mimeType')?.toString() ?? ''; + if (picData && picData.length > 0) { + data.cover = { data: picData.data, type: mimeType }; } - } catch (err) { - console.error(err); - } finally { - file.dispose(); } return data; } -self.onmessage = async (event: MessageEvent) => { - const transfer: Transferable[] = [event.data.audioData.buffer]; +async function getFileRefFromAudioData( + audioData: Uint8Array | Blob | File | FileSystemFileHandle | FileSystemFileEntry +): Promise { + if (audioData instanceof Blob || audioData instanceof File) { + const stream = new BlobStream(audioData); + return await FileRef.open(stream, true, ReadStyle.Average); + } else if (audioData instanceof FileSystemFileHandle) { + const stream = await FileSystemFileHandleStream.open(audioData, true); + return await FileRef.open(stream, true, ReadStyle.Average); + } else if ('FileSystemFileEntry' in globalThis && audioData instanceof FileSystemFileEntry) { + const file = await new Promise((resolve) => audioData.file((f) => resolve(f))); + const stream = new BlobStream(file); + return await FileRef.open(stream, true, ReadStyle.Average); + } else if (audioData instanceof Uint8Array) { + const stream = new ChunkedByteVectorStream(audioData); + return await FileRef.open(stream, true, ReadStyle.Average); + } - switch (event.data.type) { - case 'Add': - try { - const result = await addMetadataToAudio(event.data as AddMetadataMessage); - transfer.push(result.buffer); - self.postMessage( - { - type: event.data.type, - data: result, - } satisfies TagLibFileResponse, - transfer - ); - } catch (error) { - self.postMessage( - { - type: event.data.type, - error: error instanceof Error ? error.message : String(error), - } satisfies TagLibWorkerResponse, - transfer - ); - } - break; + throw new Error('Unsupported audio data type'); +} - case 'Get': - try { - const result = await getMetadataFromAudio(event.data as GetMetadataMessage); - self.postMessage( - { - type: event.data.type, - data: result, - } satisfies TagLibMetadataResponse, - transfer - ); - } catch (error) { - self.postMessage( - { - type: event.data.type, - error: error instanceof Error ? error.message : String(error), - } satisfies TagLibWorkerResponse, - transfer - ); - } - break; - } -}; +if (isWorker) { + self.onmessage = async (event: MessageEvent) => { + const transfer: Transferable[] = []; + if (event.data.audioData?.buffer instanceof ArrayBuffer) { + transfer.push(event.data.audioData.buffer); + } + + switch (event.data.type) { + case 'Add': + if ((event.data as AddMetadataMessage).cover?.data?.buffer instanceof ArrayBuffer) { + transfer.push((event.data as AddMetadataMessage).cover.data.buffer); + } + + try { + const result = (await addMetadataToAudio({ + ...event.data, + returnType: 'uint8array', + } as _AddMetadataMessage)) as Uint8Array; + + if (result.buffer !== event.data.audioData.buffer) { + transfer.push(result.buffer); + } + + self.postMessage( + { + type: event.data.type, + data: result, + } satisfies TagLibFileResponse, + transfer + ); + } catch (error) { + self.postMessage( + { + type: event.data.type, + error: error instanceof Error ? error.message : String(error), + } satisfies TagLibWorkerResponse, + transfer + ); + } + break; + + case 'Get': + try { + const result = await getMetadataFromAudio({ + ...event.data, + } as _GetMetadataMessage); + self.postMessage( + { + type: event.data.type, + data: result, + } satisfies TagLibMetadataResponse, + transfer + ); + } catch (error) { + self.postMessage( + { + type: event.data.type, + error: error instanceof Error ? error.message : String(error), + } satisfies TagLibWorkerResponse, + transfer + ); + } + break; + } + }; +} diff --git a/js/themeStore.js b/js/themeStore.js index 009f6737c..2f2cd195c 100644 --- a/js/themeStore.js +++ b/js/themeStore.js @@ -1,6 +1,7 @@ import { syncManager } from './accounts/pocketbase.js'; import { authManager } from './accounts/auth.js'; import { navigate } from './router.js'; +import { SVG_BIN, SVG_SQUARE_PEN } from './icons.js'; const THEMES_PER_PAGE = 50; @@ -196,10 +197,10 @@ export class ThemeStore { actionBtnsHtml = `
    `; diff --git a/js/tracker.js b/js/tracker.js index e1e733f2c..8c956547e 100644 --- a/js/tracker.js +++ b/js/tracker.js @@ -1,10 +1,11 @@ //js/tracker.js -import { escapeHtml, SVG_MENU, SVG_PLAY, trackDataStore, formatTime, SVG_HEART } from './utils.js'; +import { escapeHtml, trackDataStore, formatTime } from './utils.js'; import { navigate } from './router.js'; +import { SVG_MENU, SVG_PLAY, SVG_HEART } from './icons.js'; +import { Player } from './player.js'; let artistsData = []; let artistsPopularity = new Map(); // name -> popularity score -let globalPlayer = null; // Map to store artist info keyed by sheetId for quick lookup const artistBySheetId = new Map(); @@ -106,11 +107,7 @@ function transformErasImages(eras) { } async function fetchTrackerData(sheetId) { - const endpoints = [ - 'https://tracker.israeli.ovh/get/', - 'https://tracker.thug.surf/get/', - 'https://trackerapi-2.artistgrid.cx/get/', - ]; + const endpoints = ['https://trackerapi-1.artistgrid.cx/get/', 'https://trackerapi-2.artistgrid.cx/get/']; let lastError = null; for (const baseUrl of endpoints) { @@ -218,7 +215,7 @@ function createTrackerTrackItemHTML(track, index) { ? '' : ` `; @@ -282,10 +279,10 @@ function renderTrackerTracks(container, tracks) { export function createProjectCardHTML(era, artist, sheetId, trackCount) { const playBtnHTML = ` `; @@ -298,7 +295,7 @@ export function createProjectCardHTML(era, artist, sheetId, trackCount) { loading="lazy" onerror="this.src='assets/logo.svg'"> ${playBtnHTML} @@ -371,8 +368,8 @@ export async function renderTrackerArtistPage(sheetId, container) { const availableTracks = allTracks.filter((t) => !t.unavailable); if (availableTracks.length > 0) { const shuffled = [...availableTracks].sort(() => Math.random() - 0.5); - globalPlayer.setQueue(shuffled, 0); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(shuffled, 0); + Player.instance.playTrackFromQueue(); } }; } @@ -449,8 +446,8 @@ export async function renderTrackerArtistPage(sheetId, container) { } const availableTracks = eraTracks.filter((t) => !t.unavailable); if (availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, 0); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, 0); + Player.instance.playTrackFromQueue(); } } else if (e.target.closest('.card-menu-btn')) { e.stopPropagation(); @@ -520,8 +517,8 @@ export async function renderTrackerArtistPage(sheetId, container) { const availableTracks = searchTracks.filter((t) => !t.unavailable); const trackIndex = availableTracks.findIndex((t) => t.id === track.id); if (trackIndex >= 0 && availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, trackIndex); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, trackIndex); + Player.instance.playTrackFromQueue(); } }; }); @@ -596,12 +593,12 @@ export async function renderTrackerProjectPage(sheetId, projectName, container, // Setup buttons if (playBtn) { - playBtn.innerHTML = `${SVG_PLAY}Play Project`; + playBtn.innerHTML = `${SVG_PLAY(20)}Play Project`; playBtn.onclick = () => { const availableTracks = eraTracks.filter((t) => !t.unavailable); if (availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, 0); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, 0); + Player.instance.playTrackFromQueue(); } }; } @@ -611,8 +608,8 @@ export async function renderTrackerProjectPage(sheetId, projectName, container, const availableTracks = eraTracks.filter((t) => !t.unavailable); if (availableTracks.length > 0) { const shuffled = [...availableTracks].sort(() => Math.random() - 0.5); - globalPlayer.setQueue(shuffled, 0); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(shuffled, 0); + Player.instance.playTrackFromQueue(); } }; } @@ -642,8 +639,8 @@ export async function renderTrackerProjectPage(sheetId, projectName, container, const availableTracks = eraTracks.filter((t) => !t.unavailable); const trackIndex = availableTracks.findIndex((t) => t.id === track.id); if (trackIndex >= 0 && availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, trackIndex); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, trackIndex); + Player.instance.playTrackFromQueue(); } }; }); @@ -701,8 +698,8 @@ export async function renderTrackerProjectPage(sheetId, projectName, container, } const availableTracks = otherEraTracks.filter((t) => !t.unavailable); if (availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, 0); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, 0); + Player.instance.playTrackFromQueue(); } } else if (e.target.closest('.card-menu-btn')) { e.stopPropagation(); @@ -901,13 +898,13 @@ export async function renderTrackerTrackPage(trackId, container, _ui) { prodEl.innerHTML = `By ${artist.name} β€’ From ${era.name}`; if (playBtn) { - playBtn.innerHTML = `${SVG_PLAY}Play Track`; + playBtn.innerHTML = `${SVG_PLAY(20)}Play Track`; playBtn.onclick = () => { const availableTracks = allTracks.filter((t) => !t.unavailable); const trackPos = availableTracks.findIndex((t) => t.id === currentTrack.id); if (trackPos >= 0 && availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, trackPos); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, trackPos); + Player.instance.playTrackFromQueue(); } }; } @@ -937,8 +934,8 @@ export async function renderTrackerTrackPage(trackId, container, _ui) { const availableTracks = allTracks.filter((t) => !t.unavailable); const trackPos = availableTracks.findIndex((t) => t.id === currentTrack.id); if (trackPos >= 0 && availableTracks.length > 0) { - globalPlayer.setQueue(availableTracks, trackPos); - globalPlayer.playTrackFromQueue(); + Player.instance.setQueue(availableTracks, trackPos); + Player.instance.playTrackFromQueue(); } }; } @@ -981,8 +978,7 @@ export async function renderTrackerTrackPage(trackId, container, _ui) { document.title = `${currentTrack.title} - ${artist.name}`; } -export async function initTracker(player) { - globalPlayer = player; +export async function initTracker() { await Promise.all([loadArtistsPopularity(), loadArtistsData()]); } diff --git a/js/ui-interactions.js b/js/ui-interactions.js index 59f2e069b..2dd28cd45 100644 --- a/js/ui-interactions.js +++ b/js/ui-interactions.js @@ -1,9 +1,5 @@ //js/ui-interactions.js import { - SVG_CLOSE, - SVG_BIN, - SVG_HEART, - SVG_DOWNLOAD, formatTime, getTrackTitle, getTrackArtists, @@ -17,6 +13,17 @@ import { db } from './db.js'; import { syncManager } from './accounts/pocketbase.js'; import { showNotification, downloadTracks } from './downloads.js'; import { trackSearchTabChange, trackOpenQueue } from './analytics.js'; +import { + SVG_CLOSE, + SVG_BIN, + SVG_HEART, + SVG_DOWNLOAD, + SVG_HEART_FILLED, + SVG_SQUARE_PEN, + SVG_TRASH, + SVG_EQUAL, +} from './icons.js'; +import { hapticSuccess } from './haptics.js'; export function initializeUIInteractions(player, api, ui) { const sidebar = document.querySelector('.sidebar'); @@ -111,22 +118,19 @@ export function initializeUIInteractions(player, api, ui) { container.innerHTML = ` `; @@ -258,10 +262,7 @@ export function initializeUIInteractions(player, api, ui) { return `
    - - - - + ${SVG_EQUAL(16)}
    ${isBlocked ? '--:--' : formatTime(track.duration)}
    `; @@ -307,10 +308,9 @@ export function initializeUIInteractions(player, api, ui) { syncManager.syncLibraryItem('track', track, added); likeBtn.classList.toggle('active', added); - likeBtn.innerHTML = added - ? SVG_HEART.replace('class="heart-icon"', 'class="heart-icon filled"') - : SVG_HEART; + likeBtn.innerHTML = added ? SVG_HEART_FILLED(20) : SVG_HEART(20); + hapticSuccess(); showNotification(added ? `Added to Liked: ${track.title}` : `Removed from Liked: ${track.title}`); } return; @@ -462,9 +462,7 @@ export function initializeUIInteractions(player, api, ui) { if (likeBtn && track) { const isLiked = await db.isFavorite('track', track.id); likeBtn.classList.toggle('active', isLiked); - likeBtn.innerHTML = isLiked - ? SVG_HEART.replace('class="heart-icon"', 'class="heart-icon filled"') - : SVG_HEART; + likeBtn.innerHTML = isLiked ? SVG_HEART_FILLED(20) : SVG_HEART(20); } }); diff --git a/js/ui.js b/js/ui.js index ae8febf14..59d7a8d4c 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1,12 +1,6 @@ //js/ui.js import { showNotification } from './downloads.js'; import { - SVG_PLAY, - SVG_DOWNLOAD, - SVG_MENU, - SVG_HEART, - SVG_VOLUME, - SVG_MUTE, formatTime, createPlaceholder, trackDataStore, @@ -50,27 +44,46 @@ import { createTrackFromSong, } from './tracker.js'; import { trackSearch, trackChangeSort } from './analytics.js'; -import Hls from 'hls.js'; fontSettings.applyFont(); fontSettings.applyFontSize(); -const SVG_GLOBE = - ''; -const SVG_INSTAGRAM = - ' '; -const SVG_FACEBOOK = - ''; -const SVG_YOUTUBE = - ' youtube [#9E9E9E168] Created with Sketch. '; -const SVG_TWITTER = - ''; -const SVG_LINK = - ''; -const SVG_SOUNDCLOUD = - ' '; -const SVG_APPLE = - ' apple [#9E9E9E173] Created with Sketch. '; +import { + SVG_PLAY, + SVG_DOWNLOAD, + SVG_MENU, + SVG_HEART, + SVG_VOLUME, + SVG_MUTE, + SVG_HEART_FILLED, + SVG_CLOSE, + SVG_SORT, + SVG_BIN, + SVG_TRASH, + SVG_GLOBE, + SVG_INSTAGRAM, + SVG_FACEBOOK, + SVG_YOUTUBE, + SVG_TWITTER, + SVG_LINK, + SVG_SOUNDCLOUD, + SVG_APPLE, + SVG_REPEAT, + SVG_REPEAT_ONE, + SVG_PLAY_LARGE, + SVG_PAUSE_LARGE, + SVG_MINUS, + SVG_SQUARE_PEN, + SVG_SHARE, + SVG_SHUFFLE, + SVG_VIDEO, + SVG_LEFT_ARROW, + SVG_RIGHT_ARROW, + SVG_CLOCK, + SVG_MOVE_UP, + SVG_MOVE_DOWN, + SVG_CHECKBOX, +} from './icons.js'; function sortTracks(tracks, sortType) { if (sortType === 'custom') return [...tracks]; @@ -103,7 +116,27 @@ function sortTracks(tracks, sortType) { } } +const TRACKLIST_HEADER_WITH_LIKE_COL_HTML = ` +
    + # + Title + + Duration + Menu +
    +`; + export class UIRenderer { + static #instance = null; + + static get instance() { + if (!UIRenderer.#instance) { + throw new Error('UIRenderer is not initialized. Call UIRenderer.initialize(api, player) first.'); + } + return UIRenderer.#instance; + } + + /** @private */ constructor(api, player) { this.api = api; this.player = player; @@ -113,6 +146,7 @@ export class UIRenderer { this.visualizer = null; this.renderLock = false; this.lastRecommendedTracks = []; + this.currentArtistId = null; // Listen for dynamic color reset events window.addEventListener('reset-dynamic-color', () => { @@ -131,12 +165,19 @@ export class UIRenderer { }); } + static async initialize(api, player) { + if (UIRenderer.#instance) { + throw new Error('UIRenderer is already initialized'); + } + return (UIRenderer.#instance = new UIRenderer(api, player)); + } + // Helper for Heart Icon createHeartIcon(filled = false) { if (filled) { - return SVG_HEART.replace('class="heart-icon"', 'class="heart-icon filled"'); + return SVG_HEART_FILLED(20); } - return SVG_HEART; + return SVG_HEART(20); } async extractAndApplyColor(url) { @@ -283,7 +324,7 @@ export class UIRenderer { } } if (lyricsBtn) { - if (isLocal || isTracker) lyricsBtn.style.display = 'none'; + if (isLocal) lyricsBtn.style.display = 'none'; else lyricsBtn.style.removeProperty('display'); } @@ -340,7 +381,14 @@ export class UIRenderer { } } - createTrackItemHTML(track, index, showCover = false, hasMultipleDiscs = false, useTrackNumber = false) { + createTrackItemHTML( + track, + index, + showCover = false, + hasMultipleDiscs = false, + useTrackNumber = false, + inlineLike = false + ) { const isUnavailable = track.isUnavailable; const isBlocked = contentBlockingSettings?.shouldHideTrack(track); const isVideo = track.type === 'video'; @@ -352,14 +400,14 @@ export class UIRenderer { if (videoCoverUrl) { trackImageHTML = ``; } else { - trackImageHTML = `
    `; + trackImageHTML = `
    ${SVG_VIDEO(20, { style: 'opacity: 0.7;' })}
    `; } } else if (isVideo && (this.currentPage === 'search' || this.currentPage === 'library')) { const videoCoverUrl = this.api.getVideoCoverUrl(track.imageId); if (videoCoverUrl) { trackImageHTML = ``; } else { - trackImageHTML = `
    `; + trackImageHTML = `
    ${SVG_PLAY(16, { style: 'opacity: 0.7;' })}
    `; } } else { trackImageHTML = this.getCoverHTML( @@ -382,9 +430,10 @@ export class UIRenderer { } const videoIcon = isVideo - ? '' + ? `${SVG_VIDEO(14)}` : ''; const trackNumberHTML = `
    ${showCover ? trackImageHTML : displayIndex}
    `; + const checkboxHTML = `
    ${SVG_CHECKBOX(18)}
    `; const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : ''; const qualityBadge = createQualityBadgeHTML(track); const trackTitle = getTrackTitle(track); @@ -400,7 +449,7 @@ export class UIRenderer { ? '' : ` `; @@ -408,12 +457,23 @@ export class UIRenderer { ? `title="Blocked: ${contentBlockingSettings.isTrackBlocked(track.id) ? 'Track blocked' : contentBlockingSettings.isArtistBlocked(track.artist?.id) ? 'Artist blocked' : 'Album blocked'}"` : ''; + const likeType = isVideo ? 'video' : 'track'; + const showRowLike = inlineLike && !isUnavailable && !isBlocked; + const inlineLikeHTML = showRowLike + ? `
    + +
    ` + : ''; + const classList = [ 'track-item', isVideo ? 'video-track-item' : '', isCurrentTrack ? 'playing' : '', isUnavailable ? 'unavailable' : '', isBlocked ? 'blocked' : '', + showRowLike ? 'track-item--inline-like' : '', ] .filter(Boolean) .join(' '); @@ -425,6 +485,7 @@ export class UIRenderer { ${track.isLocal ? 'data-is-local="true"' : ''} ${isUnavailable ? 'title="This track is currently unavailable"' : ''} ${blockedTitle}> + ${checkboxHTML} ${trackNumberHTML}
    @@ -437,6 +498,7 @@ export class UIRenderer {
    ${getTrackArtistsHTML(track)}${yearDisplay}
    + ${inlineLikeHTML}
    ${isUnavailable || isBlocked ? '--:--' : track.duration ? formatTime(track.duration) : '--:--'}
    ${actionsHTML} @@ -469,10 +531,10 @@ export class UIRenderer { type !== 'artist' ? ` ` : ''; @@ -607,19 +669,10 @@ export class UIRenderer { imageHTML: imageHTML, actionButtonsHTML: ` `, isCompact, @@ -680,16 +733,24 @@ export class UIRenderer { const duration = formatTime(video.duration); const artistName = getTrackArtists(video); - const videoCoverUrl = this.api.getVideoCoverUrl(video.imageId); - const cover = video.image || video.cover; + const videoCoverCandidate = video.imageId || video.image || video.cover || null; + const videoCoverUrl = + videoCoverCandidate && (typeof videoCoverCandidate === 'string' || typeof videoCoverCandidate === 'number') + ? this.api.getVideoCoverUrl(videoCoverCandidate) + : null; + const coverFallback = video.image || video.cover; + const coverPrimitive = + coverFallback != null && (typeof coverFallback === 'string' || typeof coverFallback === 'number') + ? coverFallback + : null; let imageHTML; if (videoCoverUrl) { imageHTML = `${escapeHtml(video.title)}`; - } else if (cover) { - imageHTML = this.getCoverHTML(cover, escapeHtml(video.title)); + } else if (coverPrimitive) { + imageHTML = this.getCoverHTML(coverPrimitive, escapeHtml(video.title)); } else { - imageHTML = `
    `; + imageHTML = `
    ${SVG_PLAY(48, { style: 'opacity: 0.7;' })}
    `; } return ` @@ -698,7 +759,7 @@ export class UIRenderer { ${imageHTML}

    ${escapeHtml(genreName)}

    @@ -2180,12 +2330,19 @@ export class UIRenderer { // Take random samples from each to form seeds const shuffle = (arr) => [...arr].sort(() => Math.random() - 0.5); - const seeds = [ + const combined = [ ...shuffle(playlistTracks).slice(0, 20), ...shuffle(favorites).slice(0, 20), ...shuffle(history).slice(0, 10), ]; + const seenIds = new Set(); + const seeds = combined.filter((t) => { + if (seenIds.has(t.id)) return false; + seenIds.add(t.id); + return true; + }); + return shuffle(seeds); } @@ -2230,7 +2387,7 @@ export class UIRenderer { this.lastRecommendedTracks = filteredTracks; if (filteredTracks.length > 0) { - this.renderListWithTracks(songsContainer, filteredTracks, true); + this.renderListWithTracks(songsContainer, filteredTracks, true, false, false, true); } else { songsContainer.innerHTML = createPlaceholder('No song recommendations found.'); } @@ -2305,6 +2462,7 @@ export class UIRenderer { const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : ''; const qualityBadge = createQualityBadgeHTML(track); const isCompact = cardSettings.isCompactAlbum(); + const likeType = track.type === 'video' ? 'video' : 'track'; return this.createBaseCardHTML({ type: 'track', @@ -2320,7 +2478,7 @@ export class UIRenderer { track.videoUrl || track.album?.videoCoverUrl ), actionButtonsHTML: ` - `, @@ -2654,12 +2812,13 @@ export class UIRenderer { return items.filter((item) => !favoriteIds.has(item.id)); } - setupHlsVideo(video, result, fallbackImg) { + async setupHlsVideo(video, result, fallbackImg) { if (!result) return; const url = typeof result === 'string' ? result : result.videoUrl || result.hlsUrl; if (!url) return; if (url.endsWith('.m3u8')) { + const Hls = (await import('hls.js')).default; if (Hls.isSupported()) { const hls = new Hls(); video._hls = hls; @@ -2694,17 +2853,17 @@ export class UIRenderer { video.play().catch(() => {}); }); } - video.onerror = () => { + video.onerror = async () => { if (result.hlsUrl) { // HLS fallback (for some reason alot of animated covers js dont work on MP4 lol) - this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, fallbackImg); + await this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, fallbackImg); } else { video.replaceWith(fallbackImg); } }; } - replaceVideoArtwork(container, type, id, result) { + async replaceVideoArtwork(container, type, id, result) { const url = result.videoUrl || result.hlsUrl; if (!url) return; @@ -2724,9 +2883,9 @@ export class UIRenderer { video.poster = img.src; - video.onerror = () => { + video.onerror = async () => { if (video.src === result.videoUrl && result.hlsUrl) { - this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, img); + await this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, img); return; } video.replaceWith(img); @@ -2734,9 +2893,9 @@ export class UIRenderer { video.addEventListener( 'error', - (e) => { + async (e) => { if (video.src === result.videoUrl && result.hlsUrl) { - this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, img); + await this.setupHlsVideo(video, { videoUrl: null, hlsUrl: result.hlsUrl }, img); return; } console.warn('Video decoding error:', e); @@ -2747,7 +2906,7 @@ export class UIRenderer { img.replaceWith(video); - this.setupHlsVideo(video, result, img); + await this.setupHlsVideo(video, result, img); } } @@ -2759,11 +2918,13 @@ export class UIRenderer { const artistsContainer = document.getElementById('search-artists-container'); const albumsContainer = document.getElementById('search-albums-container'); const playlistsContainer = document.getElementById('search-playlists-container'); + const podcastsContainer = document.getElementById('search-podcasts-container'); tracksContainer.innerHTML = this.createSkeletonTracks(8, true); artistsContainer.innerHTML = this.createSkeletonCards(6, true); albumsContainer.innerHTML = this.createSkeletonCards(6, false); playlistsContainer.innerHTML = this.createSkeletonCards(6, false); + podcastsContainer.innerHTML = this.createSkeletonCards(6, true); if (this.searchAbortController) { this.searchAbortController.abort(); @@ -2773,19 +2934,13 @@ export class UIRenderer { try { const provider = this.api.getCurrentProvider(); - const [tracksResult, videosResult, artistsResult, albumsResult, playlistsResult] = await Promise.all([ - this.api.searchTracks(query, { signal, provider }), - this.api.searchVideos(query, { signal, provider }), - this.api.searchArtists(query, { signal, provider }), - this.api.searchAlbums(query, { signal, provider }), - this.api.searchPlaylists(query, { signal, provider }), - ]); + const results = await this.api.search(query, { signal, provider }); - let finalTracks = tracksResult.items; - let finalVideos = videosResult.items || []; - let finalArtists = artistsResult.items; - let finalAlbums = albumsResult.items; - let finalPlaylists = playlistsResult.items; + let finalTracks = (results.tracks && results.tracks.items) || []; + let finalVideos = (results.videos && results.videos.items) || []; + let finalArtists = (results.artists && results.artists.items) || []; + let finalAlbums = (results.albums && results.albums.items) || []; + let finalPlaylists = (results.playlists && results.playlists.items) || []; if (finalArtists.length === 0 && finalTracks.length > 0) { const artistMap = new Map(); @@ -2819,7 +2974,7 @@ export class UIRenderer { trackSearch(query, totalResults); if (finalTracks.length) { - this.renderListWithTracks(tracksContainer, finalTracks, true); + this.renderListWithTracks(tracksContainer, finalTracks, true, false, false, true); } else { tracksContainer.innerHTML = createPlaceholder('No tracks found.'); } @@ -2834,7 +2989,12 @@ export class UIRenderer { const el = videosContainer.querySelector(`[data-video-id="${video.id}"]`); if (el) { trackDataStore.set(el, video); + this.updateLikeState(el, 'video', video.id); el.addEventListener('click', (e) => { + if (e.target.closest('.like-btn')) { + e.stopPropagation(); + return; + } if (e.target.closest('.card-play-btn') || e.target.closest('.card-image-container')) { e.stopPropagation(); this.player.playVideo(video); @@ -2879,6 +3039,8 @@ export class UIRenderer { this.updateLikeState(el, 'playlist', playlist.uuid); } }); + + await this.renderPodcastSearchResults(query); } catch (error) { if (error.name === 'AbortError') return; console.error('Search failed:', error); @@ -2887,6 +3049,7 @@ export class UIRenderer { artistsContainer.innerHTML = errorMsg; albumsContainer.innerHTML = errorMsg; playlistsContainer.innerHTML = errorMsg; + podcastsContainer.innerHTML = errorMsg; } } @@ -2903,13 +3066,10 @@ export class UIRenderer { .map( (query) => `
    - - - - + ${SVG_CLOCK(16)} ${escapeHtml(query)} - + ${SVG_CLOSE(14)}
    ` @@ -2975,9 +3135,9 @@ export class UIRenderer { const prodEl = document.getElementById('album-detail-producer'); const tracklistContainer = document.getElementById('album-detail-tracklist'); const playBtn = document.getElementById('play-album-btn'); - if (playBtn) playBtn.innerHTML = `${SVG_PLAY}Play Album`; + if (playBtn) playBtn.innerHTML = `${SVG_PLAY(20)}Play Album`; const dlBtn = document.getElementById('download-album-btn'); - if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download Album`; + if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD(20)}Download Album`; const mixBtn = document.getElementById('album-mix-btn'); if (mixBtn) mixBtn.style.display = 'none'; @@ -3004,7 +3164,7 @@ export class UIRenderer { if (!videoCoverUrl && tracks.length > 0) { const firstTrack = tracks[0]; - this.api.getVideoArtwork(firstTrack.title, getTrackArtists(firstTrack)).then((result) => { + this.api.getVideoArtwork(firstTrack.title, getTrackArtists(firstTrack)).then(async (result) => { if (result && this.currentPage === 'album' && this.currentAlbumId === albumId) { const url = result.videoUrl || result.hlsUrl; if (!url) return; @@ -3022,7 +3182,7 @@ export class UIRenderer { video.style.opacity = '1'; video.poster = currentImageEl.src; - this.setupHlsVideo(video, result, currentImageEl); + await this.setupHlsVideo(video, result, currentImageEl); currentImageEl.replaceWith(video); } } @@ -3041,10 +3201,10 @@ export class UIRenderer { video.preload = 'auto'; video.className = imageEl.className; video.id = imageEl.id; - this.setupHlsVideo(video, videoCoverUrl, imageEl); + await this.setupHlsVideo(video, videoCoverUrl, imageEl); imageEl.replaceWith(video); } else { - this.setupHlsVideo(imageEl, videoCoverUrl, null); + await this.setupHlsVideo(imageEl, videoCoverUrl, null); } } else { if (imageEl.tagName === 'VIDEO') { @@ -3283,7 +3443,7 @@ export class UIRenderer { recommendedTracks = contentBlockingSettings.filterTracks(recommendedTracks); if (recommendedTracks.length > 0) { - this.renderListWithTracks(recommendedContainer, recommendedTracks, true); + this.renderListWithTracks(recommendedContainer, recommendedTracks, true, false, false, true); const trackItems = recommendedContainer.querySelectorAll('.track-item'); trackItems.forEach((item) => { @@ -3292,8 +3452,7 @@ export class UIRenderer { const addToPlaylistBtn = document.createElement('button'); addToPlaylistBtn.className = 'track-action-btn add-to-playlist-btn'; addToPlaylistBtn.title = 'Add to this playlist'; - addToPlaylistBtn.innerHTML = - ''; + addToPlaylistBtn.innerHTML = SVG_MINUS(20); addToPlaylistBtn.onclick = async (e) => { e.stopPropagation(); const trackData = trackDataStore.get(item); @@ -3309,14 +3468,15 @@ export class UIRenderer { const tracklistContainer = document.getElementById('playlist-detail-tracklist'); if (tracklistContainer && updatedPlaylist.tracks) { - tracklistContainer.innerHTML = ` -
    - # - Title - Duration - Menu -
    `; - this.renderListWithTracks(tracklistContainer, updatedPlaylist.tracks, true); + tracklistContainer.innerHTML = TRACKLIST_HEADER_WITH_LIKE_COL_HTML; + this.renderListWithTracks( + tracklistContainer, + updatedPlaylist.tracks, + true, + true, + false, + true + ); if (document.querySelector('.remove-from-playlist-btn')) { this.enableTrackReordering( @@ -3377,9 +3537,9 @@ export class UIRenderer { const descEl = document.getElementById('playlist-detail-description'); const tracklistContainer = document.getElementById('playlist-detail-tracklist'); const playBtn = document.getElementById('play-playlist-btn'); - if (playBtn) playBtn.innerHTML = `${SVG_PLAY}Play`; + if (playBtn) playBtn.innerHTML = `${SVG_PLAY(20)}Play`; const dlBtn = document.getElementById('download-playlist-btn'); - if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download`; + if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD(20)}Download`; const addPlaylistBtn = document.getElementById('add-playlist-to-playlist-btn'); imageEl.src = ''; @@ -3387,15 +3547,7 @@ export class UIRenderer { titleEl.innerHTML = '
    '; metaEl.innerHTML = '
    '; descEl.innerHTML = '
    '; - tracklistContainer.innerHTML = ` -
    - # - Title - Duration - Menu -
    - ${this.createSkeletonTracks(10, true)} - `; + tracklistContainer.innerHTML = `${TRACKLIST_HEADER_WITH_LIKE_COL_HTML}${this.createSkeletonTracks(10, true)}`; try { // Check if it's a user playlist (UUID format) @@ -3485,15 +3637,8 @@ export class UIRenderer { const renderTracks = () => { // Re-fetch container each time because enableTrackReordering clones it const container = document.getElementById('playlist-detail-tracklist'); - container.innerHTML = ` -
    - # - Title - Duration - Menu -
    - `; - this.renderListWithTracks(container, currentTracks, true, true); + container.innerHTML = TRACKLIST_HEADER_WITH_LIKE_COL_HTML; + this.renderListWithTracks(container, currentTracks, true, true, false, true); // Add remove buttons and enable reordering ONLY IF OWNED if (ownedPlaylist) { @@ -3503,8 +3648,7 @@ export class UIRenderer { const removeBtn = document.createElement('button'); removeBtn.className = 'track-action-btn remove-from-playlist-btn'; removeBtn.title = 'Remove from playlist'; - removeBtn.innerHTML = - ''; + removeBtn.innerHTML = SVG_BIN(20); removeBtn.dataset.trackId = currentTracks[index].id; removeBtn.dataset.type = currentTracks[index].type || 'track'; @@ -3637,15 +3781,8 @@ export class UIRenderer { let currentTracks = sortTracks(originalTracks, currentSort); const renderTracks = () => { - tracklistContainer.innerHTML = ` -
    - # - Title - Duration - Menu -
    - `; - this.renderListWithTracks(tracklistContainer, currentTracks, true, true); + tracklistContainer.innerHTML = TRACKLIST_HEADER_WITH_LIKE_COL_HTML; + this.renderListWithTracks(tracklistContainer, currentTracks, true, true, false, true); }; const applySort = (sortType) => { @@ -3758,9 +3895,9 @@ export class UIRenderer { const descEl = document.getElementById('mix-detail-description'); const tracklistContainer = document.getElementById('mix-detail-tracklist'); const playBtn = document.getElementById('play-mix-btn'); - if (playBtn) playBtn.innerHTML = `${SVG_PLAY}Play`; + if (playBtn) playBtn.innerHTML = `${SVG_PLAY(20)}Play`; const dlBtn = document.getElementById('download-mix-btn'); - if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download`; + if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD(20)}Download`; // Skeleton loading imageEl.src = ''; @@ -3768,15 +3905,7 @@ export class UIRenderer { titleEl.innerHTML = '
    '; metaEl.innerHTML = '
    '; descEl.innerHTML = '
    '; - tracklistContainer.innerHTML = ` -
    - # - Title - Duration - Menu -
    - ${this.createSkeletonTracks(10, true)} - `; + tracklistContainer.innerHTML = `${TRACKLIST_HEADER_WITH_LIKE_COL_HTML}${this.createSkeletonTracks(10, true)}`; try { const { mix, tracks } = await this.api.getMix(mixId, provider); @@ -3795,30 +3924,32 @@ export class UIRenderer { if (!videoCoverUrl && (firstTrack.album || firstTrack.type === 'video')) { const fetchArtwork = () => { - this.api.getVideoArtwork(firstTrack.title, getTrackArtists(firstTrack)).then((result) => { - if (result && this.currentPage === 'mix' && this.currentMixId === mixId) { - const url = result.videoUrl || result.hlsUrl; - if (!url) return; - firstTrack.album = firstTrack.album || {}; - firstTrack.album.videoCoverUrl = url; - const currentImageEl = document.getElementById('mix-detail-image'); - if (currentImageEl && currentImageEl.tagName !== 'VIDEO') { - const video = document.createElement('video'); - video.autoplay = true; - video.loop = true; - video.muted = true; - video.playsInline = true; - video.preload = 'auto'; - video.className = currentImageEl.className; - video.id = currentImageEl.id; - video.style.opacity = '1'; - video.poster = currentImageEl.src; - - this.setupHlsVideo(video, result, currentImageEl); - currentImageEl.replaceWith(video); + this.api + .getVideoArtwork(firstTrack.title, getTrackArtists(firstTrack)) + .then(async (result) => { + if (result && this.currentPage === 'mix' && this.currentMixId === mixId) { + const url = result.videoUrl || result.hlsUrl; + if (!url) return; + firstTrack.album = firstTrack.album || {}; + firstTrack.album.videoCoverUrl = url; + const currentImageEl = document.getElementById('mix-detail-image'); + if (currentImageEl && currentImageEl.tagName !== 'VIDEO') { + const video = document.createElement('video'); + video.autoplay = true; + video.loop = true; + video.muted = true; + video.playsInline = true; + video.preload = 'auto'; + video.className = currentImageEl.className; + video.id = currentImageEl.id; + video.style.opacity = '1'; + video.poster = currentImageEl.src; + + await this.setupHlsVideo(video, result, currentImageEl); + currentImageEl.replaceWith(video); + } } - } - }); + }); }; if (firstTrack.type === 'video') { @@ -3885,16 +4016,9 @@ export class UIRenderer { metaEl.textContent = `${tracks.length} tracks β€’ ${formatDuration(totalDuration)}`; descEl.innerHTML = `${mix.subTitle}`; - tracklistContainer.innerHTML = ` -
    - # - Title - Duration - Menu -
    - `; + tracklistContainer.innerHTML = TRACKLIST_HEADER_WITH_LIKE_COL_HTML; - this.renderListWithTracks(tracklistContainer, tracks, true, true); + this.renderListWithTracks(tracklistContainer, tracks, true, true, false, true); // Set play button action playBtn.onclick = () => { @@ -3922,6 +4046,7 @@ export class UIRenderer { async renderArtistPage(artistId, provider = null) { this.showPage('artist'); + this.currentArtistId = artistId; const imageEl = document.getElementById('artist-detail-image'); const nameEl = document.getElementById('artist-detail-name'); @@ -3934,8 +4059,10 @@ export class UIRenderer { const epsSection = document.getElementById('artist-section-eps'); const similarContainer = document.getElementById('artist-detail-similar'); const similarSection = document.getElementById('artist-section-similar'); + const inLibraryContainer = document.getElementById('artist-detail-in-library'); + const inLibrarySection = document.getElementById('artist-section-in-library'); const dlBtn = document.getElementById('download-discography-btn'); - if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}Download Discography`; + if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD(20)}Download Discography`; imageEl.src = ''; imageEl.style.backgroundColor = 'var(--muted)'; @@ -3955,6 +4082,16 @@ export class UIRenderer { if (loadUnreleasedSection) loadUnreleasedSection.style.display = 'none'; if (similarContainer) similarContainer.innerHTML = this.createSkeletonCards(6, true); if (similarSection) similarSection.style.display = 'block'; + if (inLibrarySection) inLibrarySection.style.display = 'none'; + if (inLibraryContainer) { + inLibraryContainer.innerHTML = ''; + inLibraryContainer.hidden = true; + } + // Reset chevron and toggle state + const chevronEl = document.getElementById('in-library-chevron'); + if (chevronEl) chevronEl.style.transform = 'rotate(0deg)'; + const toggleBtn = document.getElementById('in-library-toggle'); + if (toggleBtn) toggleBtn.setAttribute('aria-expanded', 'false'); try { const artist = await this.api.getArtist(artistId, provider); @@ -4189,6 +4326,235 @@ export class UIRenderer { this.renderListWithTracks(tracksContainer, artist.tracks, true); + // "In your library" section: find liked tracks and playlist tracks for this artist + if (inLibraryContainer && inLibrarySection) { + const artistNameLower = artist.name.toLowerCase(); + + const isTrackByArtist = (track) => { + if (track.artists && Array.isArray(track.artists)) { + return track.artists.some( + (a) => + a && + ((artist.id && a.id === artist.id) || + (a.name && a.name.toLowerCase() === artistNameLower)) + ); + } + if (track.artist) { + if (typeof track.artist === 'object') { + if (artist.id && track.artist.id === artist.id) return true; + if (track.artist.name && track.artist.name.toLowerCase() === artistNameLower) return true; + } else if (typeof track.artist === 'string') { + if (track.artist.toLowerCase() === artistNameLower) return true; + } + } + return false; + }; + + const refreshInLibrary = async () => { + try { + const seenIds = new Set(); + const libraryTracks = []; + const trackSourceMap = new Map(); // trackId -> Array<{ label, href }> + + const addSource = (trackId, source) => { + if (!trackSourceMap.has(trackId)) { + trackSourceMap.set(trackId, []); + } + trackSourceMap.get(trackId).push(source); + }; + + // Get liked tracks + const likedTracks = await db.getFavorites('track'); + for (const track of likedTracks) { + if (isTrackByArtist(track)) { + if (!seenIds.has(track.id)) { + seenIds.add(track.id); + libraryTracks.push(track); + } + addSource(track.id, { label: 'Liked Tracks', href: '/library' }); + } + } + + // Get tracks from user playlists + const userPlaylists = await db.getPlaylists(true); + for (const playlist of userPlaylists) { + if (playlist.tracks && Array.isArray(playlist.tracks)) { + for (const track of playlist.tracks) { + if (isTrackByArtist(track)) { + if (!seenIds.has(track.id)) { + seenIds.add(track.id); + libraryTracks.push(track); + } + const label = playlist.name || playlist.title || 'Playlist'; + addSource(track.id, { + label, + href: `/userplaylist/${playlist.id}`, + }); + } + } + } + } + + // Sort alphabetically by title + libraryTracks.sort((a, b) => (a.title || '').localeCompare(b.title || '')); + + if (libraryTracks.length > 0) { + inLibrarySection.style.display = 'block'; + this.renderListWithTracks(inLibraryContainer, libraryTracks, true); + + // Inject source labels into each track's .artist div + const trackElements = inLibraryContainer.querySelectorAll('.track-item'); + trackElements.forEach((el, idx) => { + const track = libraryTracks[idx]; + if (!track) return; + const sources = trackSourceMap.get(track.id); + if (!sources || sources.length === 0) return; + const artistDiv = el.querySelector('.track-item-details .artist'); + if (!artistDiv) return; + + // Extract artist name and year from existing content + const artistLinks = artistDiv.querySelectorAll('.artist-link'); + const artistNames = Array.from(artistLinks) + .map((a) => a.textContent) + .join(', '); + const truncatedArtist = + artistNames.length > 15 ? artistNames.slice(0, 20) + '…' : artistNames; + + // Extract year from text content (pattern: " β€’ 2024") + const fullText = artistDiv.textContent; + const yearMatch = fullText.match(/\sβ€’\s(\d{4})/); + const yearText = yearMatch ? ` β€’ ${yearMatch[1]}` : ''; + + // Build source content + const sourceSpan = document.createElement('span'); + sourceSpan.className = 'library-source'; + + const labelSpan = document.createElement('span'); + labelSpan.className = 'library-source-label'; + labelSpan.textContent = 'Β· Source:\u00a0'; + + const linkSpan = document.createElement('span'); + linkSpan.className = 'library-source-link'; + + sourceSpan.style.cursor = 'pointer'; + sourceSpan.appendChild(labelSpan); + sourceSpan.appendChild(linkSpan); + + if (sources.length === 1) { + const srcLabel = + sources[0].label.length > 15 + ? sources[0].label.slice(0, 15) + '…' + : sources[0].label; + linkSpan.textContent = srcLabel; + sourceSpan.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + navigate(sources[0].href); + }); + } else { + linkSpan.textContent = 'Multiple Playlists'; + sourceSpan.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + + const modal = document.getElementById('goto-playlist-modal'); + const list = document.getElementById('goto-playlist-list'); + const cancelBtn = document.getElementById('goto-playlist-cancel'); + const overlay = modal.querySelector('.modal-overlay'); + + list.innerHTML = ''; + sources.forEach((s) => { + const option = document.createElement('div'); + option.className = 'modal-option'; + option.dataset.href = s.href; + const span = document.createElement('span'); + span.textContent = s.label; + option.appendChild(span); + list.appendChild(option); + }); + + const closeModal = () => { + modal.classList.remove('active'); + }; + + list.onclick = (ev) => { + const option = ev.target.closest('.modal-option'); + if (!option) return; + const href = option.dataset.href; + closeModal(); + if (href) navigate(href); + }; + + cancelBtn.onclick = closeModal; + overlay.onclick = closeModal; + modal.classList.add('active'); + }); + } + + // Rebuild artist div with structured layout + artistDiv.innerHTML = ''; + artistDiv.classList.add('library-artist-flex'); + + const artistNameSpan = document.createElement('span'); + artistNameSpan.className = 'library-artist-name'; + artistNameSpan.textContent = truncatedArtist; + + const yearSpan = document.createElement('span'); + yearSpan.className = 'library-year'; + yearSpan.textContent = yearText; + + artistDiv.appendChild(artistNameSpan); + artistDiv.appendChild(yearSpan); + artistDiv.appendChild(sourceSpan); + }); + } else { + inLibrarySection.style.display = 'none'; + } + } catch (err) { + console.warn('Failed to load library tracks for artist:', err); + inLibrarySection.style.display = 'none'; + } + }; + + // Initial load + refreshInLibrary().then(() => { + inLibraryContainer.hidden = true; + }); + + // Setup chevron toggle (once) + const toggle = document.getElementById('in-library-toggle'); + const chevron = document.getElementById('in-library-chevron'); + if (toggle) { + toggle.onclick = () => { + const isOpen = !inLibraryContainer.hidden; + inLibraryContainer.hidden = isOpen; + toggle.setAttribute('aria-expanded', String(!isOpen)); + if (chevron) { + chevron.style.transform = isOpen ? 'rotate(0deg)' : 'rotate(90deg)'; + } + }; + } + + // Real-time updates: refresh when favorites or playlists change + let refreshTimeout; + const debouncedRefresh = () => { + clearTimeout(refreshTimeout); + refreshTimeout = setTimeout(() => refreshInLibrary(), 300); + }; + + // Cleanup previous listeners before attaching new ones + const cleanupOnNav = () => { + window.removeEventListener('favorites-changed', debouncedRefresh); + window.removeEventListener('playlist-tracks-changed', debouncedRefresh); + window.removeEventListener('popstate', cleanupOnNav); + }; + cleanupOnNav(); + + window.addEventListener('favorites-changed', debouncedRefresh); + window.addEventListener('playlist-tracks-changed', debouncedRefresh); + window.addEventListener('popstate', cleanupOnNav, { once: true }); + } + // Update header like button const artistLikeBtn = document.getElementById('like-artist-btn'); if (artistLikeBtn) { @@ -4354,31 +4720,30 @@ export class UIRenderer { const url = link.url; if (url.includes('tidal.com')) return ''; - if (url.includes('qobuz.com')) return ''; - let icon = SVG_GLOBE; + let icon = SVG_GLOBE(24); let title = 'Website'; if (url.includes('twitter.com') || url.includes('x.com')) { - icon = SVG_TWITTER; + icon = SVG_TWITTER(24); title = 'Twitter'; } else if (url.includes('instagram.com')) { - icon = SVG_INSTAGRAM; + icon = SVG_INSTAGRAM(24); title = 'Instagram'; } else if (url.includes('facebook.com')) { - icon = SVG_FACEBOOK; + icon = SVG_FACEBOOK(24); title = 'Facebook'; } else if (url.includes('youtube.com')) { - icon = SVG_YOUTUBE; + icon = SVG_YOUTUBE(24); title = 'YouTube'; } else if (url.includes('spotify.com') || url.includes('open.spotify.com')) { - icon = SVG_LINK; + icon = SVG_LINK(24); title = 'Spotify'; } else if (url.includes('soundcloud.com')) { - icon = SVG_SOUNDCLOUD; + icon = SVG_SOUNDCLOUD(24); title = 'SoundCloud'; } else if (url.includes('apple.com')) { - icon = SVG_APPLE; + icon = SVG_APPLE(24); title = 'Apple Music'; } @@ -4458,6 +4823,7 @@ export class UIRenderer { if (confirm('Clear all recently played tracks? This cannot be undone.')) { try { await db.clearHistory(); + await syncManager.clearHistory(); container.innerHTML = createPlaceholder("You haven't played any tracks yet."); clearBtn.style.display = 'none'; } catch (err) { @@ -4519,8 +4885,7 @@ export class UIRenderer { const shuffleBtn = document.createElement('button'); shuffleBtn.id = 'shuffle-playlist-btn'; shuffleBtn.className = 'btn-primary'; - shuffleBtn.innerHTML = - 'Shuffle'; + shuffleBtn.innerHTML = `${SVG_SHUFFLE(20)}Shuffle`; shuffleBtn.onclick = () => { const shuffledTracks = [...tracks].sort(() => Math.random() - 0.5); this.player.setQueue(shuffledTracks, 0); @@ -4533,8 +4898,7 @@ export class UIRenderer { sortBtn = document.createElement('button'); sortBtn.id = 'sort-playlist-btn'; sortBtn.className = 'btn-secondary'; - sortBtn.innerHTML = - 'Sort'; + sortBtn.innerHTML = `${SVG_SORT(20)}Sort`; sortBtn.onclick = (e) => { e.stopPropagation(); @@ -4582,15 +4946,13 @@ export class UIRenderer { const editBtn = document.createElement('button'); editBtn.id = 'edit-playlist-btn'; editBtn.className = 'btn-secondary'; - editBtn.innerHTML = - 'Edit'; + editBtn.innerHTML = `${SVG_SQUARE_PEN(24)}Edit`; fragment.appendChild(editBtn); const deleteBtn = document.createElement('button'); deleteBtn.id = 'delete-playlist-btn'; deleteBtn.className = 'btn-secondary danger'; - deleteBtn.innerHTML = - 'Delete'; + deleteBtn.innerHTML = `${SVG_BIN(24)}Delete`; fragment.appendChild(deleteBtn); } @@ -4599,8 +4961,7 @@ export class UIRenderer { const shareBtn = document.createElement('button'); shareBtn.id = 'share-playlist-btn'; shareBtn.className = 'btn-secondary'; - shareBtn.innerHTML = - 'Share'; + shareBtn.innerHTML = `${SVG_SHARE(20)}Share`; shareBtn.onclick = () => { const url = getShareUrl(`/userplaylist/${playlist.id || playlist.uuid}`); @@ -4804,28 +5165,27 @@ export class UIRenderer { ? instance.name || instance.displayName || instance.id || instanceUrl : instanceUrl; const instanceVersion = isObject && instance.version ? String(instance.version) : ''; + const isUser = isObject && instance.isUser; const safeName = escapeHtml(instanceName || 'Unknown instance'); const safeUrl = escapeHtml(instanceUrl || ''); const safeVersion = escapeHtml(instanceVersion); return ` -
  • +
  • -
    ${safeName}
    +
    ${safeName} ${isUser ? 'U' : ''}
    ${safeUrl && safeUrl !== safeName ? `
    ${safeUrl}
    ` : ''} ${safeVersion ? `
    v${safeVersion}
    ` : ''}
    - - + ${ + isUser + ? ` + ` + : '' + }
  • `; @@ -4833,8 +5193,11 @@ export class UIRenderer { .join(''); return ` -
  • - ${type === 'api' ? 'API Instances' : 'Streaming Instances'} +
  • + ${type === 'api' ? 'API Instances' : 'Streaming Instances'} +
  • ${listHtml} `; @@ -4857,8 +5220,7 @@ export class UIRenderer { document.body.classList.add('sidebar-collapsed'); const toggleBtn = document.getElementById('sidebar-toggle'); if (toggleBtn) { - toggleBtn.innerHTML = - ''; + toggleBtn.innerHTML = SVG_RIGHT_ARROW(20); } const imageEl = document.getElementById('track-detail-image'); @@ -4904,7 +5266,7 @@ export class UIRenderer { if (!videoCoverUrl && (track.album || track.type === 'video')) { const fetchArtwork = () => { - this.api.getVideoArtwork(track.title, getTrackArtists(track)).then((result) => { + this.api.getVideoArtwork(track.title, getTrackArtists(track)).then(async (result) => { if (result && this.currentPage === 'track' && this.currentTrackPageId === track.id) { const url = result.videoUrl || result.hlsUrl; if (!url) return; @@ -4923,7 +5285,7 @@ export class UIRenderer { video.style.opacity = '1'; video.poster = currentImageEl.src; - this.setupHlsVideo(video, result, currentImageEl); + await this.setupHlsVideo(video, result, currentImageEl); currentImageEl.replaceWith(video); } } @@ -4959,10 +5321,10 @@ export class UIRenderer { video.preload = 'auto'; video.className = imageEl.className; video.id = imageEl.id; - this.setupHlsVideo(video, videoCoverUrl, imageEl); + await this.setupHlsVideo(video, videoCoverUrl, imageEl); imageEl.replaceWith(video); } else { - this.setupHlsVideo(imageEl, videoCoverUrl, null); + await this.setupHlsVideo(imageEl, videoCoverUrl, null); } } else { if (imageEl.tagName === 'VIDEO') { @@ -5026,4 +5388,208 @@ export class UIRenderer { artistEl.innerHTML = ''; } } + + async renderPodcastsBrowsePage() { + this.showPage('podcasts-browse'); + const trendingContainer = document.getElementById('podcasts-trending-container'); + const recentContainer = document.getElementById('podcasts-recent-container'); + trendingContainer.innerHTML = this.createSkeletonCards(12, true); + recentContainer.innerHTML = this.createSkeletonCards(12, true); + + try { + const { podcastsAPI } = await import('./podcasts-api.js'); + const trendingResult = await podcastsAPI.getTrendingPodcasts({ max: 24 }); + if (trendingResult.items.length > 0) { + trendingContainer.innerHTML = trendingResult.items + .map((podcast) => this.createPodcastCardHTML(podcast)) + .join(''); + this.attachPodcastCardListeners(trendingContainer, trendingResult.items); + } else { + trendingContainer.innerHTML = createPlaceholder('No trending podcasts found.'); + } + } catch (error) { + console.error('Failed to load trending podcasts:', error); + trendingContainer.innerHTML = createPlaceholder('Failed to load trending podcasts.'); + } + + document.title = 'Podcasts - Monochrome Music'; + } + + cleanupPodcastState() { + this.podcastState = null; + } + + async renderPodcastPage(podcastId) { + this.cleanupPodcastState(); + this.showPage('podcasts'); + + this.podcastState = { + id: podcastId, + episodes: [], + offset: 0, + hasMore: true, + isLoading: false, + }; + + const nameEl = document.getElementById('podcasts-detail-name'); + const metaEl = document.getElementById('podcasts-detail-meta'); + const imageEl = document.getElementById('podcasts-detail-image'); + const episodesContainer = document.getElementById('podcasts-episodes-container'); + + nameEl.textContent = 'Loading...'; + metaEl.textContent = ''; + episodesContainer.innerHTML = this.createSkeletonTracks(8, true); + + try { + const { podcastsAPI } = await import('./podcasts-api.js'); + const podcastResult = await podcastsAPI.getPodcastById(podcastId); + + if (podcastResult) { + nameEl.textContent = podcastResult.title; + metaEl.textContent = `${podcastResult.episodeCount} episodes β€’ ${podcastResult.author}`; + if (podcastResult.image) { + imageEl.src = podcastResult.image; + this.setPageBackground(podcastResult.image); + } + + this.podcastState.podcastTitle = podcastResult.title; + const playBtn = document.getElementById('play-podcasts-btn'); + } else { + this.podcastState.podcastTitle = 'Unknown Podcast'; + } + + document.title = `${podcastResult?.title || 'Podcast'} - Monochrome Music`; + + episodesContainer.innerHTML = ''; + await this.loadAllPodcastEpisodes(); + } catch (error) { + console.error('Failed to load podcast:', error); + nameEl.textContent = 'Podcast not found'; + episodesContainer.innerHTML = createPlaceholder('Failed to load podcast.'); + } + } + + async loadAllPodcastEpisodes() { + this.podcastState.isLoading = true; + const episodesContainer = document.getElementById('podcasts-episodes-container'); + episodesContainer.innerHTML = this.createSkeletonTracks(8, true); + + try { + const { podcastsAPI } = await import('./podcasts-api.js'); + const result = await podcastsAPI.getPodcastEpisodes(this.podcastState.id, { + max: 10000, + }); + + this.podcastState.episodes = result.items; + this.podcastState.hasMore = false; + + const podcastTitle = this.podcastState.podcastTitle || 'Unknown Podcast'; + const tracks = result.items.map((ep) => this.transformPodcastEpisodeToTrack(ep, podcastTitle)); + this.renderListWithTracks(episodesContainer, tracks, true); + + const playBtn = document.getElementById('play-podcasts-btn'); + if (playBtn && result.items.length > 0) { + playBtn.onclick = () => { + const tracksToPlay = this.podcastState.episodes.map((ep) => + this.transformPodcastEpisodeToTrack(ep, podcastTitle) + ); + if (this.player) { + this.player.setQueue(tracksToPlay, 0); + this.player.playTrackFromQueue(); + } + }; + } + } catch (error) { + console.error('Failed to load podcast episodes:', error); + episodesContainer.innerHTML = createPlaceholder('Failed to load episodes.'); + } + + this.podcastState.isLoading = false; + } + + async renderPodcastSearchResults(query) { + const podcastsContainer = document.getElementById('search-podcasts-container'); + podcastsContainer.innerHTML = this.createSkeletonCards(12, true); + + try { + const { podcastsAPI } = await import('./podcasts-api.js'); + const result = await podcastsAPI.searchPodcasts(query, { max: 20 }); + + if (result.items.length > 0) { + podcastsContainer.innerHTML = result.items + .map((podcast) => this.createPodcastCardHTML(podcast)) + .join(''); + this.attachPodcastCardListeners(podcastsContainer, result.items); + } else { + podcastsContainer.innerHTML = createPlaceholder('No podcasts found.'); + } + } catch (error) { + console.error('Podcast search failed:', error); + podcastsContainer.innerHTML = createPlaceholder('Failed to search podcasts.'); + } + } + + createPodcastCardHTML(podcast) { + const title = escapeHtml(podcast.title || 'Unknown Podcast'); + const author = escapeHtml(podcast.author || ''); + const image = podcast.image || ''; + const description = escapeHtml((podcast.description || '').substring(0, 120)); + const episodeCount = podcast.episodeCount || 0; + + return ` +
    +
    + ${title} +
    + +
    +
    +
    +

    ${title}

    +

    ${author}

    +

    ${description}${podcast.description?.length > 120 ? '...' : ''}

    + ${episodeCount} episodes +
    +
    + `; + } + + attachPodcastCardListeners(container, podcasts) { + const cards = container.querySelectorAll('.card[data-podcast-id]'); + cards.forEach((card) => { + const podcastId = card.dataset.podcastId; + const podcast = podcasts.find((p) => p.id === podcastId); + if (podcast) { + card.addEventListener('click', () => { + navigate(`/podcasts/${podcastId}`); + }); + } + }); + } + + transformPodcastEpisodeToTrack(episode, podcastTitle = 'Unknown Podcast') { + return { + id: `podcast_${episode.id}`, + title: episode.title, + artist: { id: null, name: podcastTitle }, + artists: [{ id: null, name: podcastTitle }], + album: { + id: null, + title: podcastTitle, + cover: episode.image || episode.feedImage || '', + }, + duration: episode.duration, + explicit: episode.explicit, + dateAdded: episode.datePublished, + isPodcast: true, + enclosureUrl: episode.enclosureUrl, + enclosureType: episode.enclosureType, + enclosureLength: episode.enclosureLength, + episodeNumber: episode.episode, + episodeType: episode.episodeType, + season: episode.season, + description: episode.description, + podcastEpisode: episode, + }; + } } diff --git a/js/utils.js b/js/utils.js index c8214a331..352c8cb5b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,4 +1,6 @@ //js/utils.js +import { modernSettings } from './ModernSettings.js'; +import { SVG_ATMOS } from './icons.js'; import { qualityBadgeSettings, coverArtSizeSettings, trackDateSettings } from './storage.js'; export const QUALITY = 'HI_RES_LOSSLESS'; @@ -10,15 +12,17 @@ export const REPEAT_MODE = { }; export const AUDIO_QUALITIES = { + DOLBY_ATMOS: 'DOLBY_ATMOS', HI_RES_LOSSLESS: 'HI_RES_LOSSLESS', LOSSLESS: 'LOSSLESS', HIGH: 'HIGH', LOW: 'LOW', }; -export const QUALITY_PRIORITY = ['HI_RES_LOSSLESS', 'LOSSLESS', 'HIGH', 'LOW']; +export const QUALITY_PRIORITY = ['DOLBY_ATMOS', 'HI_RES_LOSSLESS', 'LOSSLESS', 'HIGH', 'LOW']; export const QUALITY_TOKENS = { + DOLBY_ATMOS: ['DOLBY_ATMOS', 'ATMOS'], HI_RES_LOSSLESS: [ 'HI_RES_LOSSLESS', 'HIRES_LOSSLESS', @@ -38,31 +42,14 @@ export const QUALITY_TOKENS = { export const RATE_LIMIT_ERROR_MESSAGE = 'Too Many Requests. Please wait a moment and try again.'; -export const SVG_PLAY = - ''; -export const SVG_PAUSE = - ''; -export const SVG_VOLUME = - ''; -export const SVG_MUTE = - ''; -export const SVG_DOWNLOAD = - ''; -export const SVG_MENU = - ''; -export const SVG_HEART = - ''; -export const SVG_CLOSE = - ''; -export const SVG_BIN = - ''; -export const SVG_MIX = - ''; - export const formatTime = (seconds) => { if (isNaN(seconds)) return '0:00'; - const m = Math.floor(seconds / 60); + const h = Math.floor(seconds / 3600); + const m = Math.floor((seconds % 3600) / 60); const s = Math.floor(seconds % 60); + if (h > 0) { + return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; + } return `${m}:${String(s).padStart(2, '0')}`; }; @@ -90,6 +77,45 @@ export const sanitizeForFilename = (value) => { .trim(); }; +/** + * Sanitizes a single path component (no slashes allowed in the output). + * Invalid filesystem characters are replaced with underscores. + */ +export const sanitizeForPathComponent = (value) => { + if (!value) return 'Unknown'; + return value + .replace(/[\\/:*?"<>|]/g, '_') + .replace(/\s+/g, ' ') + .trim(); +}; + +/** + * Like {@link formatTemplate} but allows `/` in the template for nested + * directory structures. Each path component has invalid characters replaced, + * the path is normalised to forward-slash separators, and empty components, + * `.`, and `..` segments are stripped. + */ +export const formatPathTemplate = (template, data) => { + let result = replaceTokens(template, { + discNumber: String(Number(data.discNumber || 1)), + trackNumber: data.trackNumber ? String(data.trackNumber).padStart(2, '0') : '00', + artist: sanitizeForPathComponent(data.artist || 'Unknown Artist'), + title: sanitizeForPathComponent(data.title || 'Unknown Title'), + album: sanitizeForPathComponent(data.album || 'Unknown Album'), + albumArtist: sanitizeForPathComponent(data.albumArtist || 'Unknown Artist'), + albumTitle: sanitizeForPathComponent(data.albumTitle || 'Unknown Album'), + year: sanitizeForPathComponent(String(data.year || 'Unknown')), + }); + + // Normalise separators, collapse duplicates, strip . and .. + return result + .replace(/\\/g, '/') + .split('/') + .map((p) => p.trim()) + .filter((p) => p !== '' && p !== '.' && p !== '..') + .join('/'); +}; + /** * Detects audio format from DataView of first bytes * @param {DataView} view - DataView of first 12 bytes of audio file @@ -108,6 +134,17 @@ export const detectAudioFormat = (view, mimeType = '') => { return 'flac'; } + // Check for OGG signature: "OggS" (0x4F 0x67 0x67 0x53) + if ( + view.byteLength >= 4 && + view.getUint8(0) === 0x4f && // O + view.getUint8(1) === 0x67 && // g + view.getUint8(2) === 0x67 && // g + view.getUint8(3) === 0x53 // S + ) { + return 'ogg'; + } + // Check for MP4/M4A signature: "ftyp" at offset 4 if ( view.byteLength >= 8 && @@ -129,6 +166,22 @@ export const detectAudioFormat = (view, mimeType = '') => { return 'mp3'; } + // Detect RIFF/WAVE by "RIFF" at offset 0 and "WAVE" at offset 8 (only in dev mode) + if ( + import.meta.env.DEV && + view.byteLength >= 12 && + view.getUint8(0) === 0x52 && // R + view.getUint8(1) === 0x49 && // I + view.getUint8(2) === 0x46 && // F + view.getUint8(3) === 0x46 && // F + view.getUint8(8) === 0x57 && // W + view.getUint8(9) === 0x41 && // A + view.getUint8(10) === 0x56 && // V + view.getUint8(11) === 0x45 // E + ) { + return 'wav'; + } + // Check for MPEG frame sync (0xFF 0xFB or 0xFF 0xFA) if (view.byteLength >= 2 && view.getUint8(0) === 0xff && (view.getUint8(1) & 0xe0) === 0xe0) { return 'mp3'; @@ -153,6 +206,7 @@ export const detectAudioFormat = (view, mimeType = '') => { // Fallback to MIME type if (mimeType === 'audio/flac') return 'flac'; + if (mimeType === 'audio/ogg') return 'ogg'; if (mimeType === 'audio/mp4' || mimeType === 'audio/x-m4a') return 'mp4'; if (mimeType === 'audio/mp3' || mimeType === 'audio/mpeg') return 'mp3'; @@ -177,8 +231,10 @@ export const getExtensionFromBlob = async (blob) => { if (format) return format; if (blob.type.includes('video')) return 'mp4'; - if (blob.type === 'audio/mp4' || blob.type === 'audio/x-m4a') return 'm4a'; - if (blob.type === 'audio/mpeg' || blob.type === 'audio/mp3') return 'mp3'; + if (blob.type === 'audio/flac') return 'flac'; + if (blob.type === 'audio/ogg') return 'ogg'; + if (blob.type === 'audio/mp4' || blob.type === 'audio/x-m4a') return 'mp4'; + if (blob.type === 'audio/mp3' || blob.type === 'audio/mpeg') return 'mp3'; return 'flac'; }; @@ -187,21 +243,21 @@ export const getExtensionForQuality = (quality) => { switch (quality) { case 'LOW': case 'HIGH': + case 'DOLBY_ATMOS': return 'm4a'; - case 'MP3_320': - return 'mp3'; default: return 'flac'; } }; export const buildTrackFilename = (track, quality, extension = null) => { - const template = localStorage.getItem('filename-template') || '{trackNumber} - {artist} - {title}'; + const template = modernSettings.filenameTemplate; const ext = extension || getExtensionForQuality(quality); const artistName = track.artist?.name || track.artists?.[0]?.name || 'Unknown Artist'; const data = { + discNumber: getTrackDiscNumber(track) || 1, trackNumber: track.trackNumber, artist: artistName, title: getTrackTitle(track), @@ -236,7 +292,9 @@ export const createQualityBadgeHTML = (track) => { if (!qualityBadgeSettings.isEnabled()) return ''; const quality = deriveTrackQuality(track); - if (quality === 'HI_RES_LOSSLESS') { + if (quality === 'DOLBY_ATMOS') { + return `${SVG_ATMOS(20)}`; + } else if (quality === 'HI_RES_LOSSLESS') { return 'HD'; } return ''; @@ -358,17 +416,17 @@ export const getTrackArtistsHTML = (track = {}, { fallback = 'Unknown Artist' } return fallback; }; -export const formatTemplate = (template, data) => { - let result = template; - result = result.replace(/\{trackNumber\}/g, data.trackNumber ? String(data.trackNumber).padStart(2, '0') : '00'); - result = result.replace(/\{artist\}/g, sanitizeForFilename(data.artist || 'Unknown Artist')); - result = result.replace(/\{title\}/g, sanitizeForFilename(data.title || 'Unknown Title')); - result = result.replace(/\{album\}/g, sanitizeForFilename(data.album || 'Unknown Album')); - result = result.replace(/\{albumArtist\}/g, sanitizeForFilename(data.albumArtist || 'Unknown Artist')); - result = result.replace(/\{albumTitle\}/g, sanitizeForFilename(data.albumTitle || 'Unknown Album')); - result = result.replace(/\{year\}/g, data.year || 'Unknown'); - return result; -}; +export const formatTemplate = (template, data) => + replaceTokens(template, { + discNumber: String(Number(data.discNumber || 1)), + trackNumber: data.trackNumber ? String(data.trackNumber).padStart(2, '0') : '00', + artist: sanitizeForFilename(data.artist || 'Unknown Artist'), + title: sanitizeForFilename(data.title || 'Unknown Title'), + album: sanitizeForFilename(data.album || 'Unknown Album'), + albumArtist: sanitizeForFilename(data.albumArtist || 'Unknown Artist'), + albumTitle: sanitizeForFilename(data.albumTitle || 'Unknown Album'), + year: data.year || 'Unknown', + }); export const calculateTotalDuration = (tracks) => { if (!Array.isArray(tracks) || tracks.length === 0) return 0; @@ -629,3 +687,84 @@ export function getTrackCoverId(track) { null ); } + +/** + * Converts a value to a positive integer. + * @param {*} value - The value to convert to a positive integer. + * @returns {number|null} The parsed positive integer, or null if the value is not a finite positive number. + */ +export function toPositiveInt(value) { + const parsed = parseInt(value, 10); + return Number.isFinite(parsed) && parsed > 0 ? parsed : null; +} + +/** + * Extracts the disc number from a track object by checking multiple possible property names. + * @param {Object} track - The track object to extract the disc number from. + * @returns {number|null} The disc number as a positive integer, or null if no valid disc number is found. + */ +export function getTrackDiscNumber(track) { + const candidates = [ + track?.volumeNumber, + track?.discNumber, + track?.mediaNumber, + track?.media_number, + track?.volume, + track?.disc, + track?.volume?.number, + track?.disc?.number, + track?.media?.number, + track?.disc, + track?.disc_no, + track?.discNo, + track?.disc_number, + track?.mediaMetadata?.discNumber, + ]; + + for (const candidate of candidates) { + const parsed = toPositiveInt(candidate); + if (parsed) return parsed; + } + return null; +} + +/** + * Executes a function with a fallback error handler. + * Works with both synchronous and asynchronous callbacks. + * + * If the callback returns a Promise, the result will also be a Promise. + * + * @template T + * @param {() => T | Promise} fn Function to execute + * @param {(error: unknown) => T | Promise} onError Error handler + * @returns {T | Promise} + */ +export function tryCatch(fn, onError) { + try { + const result = fn(); + + if (result instanceof Promise) { + return result.catch(onError); + } + + return result; + } catch (err) { + return onError(err); + } +} + +/** + * Replace `{token}` placeholders in a template string. + * + * Replacement values are inserted verbatim and are NOT reprocessed, + * preventing cascading replacements if values contain token patterns. + * + * @param {string} template The input string containing tokens like `{tokenName}` + * @param {Record} tokens An object of tokens to replace and the replacement values. + * @returns {string} The string with valid tokens replaced + */ +export function replaceTokens(template, tokens) { + return template.replace(/{([^{}]+)}/g, (match, key) => { + return key in tokens ? tokens[key] : match; + }); +} diff --git a/js/visualizer.js b/js/visualizer.js index 2e58dae87..5cfdc2f75 100644 --- a/js/visualizer.js +++ b/js/visualizer.js @@ -1,10 +1,5 @@ // js/visualizer.js import { visualizerSettings } from './storage.js'; -import { LCDPreset } from './visualizers/lcd.js'; -import { ParticlesPreset } from './visualizers/particles.js'; -import { UnknownPleasuresWebGL } from './visualizers/unknown_pleasures_webgl.js'; -import { ButterchurnPreset } from './visualizers/butterchurn.js'; -import { KawarpPreset } from './visualizers/kawarp.js'; import { audioContextManager } from './audio-context.js'; export class Visualizer { @@ -12,21 +7,10 @@ export class Visualizer { this.canvas = canvas; this.ctx = null; this.audio = audio; - this.audioContext = null; this.analyser = null; - this.isActive = false; this.animationId = null; - - this.presets = { - lcd: new LCDPreset(), - particles: new ParticlesPreset(), - 'unknown-pleasures': new UnknownPleasuresWebGL(), - butterchurn: new ButterchurnPreset(), - kawarp: new KawarpPreset(), - }; - this.activePresetKey = visualizerSettings.getPreset(); // ---- AUDIO BUFFERS (REUSED) ---- @@ -51,6 +35,19 @@ export class Visualizer { this._resizeBound = () => this.resize(); } + /** + * Must be called after class is constructed! + */ + async initPresets() { + this.presets = { + lcd: new (await import('./visualizers/lcd.js')).LCDPreset(), + particles: new (await import('./visualizers/particles.js')).ParticlesPreset(), + 'unknown-pleasures': new (await import('./visualizers/unknown_pleasures_webgl.js')).UnknownPleasuresWebGL(), + butterchurn: new (await import('./visualizers/butterchurn.js')).ButterchurnPreset(), + kawarp: new (await import('./visualizers/kawarp.js')).KawarpPreset(), + }; + } + updateDimming() { if (!this.canvas || !this.canvas.parentElement) return; const dimAmount = visualizerSettings.getDimAmount(); @@ -61,7 +58,7 @@ export class Visualizer { return this.presets[this.activePresetKey] || this.presets['lcd']; } - init() { + async init() { // Ensure shared audio context is initialized if (!audioContextManager.isReady()) { audioContextManager.init(this.audio); diff --git a/license b/license index d3af583a5..424e8c754 100644 --- a/license +++ b/license @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2026 Monochrome-Team + Copyright 2026 Monochrome Team Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 000000000..9122c6a2b --- /dev/null +++ b/nginx.conf @@ -0,0 +1,15 @@ +server { + listen 4173; + listen [::]:4173; + + root /usr/share/nginx/html; + index index.html; + + location ~* \.(?:css|js|mjs|map|json|wasm|mp3|flac|wav|ogg|png|jpg|jpeg|svg|webp|ico|gz|br|utf|ttf|woff2?)$ { + try_files $uri =404; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/package-lock.json b/package-lock.json index d71a18e8d..975392bf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,13 +27,18 @@ "appwrite": "^23.0.0", "butterchurn": "^2.6.7", "butterchurn-presets": "^2.4.7", + "client-zip": "^2.5.0", "cookie-session": "^2.1.1", - "dashjs": "^5.1.1", + "eventemitter3": "^5.0.4", + "events": "^3.3.0", "fuse.js": "^7.1.0", "hls.js": "^1.6.15", "jose": "^6.2.0", "pocketbase": "^0.26.8", - "taglib-wasm": "^1.0.5", + "shaka-player": "^5.0.7", + "simple-icons": "^16.12.0", + "svgo": "^4.0.1", + "url-toolkit": "^2.2.5", "uuid": "^13.0.0" }, "devDependencies": { @@ -55,10 +60,24 @@ "wrangler": "^4.71.0" } }, + "node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", @@ -71,8 +90,6 @@ }, "node_modules/@babel/compat-data": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -80,8 +97,6 @@ }, "node_modules/@babel/core": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.29.0", @@ -108,10 +123,8 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -127,8 +140,6 @@ }, "node_modules/@babel/generator": { "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "dependencies": { "@babel/parser": "^7.29.0", @@ -143,8 +154,6 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, "dependencies": { "@babel/types": "^7.27.3" @@ -155,8 +164,6 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "dependencies": { "@babel/compat-data": "^7.28.6", @@ -169,10 +176,24 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -190,10 +211,16 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -207,6 +234,14 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", @@ -242,8 +277,6 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -251,8 +284,6 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dev": true, "dependencies": { "@babel/traverse": "^7.28.5", @@ -264,8 +295,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "dependencies": { "@babel/traverse": "^7.28.6", @@ -277,8 +306,6 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.28.6", @@ -294,8 +321,6 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dev": true, "dependencies": { "@babel/types": "^7.27.1" @@ -306,8 +331,6 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "engines": { "node": ">=6.9.0" @@ -315,8 +338,6 @@ }, "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -332,8 +353,6 @@ }, "node_modules/@babel/helper-replace-supers": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", @@ -349,8 +368,6 @@ }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dev": true, "dependencies": { "@babel/traverse": "^7.27.1", @@ -362,8 +379,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -371,8 +386,6 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "engines": { "node": ">=6.9.0" @@ -380,8 +393,6 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -389,8 +400,6 @@ }, "node_modules/@babel/helper-wrap-function": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", "dev": true, "dependencies": { "@babel/template": "^7.28.6", @@ -402,22 +411,18 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", "dev": true, "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.2", "dev": true, "dependencies": { "@babel/types": "^7.29.0" @@ -431,8 +436,6 @@ }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -447,8 +450,6 @@ }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -462,8 +463,6 @@ }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -477,8 +476,6 @@ }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -494,8 +491,6 @@ }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -510,8 +505,6 @@ }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -522,8 +515,6 @@ }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -537,8 +528,6 @@ }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -552,8 +541,6 @@ }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -568,8 +555,6 @@ }, "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -583,8 +568,6 @@ }, "node_modules/@babel/plugin-transform-async-generator-functions": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", - "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -600,8 +583,6 @@ }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.28.6", @@ -617,8 +598,6 @@ }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -632,8 +611,6 @@ }, "node_modules/@babel/plugin-transform-block-scoping": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -647,8 +624,6 @@ }, "node_modules/@babel/plugin-transform-class-properties": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -663,8 +638,6 @@ }, "node_modules/@babel/plugin-transform-class-static-block": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -679,8 +652,6 @@ }, "node_modules/@babel/plugin-transform-classes": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -699,8 +670,6 @@ }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -715,8 +684,6 @@ }, "node_modules/@babel/plugin-transform-destructuring": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -731,8 +698,6 @@ }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -747,8 +712,6 @@ }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -762,8 +725,6 @@ }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -778,8 +739,6 @@ }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -793,8 +752,6 @@ }, "node_modules/@babel/plugin-transform-explicit-resource-management": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -809,8 +766,6 @@ }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -824,8 +779,6 @@ }, "node_modules/@babel/plugin-transform-export-namespace-from": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -839,8 +792,6 @@ }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -855,8 +806,6 @@ }, "node_modules/@babel/plugin-transform-function-name": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", @@ -872,8 +821,6 @@ }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -887,8 +834,6 @@ }, "node_modules/@babel/plugin-transform-literals": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -902,8 +847,6 @@ }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -917,8 +860,6 @@ }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -932,8 +873,6 @@ }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -948,8 +887,6 @@ }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.6", @@ -964,8 +901,6 @@ }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.6", @@ -982,8 +917,6 @@ }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -998,8 +931,6 @@ }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -1014,8 +945,6 @@ }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1029,8 +958,6 @@ }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1044,8 +971,6 @@ }, "node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1059,8 +984,6 @@ }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", @@ -1078,8 +1001,6 @@ }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1094,8 +1015,6 @@ }, "node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1109,8 +1028,6 @@ }, "node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -1125,8 +1042,6 @@ }, "node_modules/@babel/plugin-transform-parameters": { "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1140,8 +1055,6 @@ }, "node_modules/@babel/plugin-transform-private-methods": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -1156,8 +1069,6 @@ }, "node_modules/@babel/plugin-transform-private-property-in-object": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -1173,8 +1084,6 @@ }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1188,8 +1097,6 @@ }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", - "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1203,8 +1110,6 @@ }, "node_modules/@babel/plugin-transform-regexp-modifiers": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -1219,8 +1124,6 @@ }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1234,8 +1137,6 @@ }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1249,8 +1150,6 @@ }, "node_modules/@babel/plugin-transform-spread": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -1265,8 +1164,6 @@ }, "node_modules/@babel/plugin-transform-sticky-regex": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1280,8 +1177,6 @@ }, "node_modules/@babel/plugin-transform-template-literals": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1295,8 +1190,6 @@ }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1310,8 +1203,6 @@ }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1325,8 +1216,6 @@ }, "node_modules/@babel/plugin-transform-unicode-property-regex": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -1341,8 +1230,6 @@ }, "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1357,8 +1244,6 @@ }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -1372,9 +1257,7 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", - "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", + "version": "7.29.2", "dev": true, "dependencies": { "@babel/compat-data": "^7.29.0", @@ -1455,10 +1338,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1479,8 +1368,6 @@ }, "node_modules/@babel/template": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.28.6", @@ -1493,8 +1380,6 @@ }, "node_modules/@babel/traverse": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.29.0", @@ -1528,8 +1413,6 @@ }, "node_modules/@babel/types": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -1541,8 +1424,6 @@ }, "node_modules/@cacheable/memory": { "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.8.tgz", - "integrity": "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==", "dev": true, "dependencies": { "@cacheable/utils": "^2.4.0", @@ -1578,1629 +1459,1440 @@ }, "node_modules/@cacheable/utils": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.0.tgz", - "integrity": "sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ==", "dev": true, "dependencies": { "hashery": "^1.5.0", "keyv": "^5.6.0" } }, - "node_modules/@cacheable/utils/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", - "dev": true, - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, "node_modules/@capacitor/android": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-7.6.0.tgz", - "integrity": "sha512-xpfAOGcgeQnTw8C0E9nLjW15lQ6TL2ccieZks93hNiQYknnQT8FQaH2paMYkLYrQ0JfRImdBXbQ1u6sZ4kVa3w==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.2.0.tgz", + "integrity": "sha512-XLm5OsWLPfXQxDxzFS7SOdMEgGvW+2c7TGLXkTR2cSKdkWK5Abns4imlT5qghKYhjM9r74IrDkBWg/9ALUGNKQ==", "license": "MIT", "peerDependencies": { - "@capacitor/core": "^7.6.0" + "@capacitor/core": "^8.2.0" } }, "node_modules/@capacitor/app": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-7.1.2.tgz", - "integrity": "sha512-d4I/oF/PRu4megL7/IGKYfe5j7yzSON1FRFgq6kH+m5kH6g7V+wyjHRLauCzGNjdRx4S+nWOumINds0qcRBtKg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-8.0.1.tgz", + "integrity": "sha512-yeG3yyA0ETKqvgqexwHMBlmVOF13A1hRXzv/km0Ptv5TrNIZvZJK4MTI3uiqvnbHrzoJGP5DwWAjEXEfi90v3Q==", "license": "MIT", "peerDependencies": { - "@capacitor/core": ">=7.0.0" + "@capacitor/core": ">=8.0.0" } }, - "node_modules/@capacitor/browser": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-7.0.4.tgz", - "integrity": "sha512-XjooNDHEalQoMAb5/Ip7pGcPCIPHEaBv/s/B6K83qVZE66MXC/6enhw18TNaMNtL7U8bGOe6tEG1FFbQVf3PHw==", - "license": "MIT", - "peerDependencies": { - "@capacitor/core": ">=7.0.0" + "node_modules/@capacitor/assets": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@capacitor/assets/-/assets-3.0.5.tgz", + "integrity": "sha512-ohz/OUq61Y1Fc6aVSt0uDrUdeOA7oTH4pkWDbv/8I3UrPjH7oPkzYhShuDRUjekNp9RBi198VSFdt0CetpEOzw==", + "dev": true, + "dependencies": { + "@capacitor/cli": "^5.3.0", + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@trapezedev/project": "^7.0.10", + "commander": "8.3.0", + "debug": "4.3.4", + "fs-extra": "10.1.0", + "node-fetch": "2.7.0", + "node-html-parser": "5.4.2", + "sharp": "0.32.6", + "tslib": "2.6.2", + "yargs": "17.7.2" + }, + "bin": { + "capacitor-assets": "bin/capacitor-assets" + }, + "engines": { + "node": ">=10.3.0" } }, - "node_modules/@capacitor/cli": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-7.6.0.tgz", - "integrity": "sha512-3PL8xIgXLj1037NqmuzoKXNOi80AdY7eSCnX6/A7RfjFqT8TEiCL+PlHsHtg6/BSZGSmmxGGBjH3nXrNCRoFhw==", + "node_modules/@capacitor/assets/node_modules/@capacitor/cli": { + "version": "5.7.8", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.7.8.tgz", + "integrity": "sha512-qN8LDlREMhrYhOvVXahoJVNkP8LP55/YPRJrzTAFrMqlNJC18L3CzgWYIblFPnuwfbH/RxbfoZT/ydkwgVpMrw==", + "dev": true, "license": "MIT", "dependencies": { - "@ionic/cli-framework-output": "^2.2.8", - "@ionic/utils-subprocess": "^3.0.1", - "@ionic/utils-terminal": "^2.3.5", - "commander": "^12.1.0", - "debug": "^4.4.0", + "@ionic/cli-framework-output": "^2.2.5", + "@ionic/utils-fs": "^3.1.6", + "@ionic/utils-subprocess": "^2.1.11", + "@ionic/utils-terminal": "^2.3.3", + "commander": "^9.3.0", + "debug": "^4.3.4", "env-paths": "^2.2.0", - "fs-extra": "^11.2.0", - "kleur": "^4.1.5", - "native-run": "^2.0.3", + "kleur": "^4.1.4", + "native-run": "^2.0.0", "open": "^8.4.0", - "plist": "^3.1.0", + "plist": "^3.0.5", "prompts": "^2.4.2", - "rimraf": "^6.0.1", - "semver": "^7.6.3", - "tar": "^7.5.3", - "tslib": "^2.8.1", - "xml2js": "^0.6.2" + "rimraf": "^4.4.1", + "semver": "^7.3.7", + "tar": "^6.1.11", + "tslib": "^2.4.0", + "xml2js": "^0.5.0" }, "bin": { "cap": "bin/capacitor", "capacitor": "bin/capacitor" }, "engines": { - "node": ">=20.0.0" + "node": ">=16.0.0" } }, - "node_modules/@capacitor/cli/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/@capacitor/assets/node_modules/@capacitor/cli/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": "^12.20.0 || >=14" } }, - "node_modules/@capacitor/cli/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@capacitor/assets/node_modules/@ionic/utils-process": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.11.tgz", + "integrity": "sha512-Uavxn+x8j3rDlZEk1X7YnaN6wCgbCwYQOeIjv/m94i1dzslqWhqIHEqxEyeE8HsT5Negboagg7GtQiABy+BLbA==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.4", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@capacitor/cli/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "node_modules/@capacitor/assets/node_modules/@ionic/utils-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.6.tgz", + "integrity": "sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA==", + "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "debug": "^4.0.0", + "tslib": "^2.0.1" }, "engines": { - "node": ">=14.14" + "node": ">=16.0.0" } }, - "node_modules/@capacitor/cli/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@capacitor/assets/node_modules/@ionic/utils-subprocess": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz", + "integrity": "sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.11", + "@ionic/utils-stream": "3.1.6", + "@ionic/utils-terminal": "2.3.4", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" } }, - "node_modules/@capacitor/core": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.6.0.tgz", - "integrity": "sha512-K6LEvgxW6Nd6uNWHj3U512hUtB4kln71TvVgdvwJRFMLySpUrWwb/A8Q7c3QGogvPvgOjN1U65onkyRTihPGwA==", + "node_modules/@capacitor/assets/node_modules/@ionic/utils-terminal": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.4.tgz", + "integrity": "sha512-cEiMFl3jklE0sW60r8JHH3ijFTwh/jkdEKWbylSyExQwZ8pPuwoXz7gpkWoJRLuoRHHSvg+wzNYyPJazIHfoJA==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@capacitor/dialog": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/dialog/-/dialog-7.0.4.tgz", - "integrity": "sha512-7W41dohW/vGmLIpqmrvUmhznyFjXK/UPXDU2PHRjV91JbukUSUXdYsvrUPgYW/Nph+SQXyLIv/9GmQFPpLpo/Q==", - "license": "MIT", - "peerDependencies": { - "@capacitor/core": ">=7.0.0" - } + "node_modules/@capacitor/assets/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" }, - "node_modules/@capacitor/filesystem": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-7.1.8.tgz", - "integrity": "sha512-Qpw/2SE4/CzqAUvGgSM9hw/uXQ5qoOaF4wxbToXwpAaKPS+tzletS1h5ti3jjLmGcqizTs2sEXMtcsARW/Ceew==", + "node_modules/@capacitor/assets/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, "license": "MIT", "dependencies": { - "@capacitor/synapse": "^1.0.3" - }, - "peerDependencies": { - "@capacitor/core": ">=7.0.0" - } - }, - "node_modules/@capacitor/screen-orientation": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/screen-orientation/-/screen-orientation-7.0.4.tgz", - "integrity": "sha512-xWeWnZsV6z1bXxlOnSi3ynrFMK/JICryAuLnIvGL069BHS05nvxwu15d0xMZiMZWkoucNEAN60vyIYGGqz5IWA==", - "license": "MIT", - "peerDependencies": { - "@capacitor/core": ">=7.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/@capacitor/share": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/share/-/share-7.0.4.tgz", - "integrity": "sha512-wNXxmXUcChrtbZ5jQv8scFIbIGKo3rk6B7qpWySxfUhYJP5NANgAqQ9Z69m0k/zYsucdh66SBU7XW1ykd9aUug==", - "license": "MIT", - "peerDependencies": { - "@capacitor/core": ">=7.0.0" + "node_modules/@capacitor/assets/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" } }, - "node_modules/@capacitor/synapse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz", - "integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==", - "license": "ISC" - }, - "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", - "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "node_modules/@capacitor/assets/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "license": "MIT OR Apache-2.0", + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">= 12" } }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.15.0.tgz", - "integrity": "sha512-EGYmJaGZKWl+X8tXxcnx4v2bOZSjQeNI5dWFeXivgX9+YCT69AkzHHwlNbVpqtEUTbew8eQurpyOpeN8fg00nw==", + "node_modules/@capacitor/assets/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT OR Apache-2.0", - "peerDependencies": { - "unenv": "2.0.0-rc.24", - "workerd": "1.20260301.1 || ~1.20260302.1 || ~1.20260303.1 || ~1.20260304.1 || >1.20260305.0 <2.0.0-0" + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" }, "peerDependenciesMeta": { - "workerd": { + "supports-color": { "optional": true } } }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260301.1.tgz", - "integrity": "sha512-+kJvwociLrvy1JV9BAvoSVsMEIYD982CpFmo/yMEvBwxDIjltYsLTE8DLi0mCkGsQ8Ygidv2fD9wavzXeiY7OQ==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/assets/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=16" + "node": ">=12" } }, - "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260301.1.tgz", - "integrity": "sha512-PPIetY3e67YBr9O4UhILK8nbm5TqUDl14qx4rwFNrRSBOvlzuczzbd4BqgpAtbGVFxKp1PWpjAnBvGU/OI/tLQ==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/assets/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, "engines": { - "node": ">=16" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260301.1.tgz", - "integrity": "sha512-Gu5vaVTZuYl3cHa+u5CDzSVDBvSkfNyuAHi6Mdfut7TTUdcb3V5CIcR/mXRSyMXzEy9YxEWIfdKMxOMBjupvYQ==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/assets/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC" + }, + "node_modules/@capacitor/assets/node_modules/minimatch": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.7.tgz", + "integrity": "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=16" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260301.1.tgz", - "integrity": "sha512-igL1pkyCXW6GiGpjdOAvqMi87UW0LMc/+yIQe/CSzuZJm5GzXoAMrwVTkCFnikk6JVGELrM5x0tGYlxa0sk5Iw==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/assets/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", "engines": { - "node": ">=16" + "node": ">=8" } }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260301.1.tgz", - "integrity": "sha512-Q0wMJ4kcujXILwQKQFc1jaYamVsNvjuECzvRrTI8OxGFMx2yq9aOsswViE4X1gaS2YQQ5u0JGwuGi5WdT1Lt7A==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/assets/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, "engines": { - "node": ">=16" + "node": ">= 8" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@capacitor/assets/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "yallist": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@capacitor/assets/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } + "license": "MIT" }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "node_modules/@capacitor/assets/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.18" }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.28.tgz", - "integrity": "sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ] - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "node_modules/@capacitor/assets/node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "license": "BlueOak-1.0.0", "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", - "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", + "node_modules/@capacitor/assets/node_modules/rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "license": "ISC", + "dependencies": { + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, "engines": { - "node": ">=18" + "node": ">=14" }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/@capacitor/assets/node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, "engines": { - "node": ">=18" + "node": ">=14.15.0" }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", - "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", + "node_modules/@capacitor/assets/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/JounQin" - } + "license": "ISC" }, - "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "node_modules/@capacitor/assets/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "MIT", - "optional": true, + "license": "ISC", "dependencies": { - "tslib": "^2.4.0" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], + "node_modules/@capacitor/assets/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, - "optional": true, - "os": [ - "aix" - ], + "license": "ISC", "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], + "node_modules/@capacitor/assets/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } + "license": "0BSD" }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/assets/node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, "engines": { - "node": ">=18" + "node": ">=4.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/assets/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=4.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/assets/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } + "license": "ISC" }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/cli": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.2.0.tgz", + "integrity": "sha512-1cMEk0d/I6tl1U+v/lnJR5Oylpx8ZBIHrvQxD5zK0MkjYOUyQAAGJgh97rkhGJqjAUvrGpa8H4BmyhNQN9a17A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, "engines": { - "node": ">=18" + "node": ">=22.0.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", "engines": { "node": ">=18" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], + "node_modules/@capacitor/cli/node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=14.14" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/core": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.2.0.tgz", + "integrity": "sha512-oKaoNeNtH2iIZMDFVrb1atoyRECDGHcfLMunJ5KWN8DtvpVBeeA4c41e20NTuhMxw1cSYbpq2PV2hb+/9CJxlQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/haptics": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-8.0.1.tgz", + "integrity": "sha512-8v8rowLBMeb3CryqoQvXndwyUsoi4pPXf0qFw7IGA4D32Uk7+K6juN2SjRowqunoovkvvbFmU9TD7JIAz2zmFw==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=8.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/ios": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.2.0.tgz", + "integrity": "sha512-X2/VtM4qP/R1SM0VQ5W/VotEc6PS/KTooD33EijsfAHWBdee+xmBapW8SeNLnu16wJ+tsfWlvtipaJEyfKbRKQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.2.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/android": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-7.6.0.tgz", + "integrity": "sha512-xpfAOGcgeQnTw8C0E9nLjW15lQ6TL2ccieZks93hNiQYknnQT8FQaH2paMYkLYrQ0JfRImdBXbQ1u6sZ4kVa3w==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^7.6.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/app": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-7.1.2.tgz", + "integrity": "sha512-d4I/oF/PRu4megL7/IGKYfe5j7yzSON1FRFgq6kH+m5kH6g7V+wyjHRLauCzGNjdRx4S+nWOumINds0qcRBtKg==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@capacitor/browser": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-7.0.4.tgz", + "integrity": "sha512-XjooNDHEalQoMAb5/Ip7pGcPCIPHEaBv/s/B6K83qVZE66MXC/6enhw18TNaMNtL7U8bGOe6tEG1FFbQVf3PHw==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@capacitor/cli": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-7.6.0.tgz", + "integrity": "sha512-3PL8xIgXLj1037NqmuzoKXNOi80AdY7eSCnX6/A7RfjFqT8TEiCL+PlHsHtg6/BSZGSmmxGGBjH3nXrNCRoFhw==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, "engines": { - "node": ">=18" + "node": ">=20.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@capacitor/cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", "engines": { "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@capacitor/cli/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@capacitor/cli/node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=14.14" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], + "node_modules/@capacitor/core": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.6.0.tgz", + "integrity": "sha512-K6LEvgxW6Nd6uNWHj3U512hUtB4kln71TvVgdvwJRFMLySpUrWwb/A8Q7c3QGogvPvgOjN1U65onkyRTihPGwA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@capacitor/dialog": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/dialog/-/dialog-7.0.4.tgz", + "integrity": "sha512-7W41dohW/vGmLIpqmrvUmhznyFjXK/UPXDU2PHRjV91JbukUSUXdYsvrUPgYW/Nph+SQXyLIv/9GmQFPpLpo/Q==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" + } + }, + "node_modules/@capacitor/filesystem": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-7.1.8.tgz", + "integrity": "sha512-Qpw/2SE4/CzqAUvGgSM9hw/uXQ5qoOaF4wxbToXwpAaKPS+tzletS1h5ti3jjLmGcqizTs2sEXMtcsARW/Ceew==", + "license": "MIT", + "dependencies": { + "@capacitor/synapse": "^1.0.3" + }, + "peerDependencies": { + "@capacitor/core": ">=7.0.0" + } + }, + "node_modules/@capacitor/screen-orientation": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/screen-orientation/-/screen-orientation-7.0.4.tgz", + "integrity": "sha512-xWeWnZsV6z1bXxlOnSi3ynrFMK/JICryAuLnIvGL069BHS05nvxwu15d0xMZiMZWkoucNEAN60vyIYGGqz5IWA==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" + } + }, + "node_modules/@capacitor/share": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/share/-/share-7.0.4.tgz", + "integrity": "sha512-wNXxmXUcChrtbZ5jQv8scFIbIGKo3rk6B7qpWySxfUhYJP5NANgAqQ9Z69m0k/zYsucdh66SBU7XW1ykd9aUug==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" + } + }, + "node_modules/@capacitor/synapse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz", + "integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==", + "license": "ISC" + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "license": "MIT OR Apache-2.0", "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "node_modules/@cloudflare/unenv-preset": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.15.0.tgz", + "integrity": "sha512-EGYmJaGZKWl+X8tXxcnx4v2bOZSjQeNI5dWFeXivgX9+YCT69AkzHHwlNbVpqtEUTbew8eQurpyOpeN8fg00nw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": "1.20260301.1 || ~1.20260302.1 || ~1.20260303.1 || ~1.20260304.1 || >1.20260305.0 <2.0.0-0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260317.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260317.1.tgz", + "integrity": "sha512-8hjh3sPMwY8M/zedq3/sXoA2Q4BedlGufn3KOOleIG+5a4ReQKLlUah140D7J6zlKmYZAFMJ4tWC7hCuI/s79g==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "darwin" ], "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260317.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260317.1.tgz", + "integrity": "sha512-M/MnNyvO5HMgoIdr3QHjdCj2T1ki9gt0vIUnxYxBu9ISXS/jgtMl6chUVPJ7zHYBn9MyYr8ByeN6frjYxj0MGg==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "openharmony" + "darwin" ], "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260317.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260317.1.tgz", + "integrity": "sha512-1ltuEjkRcS3fsVF7CxsKlWiRmzq2ZqMfqDN0qUOgbUwkpXsLVJsXmoblaLf5OP00ELlcgF0QsN0p2xPEua4Uug==", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260317.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260317.1.tgz", + "integrity": "sha512-3QrNnPF1xlaNwkHpasvRvAMidOvQs2NhXQmALJrEfpIJ/IDL2la8g499yXp3eqhG3hVMCB07XVY149GTs42Xtw==", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" + "linux" ], "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260317.1", "cpu": [ "x64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" + "node": ">=18" }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.28.tgz", + "integrity": "sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==", "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" } - } + ] }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", "dev": true, - "dependencies": { - "@eslint/core": "^0.17.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.3", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.15" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", - "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "node_modules/@csstools/selector-specificity": { + "version": "5.0.0", "dev": true, - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.3", - "strip-json-comments": "^3.1.1" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@dantheman827/taglib-ts": { + "version": "0.1.4", + "resolved": "https://github.com/DanTheMan827/taglib-ts/archive/b4238b2627aceb97f58813258046f1259f68cab7.tar.gz", + "integrity": "sha512-rvQOn9GDEj2sH4yV6oUTMMG9+rJbFG7tQkiP6/bhGJARg1Vmdy283j4YFCl+ubkqsMQ+UfAhEWSw5d5lfPVfwQ==", + "license": "LGPL-2.1-or-later" + }, + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.2.1", + "dev": true, "funding": { - "url": "https://opencollective.com/eslint" + "type": "github", + "url": "https://github.com/sponsors/JounQin" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@emnapi/runtime": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "tslib": "^2.4.0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "aix" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/js": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", - "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": ">=18" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@ffmpeg/core": { - "version": "0.12.10", - "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.12.10.tgz", - "integrity": "sha512-dzNplnn2Nxle2c2i2rrDhqcB19q9cglCkWnoMTDN9Q9l3PvdjZWd1HfSPjCNWc/p8Q3CT+Es9fWOR0UhAeYQZA==", - "license": "GPL-2.0-or-later", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=16.x" + "node": ">=18" } }, - "node_modules/@ffmpeg/ffmpeg": { - "version": "0.12.15", - "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", - "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", - "license": "MIT", - "dependencies": { - "@ffmpeg/types": "^0.12.4" - }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18.x" + "node": ">=18" } }, - "node_modules/@ffmpeg/types": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/@ffmpeg/types/-/types-0.12.4.tgz", - "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", - "license": "MIT", - "engines": { - "node": ">=16.x" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { "node": ">=18" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "freebsd" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", "cpu": [ - "x64" + "arm" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", "cpu": [ "arm64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "darwin" + "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", "cpu": [ - "x64" + "ia32" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "darwin" + "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", "cpu": [ - "arm" + "loong64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", "cpu": [ - "arm64" + "mips64el" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", "cpu": [ "ppc64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", "cpu": [ "riscv64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", "cpu": [ "s390x" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", "cpu": [ "x64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", "cpu": [ "arm64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "netbsd" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", "cpu": [ "x64" ], "dev": true, - "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "netbsd" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", "cpu": [ - "arm" + "arm64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "openbsd" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", "cpu": [ - "riscv64" + "arm64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "openharmony" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", "cpu": [ - "s390x" + "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "sunos" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", "cpu": [ - "x64" + "arm64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", "cpu": [ - "arm64" + "ia32" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + "node": ">=18" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, "dependencies": { - "@emnapi/runtime": "^1.7.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "url": "https://opencollective.com/eslint" }, - "funding": { - "url": "https://opencollective.com/libvips" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/libvips" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@ionic/cli-framework-output": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", - "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", - "license": "MIT", + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, "dependencies": { - "@ionic/utils-terminal": "2.3.5", - "debug": "^4.0.0", - "tslib": "^2.0.1" + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@ionic/cli-framework-output/node_modules/debug": { + "node_modules/@eslint/config-array/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", + "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -3213,1690 +2905,3455 @@ } } }, - "node_modules/@ionic/utils-array": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", - "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", - "license": "MIT", + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "dev": true, "dependencies": { - "debug": "^4.0.0", - "tslib": "^2.0.1" + "@eslint/core": "^0.17.0" }, "engines": { - "node": ">=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@ionic/utils-array/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", + "node_modules/@eslint/core": { + "version": "0.17.0", + "dev": true, "dependencies": { - "ms": "^2.1.3" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@ionic/utils-fs": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", - "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", - "license": "MIT", + "node_modules/@eslint/eslintrc": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "dev": true, "dependencies": { - "@types/fs-extra": "^8.0.0", - "debug": "^4.0.0", - "fs-extra": "^9.0.0", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@ionic/utils-fs/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.3", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@ionic/utils-object": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", - "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", - "license": "MIT", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.14.0", + "dev": true, "dependencies": { - "debug": "^4.0.0", - "tslib": "^2.0.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=16.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@ionic/utils-object/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "dev": true, "engines": { - "node": ">=6.0" + "node": ">=18" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ionic/utils-process": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", - "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", - "license": "MIT", - "dependencies": { - "@ionic/utils-object": "2.1.6", - "@ionic/utils-terminal": "2.3.5", - "debug": "^4.0.0", - "signal-exit": "^3.0.3", - "tree-kill": "^1.2.2", - "tslib": "^2.0.1" + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", + "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "dev": true, "engines": { - "node": ">=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@ionic/utils-process/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "dev": true, "dependencies": { - "ms": "^2.1.3" + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@ionic/utils-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", - "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", - "license": "MIT", - "dependencies": { - "debug": "^4.0.0", - "tslib": "^2.0.1" - }, + "node_modules/@ffmpeg/core": { + "version": "0.12.10", + "license": "GPL-2.0-or-later", "engines": { - "node": ">=16.0.0" + "node": ">=16.x" } }, - "node_modules/@ionic/utils-stream/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@ffmpeg/ffmpeg": { + "version": "0.12.15", "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@ffmpeg/types": "^0.12.4" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=18.x" } }, - "node_modules/@ionic/utils-subprocess": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", - "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "node_modules/@ffmpeg/types": { + "version": "0.12.4", "license": "MIT", - "dependencies": { - "@ionic/utils-array": "2.1.6", - "@ionic/utils-fs": "3.1.7", - "@ionic/utils-process": "2.1.12", - "@ionic/utils-stream": "3.1.7", - "@ionic/utils-terminal": "2.3.5", - "cross-spawn": "^7.0.3", - "debug": "^4.0.0", - "tslib": "^2.0.1" - }, "engines": { - "node": ">=16.0.0" + "node": ">=16.x" } }, - "node_modules/@ionic/utils-subprocess/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "dev": true, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=18.18.0" } }, - "node_modules/@ionic/utils-terminal": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", - "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", - "license": "MIT", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "dev": true, "dependencies": { - "@types/slice-ansi": "^4.0.0", - "debug": "^4.0.0", - "signal-exit": "^3.0.3", - "slice-ansi": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "tslib": "^2.0.1", - "untildify": "^4.0.0", - "wrap-ansi": "^7.0.0" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.18.0" } }, - "node_modules/@ionic/utils-terminal/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, "engines": { - "node": ">=6.0" + "node": ">=12.22" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/cliui": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", - "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", "dev": true, "engines": { - "node": ">=18" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jofr/capacitor-media-session": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@jofr/capacitor-media-session/-/capacitor-media-session-4.0.0.tgz", - "integrity": "sha512-IGfc6BUzeeR0sJkk+0/jij3l0h78NdTqPMwBc9LXZrojtiqNtg4tw3CnIkYGccwZ/0glV3hPl8HVNTElOPVCyg==", - "license": "GPL-3.0-or-later", - "peerDependencies": { - "@capacitor/core": "^6.0.0" + "node_modules/@img/colour": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@kawarp/core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kawarp/core/-/core-1.1.1.tgz", - "integrity": "sha512-hnJ0CQQAa6o4HPoUE6Tkn6/cqzpA/tRPNDTNqVeoY9rozL37KweAzbypmdrYTBOdyJRR9MvETyxy4hlpenIa/w==", - "license": "AGPL-3.0" - }, - "node_modules/@keyv/serialize": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", - "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", - "dev": true - }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", - "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", - "license": "BSD-3-Clause" - }, - "node_modules/@lit/reactive-element": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", - "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.5.0" + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@m430/capacitor-app-install": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@m430/capacitor-app-install/-/capacitor-app-install-0.0.3.tgz", - "integrity": "sha512-HsdpY/uZjjwvdn+71iCNAORIh3zQSXSW1KqzgRqphUzJW3whpAFsR4ErQAf8hbe/8yOouF01Rxz0bEBkyq3B1A==", - "license": "MIT", - "peerDependencies": { - "@capacitor/core": ">=7.0.0" + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@msgpack/msgpack": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", - "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", - "license": "ISC", - "engines": { - "node": ">= 18" + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], "dev": true, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@odion-cloud/capacitor-mediastore": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/@odion-cloud/capacitor-mediastore/-/capacitor-mediastore-1.0.21.tgz", - "integrity": "sha512-MgUaIZgzG5QsXprV7iIqz/bCMLgRaO2tFdzGcksx4QR+saKVMQ/XmhiuUyxSD3VGOCnoRjPYN9tKcEDkplW1zg==", - "license": "MIT", - "dependencies": { - "@capacitor/cli": "^7.4.0", - "@rollup/plugin-node-resolve": "^16.0.1", - "@rollup/plugin-terser": "^0.4.4", - "rollup": "^4.12.0", - "typescript": "^5.8.3" - }, - "peerDependencies": { - "@capacitor/core": "^6.0.0" + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@odion-cloud/capacitor-mediastore/node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", - "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", - "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" } }, - "node_modules/@poppinss/colors": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", - "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^4.1.5" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" } }, - "node_modules/@poppinss/dumper": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", - "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/colors": "^4.1.5", - "@sindresorhus/is": "^7.0.2", - "supports-color": "^10.0.0" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" } }, - "node_modules/@poppinss/dumper/node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, - "node_modules/@poppinss/exception": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", - "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", - "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" + "linux" ], - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" ], - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ - "arm64" + "wasm32" ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", "cpu": [ "arm64" ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" + "win32" ], - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ - "loong64" + "ia32" ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" + "win32" ], - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", "cpu": [ - "ppc64" + "x64" ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" + "win32" ], - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/cli-framework-output/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-object/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jofr/capacitor-media-session": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@jofr/capacitor-media-session/-/capacitor-media-session-4.0.0.tgz", + "integrity": "sha512-IGfc6BUzeeR0sJkk+0/jij3l0h78NdTqPMwBc9LXZrojtiqNtg4tw3CnIkYGccwZ/0glV3hPl8HVNTElOPVCyg==", + "license": "GPL-3.0-or-later", + "peerDependencies": { + "@capacitor/core": "^6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kawarp/core": { + "version": "1.1.1", + "license": "AGPL-3.0" + }, + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "dev": true + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", + "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0" + } + }, + "node_modules/@m430/capacitor-app-install": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@m430/capacitor-app-install/-/capacitor-app-install-0.0.3.tgz", + "integrity": "sha512-HsdpY/uZjjwvdn+71iCNAORIh3zQSXSW1KqzgRqphUzJW3whpAFsR4ErQAf8hbe/8yOouF01Rxz0bEBkyq3B1A==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": ">=7.0.0" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.5.1", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.2", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@odion-cloud/capacitor-mediastore": { + "version": "1.0.21", + "resolved": "https://registry.npmjs.org/@odion-cloud/capacitor-mediastore/-/capacitor-mediastore-1.0.21.tgz", + "integrity": "sha512-MgUaIZgzG5QsXprV7iIqz/bCMLgRaO2tFdzGcksx4QR+saKVMQ/XmhiuUyxSD3VGOCnoRjPYN9tKcEDkplW1zg==", + "license": "MIT", + "dependencies": { + "@capacitor/cli": "^7.4.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.12.0", + "typescript": "^5.8.3" + }, + "peerDependencies": { + "@capacitor/core": "^6.0.0" + } + }, + "node_modules/@odion-cloud/capacitor-mediastore/node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", + "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/dumper/node_modules/supports-color": { + "version": "10.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@prettier/plugin-xml": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@prettier/plugin-xml/-/plugin-xml-2.2.0.tgz", + "integrity": "sha512-UWRmygBsyj4bVXvDiqSccwT1kmsorcwQwaIy30yVh8T+Gspx4OlC0shX1y+ZuwXZvgnafmpRYKks0bAu9urJew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xml-tools/parser": "^1.0.11", + "prettier": ">=2.4.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ - "riscv64" + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" ], "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ] + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.15", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "dev": true, + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svta/cml-608": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-608/-/cml-608-1.0.1.tgz", + "integrity": "sha512-Y/Ier9VPUSOBnf0bJqdDyTlPrt4dDB+jk5mYHa1bnD2kcRl8qn7KkW3PRuj4w1aVN+BS2eHmsLxodt7P2hylUg==", + "engines": { + "node": ">=20" + } + }, + "node_modules/@svta/cml-cmcd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-cmcd/-/cml-cmcd-1.0.1.tgz", + "integrity": "sha512-eox305g+QUJgXqOLVrbgxeQHCgl90ewwQ9O2bIoo7m+hanR8Xswu5CknFnT5qqIbLOHfw80ug+raycoAFHTQ+w==", + "engines": { + "node": ">=20" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@svta/cml-cmsd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-cmsd/-/cml-cmsd-1.0.1.tgz", + "integrity": "sha512-+nIB8PuSfb/qw+xGaArPhNqPm84tBJUbe3H1DnPL5QUsjSUI7mUIUQwAtRV1ZdEu0+80g9i0op79woB0OIwr/g==", + "engines": { + "node": ">=20" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@trapezedev/project/node_modules/@ionic/utils-subprocess": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz", + "integrity": "sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.11", + "@ionic/utils-stream": "3.1.6", + "@ionic/utils-terminal": "2.3.4", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@svta/cml-dash": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-dash/-/cml-dash-1.0.1.tgz", + "integrity": "sha512-lYnD1I7FUbbQND+xICI+kcRaRXuT+whKk27R8m8me5VMVu2sMsAMc7Yui6l9sxw2cBKt8pSETPYRm/1+n4LZkw==", + "engines": { + "node": ">=20" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@svta/cml-id3": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-id3/-/cml-id3-1.0.1.tgz", + "integrity": "sha512-90fGlL1qRI88CcaB89k6NG6cC3kky4Eu2jwqU4HefqK+S5k2OASUxf8JXkGz+DsdaiY7sh51vGPYdolfBZS7ug==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@trapezedev/project/node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svta/cml-request": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-request/-/cml-request-1.0.1.tgz", + "integrity": "sha512-enL19BuXUjFkDDDF9jdNwUclMNPRsagnjGAetVC7xcmpDMpEx+ZLgsDip6BFNg5p6izSEk/OyujTWW1r8bDNiA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@trapezedev/project/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@trapezedev/project/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@trapezedev/project/node_modules/tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@svta/cml-xml/-/cml-xml-1.0.1.tgz", + "integrity": "sha512-11LkJa5kDEcsRMWkVI1ABH3KLCxGoiSVe4kQ293ItVj8ncTTQ7htmCGiJDjS+Cmy35UgF3e/vc0ysJIiWRTx2g==", + "engines": { + "node": ">=20" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "25.3.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==" + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, + "node_modules/@uimaxbai/am-lyrics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@uimaxbai/am-lyrics/-/am-lyrics-1.1.1.tgz", + "integrity": "sha512-U4qnMK2gWqfIWUwH9Wm4r5PGeCqmvmHVNCeYOTsSUIAMMZd3LBDyCZL/dAs5A4VaHxJecCyy2dy94IN4zH5gzg==", + "license": "MPL-2.0", + "dependencies": { + "@babel/runtime": "^7.27.6", + "lit": "^3.1.4" + }, + "peerDependencies": { + "@lit/react": "^1.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@lit/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@uimaxbai/am-lyrics": { + "version": "1.1.4", + "license": "MPL-2.0", + "dependencies": { + "@babel/runtime": "^7.27.6", + "lit": "^3.1.4" + }, + "peerDependencies": { + "@lit/react": "^1.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@lit/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@xml-tools/parser": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", + "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chevrotain": "7.1.1" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/appwrite": { + "version": "23.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] + "node_modules/asap": { + "version": "2.0.6", + "dev": true, + "license": "MIT" }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, + "node_modules/async-function": { + "version": "1.0.0", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/b4a": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", + "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", + "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.6", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", + "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.6", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", + "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.6" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], - "optional": true, - "os": [ - "linux" - ] + "license": "MIT" }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.6.tgz", + "integrity": "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz", + "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.10.0.tgz", + "integrity": "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz", + "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], - "optional": true, - "os": [ - "openbsd" - ] + "license": "MIT" }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "openharmony" - ] + "node_modules/baseline-browser-mapping": { + "version": "2.10.9", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ] + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ] + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] + "node_modules/bcp-47-normalize": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", + "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", + "dependencies": { + "bcp-47": "^2.0.0", + "bcp-47-match": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } }, - "node_modules/@sindresorhus/is": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", - "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", - "dev": true, + "node_modules/bignumber.js": { + "version": "9.3.1", "license": "MIT", "engines": { - "node": ">=18" + "node": "*" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">= 5.10.0" } }, - "node_modules/@speed-highlight/core": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.14.tgz", - "integrity": "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==", + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, - "license": "CC0-1.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/@surma/rollup-plugin-off-main-thread": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/braces": { + "version": "3.0.3", "dev": true, "dependencies": { - "ejs": "^3.1.6", - "json5": "^2.2.0", - "magic-string": "^0.25.0", - "string.prototype.matchall": "^4.0.6" + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@svta/cml-608": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-608/-/cml-608-1.0.1.tgz", - "integrity": "sha512-Y/Ier9VPUSOBnf0bJqdDyTlPrt4dDB+jk5mYHa1bnD2kcRl8qn7KkW3PRuj4w1aVN+BS2eHmsLxodt7P2hylUg==", + "node_modules/browserslist": { + "version": "4.28.1", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, "engines": { - "node": ">=20" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@svta/cml-cmcd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-cmcd/-/cml-cmcd-1.0.1.tgz", - "integrity": "sha512-eox305g+QUJgXqOLVrbgxeQHCgl90ewwQ9O2bIoo7m+hanR8Xswu5CknFnT5qqIbLOHfw80ug+raycoAFHTQ+w==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@svta/cml-cta": "1.0.1", - "@svta/cml-structured-field-values": "1.0.1", - "@svta/cml-utils": "1.0.1" + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/butterchurn": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/butterchurn/-/butterchurn-2.6.7.tgz", + "integrity": "sha512-BJiRA8L0L2+84uoG2SSfkp0kclBuN+vQKf217pK7pMlwEO2ZEg3MtO2/o+l8Qpr8Nbejg8tmL1ZHD1jmhiaaqg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "ecma-proposal-math-extensions": "0.0.2" + } + }, + "node_modules/butterchurn-presets": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/butterchurn-presets/-/butterchurn-presets-2.4.7.tgz", + "integrity": "sha512-4MdM8ripz/VfH1BCldrIKdAc/1ryJFBDvqlyow6Ivo1frwj0H3duzvSMFC7/wIjAjxb1QpwVHVqGqS9uAFKhpg==", + "dependencies": { + "babel-runtime": "^6.26.0", + "ecma-proposal-math-extensions": "0.0.2", + "lodash": "^4.17.4" } }, - "node_modules/@svta/cml-cmsd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-cmsd/-/cml-cmsd-1.0.1.tgz", - "integrity": "sha512-+nIB8PuSfb/qw+xGaArPhNqPm84tBJUbe3H1DnPL5QUsjSUI7mUIUQwAtRV1ZdEu0+80g9i0op79woB0OIwr/g==", - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@svta/cml-cta": "1.0.1", - "@svta/cml-structured-field-values": "1.0.1", - "@svta/cml-utils": "1.0.1" + "node_modules/cacheable": { + "version": "2.3.4", + "dev": true, + "dependencies": { + "@cacheable/memory": "^2.0.8", + "@cacheable/utils": "^2.4.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.6.0" } }, - "node_modules/@svta/cml-cta": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-cta/-/cml-cta-1.0.1.tgz", - "integrity": "sha512-jcXqNIPv26bmFxIOFh8/c3+6WLH4qBjKpq9qTQcggDPoHuV1YBydMsJLOnYPDeK8rNMKcAkFLbnDRvyJthu5yw==", - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@svta/cml-structured-field-values": "1.0.1", - "@svta/cml-utils": "1.0.1" + "node_modules/cacheable/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "dependencies": { + "@keyv/serialize": "^1.1.1" } }, - "node_modules/@svta/cml-dash": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-dash/-/cml-dash-1.0.1.tgz", - "integrity": "sha512-lYnD1I7FUbbQND+xICI+kcRaRXuT+whKk27R8m8me5VMVu2sMsAMc7Yui6l9sxw2cBKt8pSETPYRm/1+n4LZkw==", + "node_modules/call-bind": { + "version": "1.0.8", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, "engines": { - "node": ">=20" + "node": ">= 0.4" }, - "peerDependencies": { - "@svta/cml-utils": "1.0.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@svta/cml-id3": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-id3/-/cml-id3-1.0.1.tgz", - "integrity": "sha512-90fGlL1qRI88CcaB89k6NG6cC3kky4Eu2jwqU4HefqK+S5k2OASUxf8JXkGz+DsdaiY7sh51vGPYdolfBZS7ug==", - "engines": { - "node": ">=20" + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, - "peerDependencies": { - "@svta/cml-utils": "1.0.1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/@svta/cml-request": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-request/-/cml-request-1.0.1.tgz", - "integrity": "sha512-enL19BuXUjFkDDDF9jdNwUclMNPRsagnjGAetVC7xcmpDMpEx+ZLgsDip6BFNg5p6izSEk/OyujTWW1r8bDNiA==", + "node_modules/call-bound": { + "version": "1.0.4", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, "engines": { - "node": ">=20" + "node": ">= 0.4" }, - "peerDependencies": { - "@svta/cml-utils": "1.0.1", - "@svta/cml-xml": "1.0.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@svta/cml-structured-field-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-structured-field-values/-/cml-structured-field-values-1.0.1.tgz", - "integrity": "sha512-Kibciki59Pon3Pn/sl5uyrbJcSpZQDKqdCfDrokBvOdLoqqcd0oFrkEPsZBiuuIODX1CB80612xe8hopeFDyBA==", - "license": "Apache-2.0", - "peer": true, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@svta/cml-utils": "1.0.1" + "node": ">=6" } }, - "node_modules/@svta/cml-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-utils/-/cml-utils-1.0.1.tgz", - "integrity": "sha512-kso3curTJfp00I1mKFoBliBApjn4aPE+wF8cPucf7TrSDVWZDeLLuF14ASmUE9m7rnrqTTK4878VvmXaXcCCfQ==", - "license": "Apache-2.0", - "peer": true, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=20" + "node": ">=6" } }, - "node_modules/@svta/cml-xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@svta/cml-xml/-/cml-xml-1.0.1.tgz", - "integrity": "sha512-11LkJa5kDEcsRMWkVI1ABH3KLCxGoiSVe4kQ293ItVj8ncTTQ7htmCGiJDjS+Cmy35UgF3e/vc0ysJIiWRTx2g==", + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, "engines": { - "node": ">=20" + "node": ">=8" }, - "peerDependencies": { - "@svta/cml-utils": "1.0.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + "node_modules/caniuse-lite": { + "version": "1.0.30001775", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", + "integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/@types/fs-extra": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", - "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", - "license": "MIT", + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, "dependencies": { - "@types/node": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "25.3.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", - "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.18.0" + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==" + "node_modules/codem-isoboxer": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.10.tgz", + "integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==" }, - "node_modules/@types/sarif": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", - "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" - }, - "node_modules/@uimaxbai/am-lyrics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@uimaxbai/am-lyrics/-/am-lyrics-1.1.1.tgz", - "integrity": "sha512-U4qnMK2gWqfIWUwH9Wm4r5PGeCqmvmHVNCeYOTsSUIAMMZd3LBDyCZL/dAs5A4VaHxJecCyy2dy94IN4zH5gzg==", - "license": "MPL-2.0", + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.27.6", - "lit": "^3.1.4" - }, - "peerDependencies": { - "@lit/react": "^1.0.0", - "react": ">=17.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, - "peerDependenciesMeta": { - "@lit/react": { - "optional": true - }, - "react": { - "optional": true - } - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", - "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=12" } }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "bin": { - "acorn": "bin/acorn" + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=12.5.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/common-tags": { + "version": "1.8.2", + "dev": true, "engines": { - "node": ">=8" + "node": ">=4.0.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" } }, - "node_modules/appwrite": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-23.0.0.tgz", - "integrity": "sha512-K11a597npl3jsnxWKzjw163n4GguH4+/zBCOiU15yc1u+7QF0nP9mxsY4JxKrBU6bmQRtgtMTPv/6YOLSwp/QQ==", - "license": "BSD-3-Clause", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "dev": true, + "license": "ISC", "dependencies": { - "json-bigint": "1.0.0" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/configstore/node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "license": "ISC" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "node_modules/conventional-changelog": { + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", + "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "node_modules/conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, + "license": "ISC", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" + "q": "^1.5.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "node_modules/conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, - "license": "MIT" - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "ISC", + "dependencies": { + "q": "^1.5.1" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", + "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=10" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, + "license": "ISC", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "q": "^1.5.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", - "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", + "node_modules/conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.6", - "semver": "^6.3.1" + "q": "^1.5.1" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", - "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", + "node_modules/conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6", - "core-js-compat": "^3.48.0" + "q": "^1.5.1" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", - "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", + "node_modules/conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6" + "q": "^1.5.1" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "node_modules/conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "license": "ISC", "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "node_modules/conventional-changelog-writer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", + "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/bcp-47": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", - "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "node_modules/conventional-changelog-writer/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/conventional-changelog-writer/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", "dependencies": { - "is-alphabetical": "^2.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0" + "p-locate": "^4.1.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=8" } }, - "node_modules/bcp-47-match": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", - "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "node_modules/conventional-changelog-writer/node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bcp-47-normalize": { + "node_modules/conventional-changelog-writer/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", - "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", "dependencies": { - "bcp-47": "^2.0.0", - "bcp-47-match": "^2.0.0" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", + "node_modules/conventional-changelog-writer/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "node_modules/conventional-changelog-writer/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "node_modules/conventional-changelog-writer/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, - "license": "MIT" - }, - "node_modules/bplist-parser": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", - "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", "license": "MIT", "dependencies": { - "big-integer": "1.6.x" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">= 5.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/conventional-changelog-writer/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/conventional-changelog-writer/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "fill-range": "^7.1.1" - }, + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/conventional-changelog-writer/node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/conventional-changelog-writer/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, + "license": "ISC", "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "semver": "bin/semver.js" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/conventional-changelog-writer/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/butterchurn": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/butterchurn/-/butterchurn-2.6.7.tgz", - "integrity": "sha512-BJiRA8L0L2+84uoG2SSfkp0kclBuN+vQKf217pK7pMlwEO2ZEg3MtO2/o+l8Qpr8Nbejg8tmL1ZHD1jmhiaaqg==", - "dependencies": { - "@babel/runtime": "^7.0.0", - "ecma-proposal-math-extensions": "0.0.2" + "node_modules/conventional-changelog-writer/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" } }, - "node_modules/butterchurn-presets": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/butterchurn-presets/-/butterchurn-presets-2.4.7.tgz", - "integrity": "sha512-4MdM8ripz/VfH1BCldrIKdAc/1ryJFBDvqlyow6Ivo1frwj0H3duzvSMFC7/wIjAjxb1QpwVHVqGqS9uAFKhpg==", + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "license": "MIT", "dependencies": { - "babel-runtime": "^6.26.0", - "ecma-proposal-math-extensions": "0.0.2", - "lodash": "^4.17.4" + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/cacheable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.3.tgz", - "integrity": "sha512-iffYMX4zxKp54evOH27fm92hs+DeC1DhXmNVN8Tr94M/iZIV42dqTHSR2Ik4TOSPyOAwKr7Yu3rN9ALoLkbWyQ==", + "node_modules/conventional-commits-parser": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", + "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@cacheable/memory": "^2.0.8", - "@cacheable/utils": "^2.4.0", - "hookified": "^1.15.0", - "keyv": "^5.6.0", - "qified": "^0.6.0" + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/cacheable/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "node_modules/conventional-commits-parser/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.1.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "node_modules/conventional-commits-parser/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/conventional-commits-parser/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/conventional-commits-parser/node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "engines": { - "node": ">= 0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/conventional-commits-parser/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/conventional-commits-parser/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001775", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", - "integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==", + "node_modules/conventional-commits-parser/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/conventional-commits-parser/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", + "node_modules/conventional-commits-parser/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/codem-isoboxer": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.10.tgz", - "integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/conventional-commits-parser/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "color-name": "~1.1.4" - }, + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/conventional-commits-parser/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/conventional-commits-parser/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "node_modules/conventional-commits-parser/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "node_modules/conventional-commits-parser/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/conventional-commits-parser/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -4906,8 +6363,6 @@ }, "node_modules/cookie": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "dev": true, "license": "MIT", "engines": { @@ -4932,6 +6387,13 @@ "node": ">= 0.10" } }, + "node_modules/cookie-session/node_modules/debug": { + "version": "3.2.7", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/cookies": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", @@ -4952,9 +6414,7 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "version": "3.49.0", "dev": true, "dependencies": { "browserslist": "^4.28.1" @@ -4964,6 +6424,13 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -4990,6 +6457,13 @@ } } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5005,8 +6479,6 @@ }, "node_modules/crypto-random-string": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, "engines": { "node": ">=8" @@ -5014,13 +6486,25 @@ }, "node_modules/css-functions-list": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", - "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", "dev": true, "engines": { "node": ">=12" } }, + "node_modules/css-select": { + "version": "5.2.2", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css-tree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", @@ -5034,10 +6518,18 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/css-what": { + "version": "6.2.2", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "bin": { "cssesc": "bin/cssesc" @@ -5071,8 +6563,6 @@ }, "node_modules/data-view-buffer": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -5088,8 +6578,6 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -5105,8 +6593,6 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -5120,12 +6606,93 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "ms": "^2.1.1" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" } }, "node_modules/deep-is": { @@ -5144,8 +6711,6 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { "es-define-property": "^1.0.0", @@ -5165,24 +6730,84 @@ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/del/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 0.4" + "bin": { + "rimraf": "bin.js" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/depd": { @@ -5195,8 +6820,6 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5205,8 +6828,6 @@ }, "node_modules/dezalgo": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "dev": true, "license": "ISC", "dependencies": { @@ -5214,10 +6835,18 @@ "wrappy": "1" } }, + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { "path-type": "^4.0.0" @@ -5228,8 +6857,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -5247,8 +6874,6 @@ }, "node_modules/ejs": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -5289,6 +6914,26 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -5299,8 +6944,6 @@ }, "node_modules/error-ex": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "dependencies": { "is-arrayish": "^0.2.1" @@ -5308,8 +6951,6 @@ }, "node_modules/error-stack-parser-es": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", - "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", "dev": true, "license": "MIT", "funding": { @@ -5318,8 +6959,6 @@ }, "node_modules/es-abstract": { "version": "1.24.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", - "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.2", @@ -5386,8 +7025,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "engines": { "node": ">= 0.4" @@ -5395,8 +7032,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "engines": { "node": ">= 0.4" @@ -5404,8 +7039,6 @@ }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "dependencies": { "es-errors": "^1.3.0" @@ -5416,8 +7049,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -5431,8 +7062,6 @@ }, "node_modules/es-to-primitive": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "dependencies": { "is-callable": "^1.2.7", @@ -5447,9 +7076,7 @@ } }, "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "version": "0.27.4", "dev": true, "hasInstallScript": true, "bin": { @@ -5459,38 +7086,36 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" } }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -5498,8 +7123,6 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { "node": ">=10" @@ -5569,8 +7192,6 @@ }, "node_modules/eslint-config-prettier": { "version": "10.1.8", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", - "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -5584,8 +7205,6 @@ }, "node_modules/eslint-scope": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -5600,8 +7219,6 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5610,27 +7227,22 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.14.0", "dev": true, "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/espree": { "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "dependencies": { "acorn": "^8.15.0", @@ -5646,8 +7258,6 @@ }, "node_modules/esquery": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -5658,8 +7268,6 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { "estraverse": "^5.2.0" @@ -5670,8 +7278,6 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { "node": ">=4.0" @@ -5684,8 +7290,6 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { "node": ">=0.10.0" @@ -5698,8 +7302,6 @@ }, "node_modules/fast-glob": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5714,8 +7316,6 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" @@ -5738,8 +7338,6 @@ }, "node_modules/fast-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -5754,8 +7352,6 @@ }, "node_modules/fastest-levenshtein": { "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "engines": { "node": ">= 4.9.1" @@ -5763,8 +7359,6 @@ }, "node_modules/fastq": { "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -5781,8 +7375,6 @@ }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { "flat-cache": "^4.0.0" @@ -5793,17 +7385,22 @@ }, "node_modules/filelist": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", - "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, "dependencies": { "minimatch": "^5.0.1" } }, + "node_modules/filelist/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" @@ -5811,8 +7408,6 @@ }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -5823,8 +7418,6 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5835,8 +7428,6 @@ }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { "locate-path": "^6.0.0", @@ -5851,8 +7442,6 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -5862,6 +7451,14 @@ "node": ">=16" } }, + "node_modules/flat-cache/node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -5870,8 +7467,6 @@ }, "node_modules/for-each": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "dependencies": { "is-callable": "^1.2.7" @@ -5885,8 +7480,6 @@ }, "node_modules/foreground-child": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "dependencies": { "cross-spawn": "^7.0.6", @@ -5913,8 +7506,6 @@ }, "node_modules/formidable": { "version": "3.5.4", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", - "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, "license": "MIT", "dependencies": { @@ -5929,6 +7520,13 @@ "url": "https://ko-fi.com/tunnckoCore/commissions" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -5966,8 +7564,6 @@ }, "node_modules/function.prototype.name": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -5986,8 +7582,6 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5995,65 +7589,176 @@ }, "node_modules/fuse.js": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz", - "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==", "license": "Apache-2.0", "engines": { "node": ">=10" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "node_modules/generator-function": { + "version": "2.0.1", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/get-pkg-repo/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/get-pkg-repo/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "engines": { - "node": ">= 0.4" + "license": "MIT" + }, + "node_modules/get-pkg-repo/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true + "node_modules/get-pkg-repo/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "dependencies": { "dunder-proto": "^1.0.1", @@ -6065,8 +7770,6 @@ }, "node_modules/get-symbol-description": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -6099,8 +7802,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { "is-glob": "^4.0.3" @@ -6147,8 +7848,6 @@ }, "node_modules/global-modules": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, "dependencies": { "global-prefix": "^3.0.0" @@ -6159,8 +7858,6 @@ }, "node_modules/global-prefix": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "dependencies": { "ini": "^1.3.5", @@ -6173,8 +7870,6 @@ }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" @@ -6185,8 +7880,6 @@ }, "node_modules/globals": { "version": "17.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", - "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, "engines": { "node": ">=18" @@ -6197,8 +7890,6 @@ }, "node_modules/globalthis": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { "define-properties": "^1.2.1", @@ -6213,8 +7904,6 @@ }, "node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { "array-union": "^2.1.0", @@ -6239,8 +7928,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "engines": { "node": ">= 0.4" @@ -6254,10 +7941,53 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/gradle-to-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gradle-to-js/-/gradle-to-js-2.0.1.tgz", + "integrity": "sha512-is3hDn9zb8XXnjbEeAEIqxTpLHUiGBqjegLmXPuyMBfKAggpadWFku4/AP8iYAGBX6qR9/5UIUIp47V0XI3aMw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash.merge": "^4.6.2" + }, + "bin": { + "gradle-to-js": "cli.js" + } + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/has-bigints": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "engines": { "node": ">= 0.4" @@ -6268,8 +7998,6 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" @@ -6277,8 +8005,6 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { "es-define-property": "^1.0.0" @@ -6289,8 +8015,6 @@ }, "node_modules/has-proto": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "dependencies": { "dunder-proto": "^1.0.0" @@ -6304,8 +8028,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "engines": { "node": ">= 0.4" @@ -6316,8 +8038,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { "has-symbols": "^1.0.3" @@ -6331,8 +8051,6 @@ }, "node_modules/hashery": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.0.tgz", - "integrity": "sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==", "dev": true, "dependencies": { "hookified": "^1.14.0" @@ -6352,10 +8070,18 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, "node_modules/hls.js": { "version": "1.6.15", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.15.tgz", - "integrity": "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==", "license": "Apache-2.0" }, "node_modules/hookified": { @@ -6381,8 +8107,6 @@ }, "node_modules/html-tags": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "engines": { "node": ">=8" @@ -6393,8 +8117,6 @@ }, "node_modules/htmlhint": { "version": "1.9.2", - "resolved": "https://registry.npmjs.org/htmlhint/-/htmlhint-1.9.2.tgz", - "integrity": "sha512-PweWSPA1Pb+AVFIOSpIGu5KhLdmtk/uf/0CpjvrDf6XUWmdTyqUljlylwSxQ0AWLvPGcBxK2n8uISsI4lCOkBQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6420,8 +8142,6 @@ }, "node_modules/htmlhint/node_modules/commander": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "engines": { "node": ">=16" @@ -6433,10 +8153,29 @@ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", "dev": true }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -6449,8 +8188,6 @@ }, "node_modules/import-fresh": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -6473,8 +8210,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" @@ -6493,8 +8228,6 @@ }, "node_modules/internal-slot": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -6529,8 +8262,6 @@ }, "node_modules/is-array-buffer": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -6552,8 +8283,6 @@ }, "node_modules/is-async-function": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "dependencies": { "async-function": "^1.0.0", @@ -6571,8 +8300,6 @@ }, "node_modules/is-bigint": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "dependencies": { "has-bigints": "^1.0.2" @@ -6586,8 +8313,6 @@ }, "node_modules/is-boolean-object": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -6602,8 +8327,6 @@ }, "node_modules/is-callable": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -6628,8 +8351,6 @@ }, "node_modules/is-data-view": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -6645,8 +8366,6 @@ }, "node_modules/is-date-object": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -6664,8 +8383,7 @@ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-docker": { @@ -6685,8 +8403,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" @@ -6694,8 +8410,6 @@ }, "node_modules/is-finalizationregistry": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "dependencies": { "call-bound": "^1.0.3" @@ -6717,8 +8431,6 @@ }, "node_modules/is-generator-function": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "dependencies": { "call-bound": "^1.0.4", @@ -6736,8 +8448,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" @@ -6748,8 +8458,6 @@ }, "node_modules/is-map": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "engines": { "node": ">= 0.4" @@ -6765,8 +8473,6 @@ }, "node_modules/is-negative-zero": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -6777,8 +8483,6 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" @@ -6786,8 +8490,6 @@ }, "node_modules/is-number-object": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -6802,8 +8504,6 @@ }, "node_modules/is-regex": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -6820,8 +8520,6 @@ }, "node_modules/is-regexp": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -6829,8 +8527,6 @@ }, "node_modules/is-set": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "engines": { "node": ">= 0.4" @@ -6841,8 +8537,6 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "dependencies": { "call-bound": "^1.0.3" @@ -6856,8 +8550,6 @@ }, "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" @@ -6868,8 +8560,6 @@ }, "node_modules/is-string": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -6884,8 +8574,6 @@ }, "node_modules/is-symbol": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -6899,10 +8587,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-typed-array": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "dependencies": { "which-typed-array": "^1.1.16" @@ -6916,8 +8615,6 @@ }, "node_modules/is-weakmap": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "engines": { "node": ">= 0.4" @@ -6928,8 +8625,6 @@ }, "node_modules/is-weakref": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "dependencies": { "call-bound": "^1.0.3" @@ -6943,8 +8638,6 @@ }, "node_modules/is-weakset": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -6982,8 +8675,6 @@ }, "node_modules/jackspeak": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", - "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "dev": true, "dependencies": { "@isaacs/cliui": "^9.0.0" @@ -6997,8 +8688,6 @@ }, "node_modules/jake": { "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", "dev": true, "dependencies": { "async": "^3.2.6", @@ -7029,8 +8718,6 @@ }, "node_modules/js-yaml": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -7041,8 +8728,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "bin": { "jsesc": "bin/jsesc" @@ -7053,8 +8738,6 @@ }, "node_modules/json-bigint": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "license": "MIT", "dependencies": { "bignumber.js": "^9.0.0" @@ -7090,10 +8773,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -7113,15 +8801,40 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, "node_modules/jsonpointer": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -7134,18 +8847,16 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "dependencies": { - "json-buffer": "3.0.1" + "@keyv/serialize": "^1.1.1" } }, "node_modules/kind-of": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "engines": { "node": ">=0.10.0" @@ -7167,9 +8878,7 @@ "dev": true }, "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "version": "3.1.0", "dev": true, "engines": { "node": ">=6" @@ -7177,8 +8886,6 @@ }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -7238,13 +8945,69 @@ "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", "dependencies": { - "lie": "3.1.1" + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.2", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.2", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { "p-locate": "^5.0.0" @@ -7280,18 +9043,18 @@ "dev": true }, "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "11.2.7", "dev": true, "dependencies": { "yallist": "^3.0.2" } }, + "node_modules/lucide-static": { + "version": "0.577.0", + "license": "ISC" + }, "node_modules/magic-string": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" @@ -7299,8 +9062,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "engines": { "node": ">= 0.4" @@ -7308,8 +9069,6 @@ }, "node_modules/mathml-tag-names": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true, "funding": { "type": "github", @@ -7324,8 +9083,6 @@ }, "node_modules/meow": { "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "engines": { "node": ">=18" @@ -7336,17 +9093,46 @@ }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { "node": ">= 8" } }, + "node_modules/mergexml": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz", + "integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@xmldom/xmldom": "^0.7.0", + "formidable": "^3.5.1", + "xpath": "0.0.27" + } + }, + "node_modules/mergexml/node_modules/@xmldom/xmldom": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", + "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==", + "deprecated": "this version is no longer supported, please update to at least 0.8.*", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mergexml/node_modules/xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -7356,17 +9142,64 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "4.1.0", + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/miniflare": { - "version": "4.20260301.1", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260301.1.tgz", - "integrity": "sha512-fqkHx0QMKswRH9uqQQQOU/RoaS3Wjckxy3CUX3YGJr0ZIMu7ObvI+NovdYi6RIsSPthNtq+3TPmRNxjeRiasog==", + "version": "4.20260317.0", "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", - "undici": "7.18.2", - "workerd": "1.20260301.1", + "undici": "7.24.4", + "workerd": "1.20260317.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, @@ -7379,8 +9212,6 @@ }, "node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -7389,6 +9220,31 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/minipass": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", @@ -7417,8 +9273,6 @@ }, "node_modules/nanoid": { "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -7500,6 +9354,90 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-html-parser": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.2.tgz", + "integrity": "sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-select": "^4.2.1", + "he": "1.2.0" + } + }, + "node_modules/node-html-parser/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/node-html-parser/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/node-html-parser/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/node-html-parser/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/node-html-parser/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -7508,8 +9446,6 @@ }, "node_modules/node-sarif-builder": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.2.0.tgz", - "integrity": "sha512-kVIOdynrF2CRodHZeP/97Rh1syTUHBNiw17hUCIVhlhEsWlfJm19MuO56s4MdKbr22xWx6mzMnNAgXzVlIYM9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -7522,8 +9458,6 @@ }, "node_modules/node-sarif-builder/node_modules/fs-extra": { "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "dev": true, "license": "MIT", "dependencies": { @@ -7535,10 +9469,24 @@ "node": ">=14.14" } }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -7546,8 +9494,6 @@ }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "engines": { "node": ">= 0.4" @@ -7558,8 +9504,6 @@ }, "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "engines": { "node": ">= 0.4" @@ -7567,8 +9511,6 @@ }, "node_modules/object.assign": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -7595,8 +9537,6 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { @@ -7622,8 +9562,6 @@ }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { "deep-is": "^0.1.3", @@ -7639,8 +9577,6 @@ }, "node_modules/own-keys": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "dependencies": { "get-intrinsic": "^1.2.6", @@ -7656,8 +9592,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" @@ -7671,8 +9605,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { "p-limit": "^3.0.2" @@ -7684,6 +9616,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -7691,8 +9649,6 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { "callsites": "^3.0.0" @@ -7703,8 +9659,6 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", @@ -7726,8 +9680,6 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" @@ -7780,8 +9732,6 @@ }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "engines": { "node": ">=8" @@ -7806,12 +9756,12 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -7838,8 +9788,6 @@ }, "node_modules/possible-typed-array-names": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "engines": { "node": ">= 0.4" @@ -7887,8 +9835,6 @@ }, "node_modules/postcss-safe-parser": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", "dev": true, "funding": [ { @@ -7913,8 +9859,6 @@ }, "node_modules/postcss-scss": { "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, "funding": [ { @@ -7939,8 +9883,6 @@ }, "node_modules/postcss-selector-parser": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -7956,10 +9898,73 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -7967,8 +9972,6 @@ }, "node_modules/prettier": { "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7982,8 +9985,6 @@ }, "node_modules/pretty-bytes": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", - "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", "dev": true, "engines": { "node": "^14.13.1 || >=16.0.0" @@ -8023,22 +10024,54 @@ "node": ">=6" } }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, "node_modules/qified": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/qified/-/qified-0.6.0.tgz", - "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", + "version": "0.9.0", "dev": true, + "license": "MIT", "dependencies": { - "hookified": "^1.14.0" + "hookified": "^2.1.0" }, "engines": { "node": ">=20" } }, + "node_modules/qified/node_modules/hookified": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -8069,10 +10102,22 @@ "node": ">= 6" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8099,8 +10144,6 @@ }, "node_modules/regenerate-unicode-properties": { "version": "10.2.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", - "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, "dependencies": { "regenerate": "^1.4.2" @@ -8116,8 +10159,6 @@ }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8128,51 +10169,320 @@ "set-function-name": "^2.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.13.0", + "dev": true, + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/replace": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/replace/-/replace-1.2.2.tgz", + "integrity": "sha512-C4EDifm22XZM2b2JOYe6Mhn+lBsLBAvLbK8drfUQLTfD1KYl/n3VaW/CDju0Ny4w3xTtegBpg8YNSpFJPUDSjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "2.4.2", + "minimatch": "3.0.5", + "yargs": "^15.3.1" + }, + "bin": { + "replace": "bin/replace.js", + "search": "bin/search.js" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/replace/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/replace/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/replace/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/replace/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/replace/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/replace/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/replace/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/replace/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/replace/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/replace/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/replace/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/regexpu-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", - "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "node_modules/replace/node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.2", - "regjsgen": "^0.8.0", - "regjsparser": "^0.13.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.2.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true + "node_modules/replace/node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" }, - "node_modules/regjsparser": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "node_modules/replace/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/replace/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "license": "MIT", "dependencies": { - "jsesc": "~3.1.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": ">=8" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/replace/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -8198,18 +10508,14 @@ } }, "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/reusify": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "engines": { "iojs": ">=1.0.0", @@ -8246,42 +10552,14 @@ "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": ">=10.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -8303,8 +10581,6 @@ }, "node_modules/safe-array-concat": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8322,8 +10598,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -8341,8 +10615,6 @@ }, "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -8357,8 +10629,6 @@ }, "node_modules/safe-regex-test": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -8378,12 +10648,13 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.4", "dev": true, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/serialize-javascript": { @@ -8395,10 +10666,15 @@ "node": ">=20.0.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { "define-data-property": "^1.1.4", @@ -8414,8 +10690,6 @@ }, "node_modules/set-function-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { "define-data-property": "^1.1.4", @@ -8429,8 +10703,6 @@ }, "node_modules/set-proto": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "dependencies": { "dunder-proto": "^1.0.1", @@ -8443,8 +10715,6 @@ }, "node_modules/sharp": { "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -8486,19 +10756,6 @@ "@img/sharp-win32-x64": "0.34.5" } }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8520,8 +10777,6 @@ }, "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -8539,8 +10794,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -8555,8 +10808,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -8573,8 +10824,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -8603,8 +10852,6 @@ }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { "node": ">=8" @@ -8676,10 +10923,67 @@ "node": ">= 10.x" } }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "dependencies": { "es-errors": "^1.3.0", @@ -8713,8 +11017,6 @@ }, "node_modules/string.prototype.matchall": { "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8740,8 +11042,6 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8761,8 +11061,6 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -8779,8 +11077,6 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -8796,8 +11092,6 @@ }, "node_modules/stringify-object": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", @@ -8810,8 +11104,6 @@ }, "node_modules/stringify-object/node_modules/is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -8828,19 +11120,38 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", "dev": true, "engines": { "node": ">=10" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" @@ -8851,8 +11162,6 @@ }, "node_modules/stylelint": { "version": "16.26.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz", - "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==", "dev": true, "funding": [ { @@ -8914,8 +11223,6 @@ }, "node_modules/stylelint-config-recommended": { "version": "17.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-17.0.0.tgz", - "integrity": "sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==", "dev": true, "funding": [ { @@ -8936,8 +11243,6 @@ }, "node_modules/stylelint-config-recommended-scss": { "version": "16.0.2", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-16.0.2.tgz", - "integrity": "sha512-aUTHhPPWCvFyWaxtckJlCPaXTDFsp4pKO8evXNCsW9OwsaUWyMd6jvcUhSmfGWPrTddvzNqK4rS/UuSLcbVGdQ==", "dev": true, "dependencies": { "postcss-scss": "^4.0.9", @@ -8959,8 +11264,6 @@ }, "node_modules/stylelint-config-standard": { "version": "39.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-39.0.1.tgz", - "integrity": "sha512-b7Fja59EYHRNOTa3aXiuWnhUWXFU2Nfg6h61bLfAb5GS5fX3LMUD0U5t4S8N/4tpHQg3Acs2UVPR9jy2l1g/3A==", "dev": true, "funding": [ { @@ -8984,8 +11287,6 @@ }, "node_modules/stylelint-config-standard-scss": { "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-16.0.0.tgz", - "integrity": "sha512-/FHECLUu+med/e6OaPFpprG86ShC4SYT7Tzb2PTVdDjJsehhFBOioSlWqYFqJxmGPIwO3AMBxNo+kY3dxrbczA==", "dev": true, "dependencies": { "stylelint-config-recommended-scss": "^16.0.1", @@ -9006,8 +11307,6 @@ }, "node_modules/stylelint-scss": { "version": "6.14.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz", - "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==", "dev": true, "dependencies": { "css-tree": "^3.0.1", @@ -9066,28 +11365,22 @@ }, "node_modules/stylelint/node_modules/file-entry-cache": { "version": "11.1.2", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.2.tgz", - "integrity": "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==", "dev": true, "dependencies": { "flat-cache": "^6.1.20" } }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.20", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.20.tgz", - "integrity": "sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==", + "node_modules/stylelint/node_modules/file-entry-cache/node_modules/flat-cache": { + "version": "6.1.21", "dev": true, "dependencies": { - "cacheable": "^2.3.2", - "flatted": "^3.3.3", + "cacheable": "^2.3.3", + "flatted": "^3.4.1", "hookified": "^1.15.0" } }, "node_modules/stylelint/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "engines": { "node": ">= 4" @@ -9138,8 +11431,6 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" @@ -9150,41 +11441,65 @@ }, "node_modules/supports-hyperlinks": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "dev": true + }, + "node_modules/svgo": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" }, "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/svgo" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16" } }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, "node_modules/table": { "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "dependencies": { "ajv": "^8.0.1", @@ -9197,10 +11512,10 @@ "node": ">=10.0.0" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "node_modules/tar": { + "version": "7.5.12", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.12.tgz", + "integrity": "sha512-9TsuLcdhOn4XztcQqhNyq1KOwOOED/3k58JAvtULiYqbO8B/0IBAAIE1hj0Svmm58k27TmcigyDI0deMlgG3uw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", @@ -9228,15 +11543,45 @@ "@msgpack/msgpack": "^3.1.3" }, "engines": { - "node": ">=22.6.0" - }, - "peerDependencies": { - "typescript": ">=4.5.0" + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", + "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.8.tgz", + "integrity": "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/tar": { @@ -9264,10 +11609,18 @@ "node": ">=18" } }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, "node_modules/temp-dir": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, "engines": { "node": ">=8" @@ -9275,8 +11628,6 @@ }, "node_modules/tempy": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", "dev": true, "dependencies": { "is-stream": "^2.0.0", @@ -9322,10 +11673,45 @@ "readable-stream": "3" } }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "dependencies": { "fdir": "^6.5.0", @@ -9338,10 +11724,10 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "engines": { "node": ">=12.0.0" @@ -9369,8 +11755,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" @@ -9404,8 +11788,6 @@ }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -9416,8 +11798,6 @@ }, "node_modules/type-fest": { "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, "engines": { "node": ">=10" @@ -9428,8 +11808,6 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -9442,8 +11820,6 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "dependencies": { "call-bind": "^1.0.8", @@ -9461,8 +11837,6 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", @@ -9482,8 +11856,6 @@ }, "node_modules/typed-array-length": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -9505,6 +11877,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9532,16 +11905,14 @@ } ], "bin": { - "ua-parser-js": "script/cli.js" + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": "*" + "node": ">=0.8.0" } }, "node_modules/unbox-primitive": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "dependencies": { "call-bound": "^1.0.3", @@ -9557,9 +11928,7 @@ } }, "node_modules/undici": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.2.tgz", - "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==", + "version": "7.24.4", "dev": true, "license": "MIT", "engines": { @@ -9584,8 +11953,6 @@ }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "engines": { "node": ">=4" @@ -9593,8 +11960,6 @@ }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", @@ -9606,8 +11971,6 @@ }, "node_modules/unicode-match-property-value-ecmascript": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", - "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "engines": { "node": ">=4" @@ -9615,8 +11978,6 @@ }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", - "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "engines": { "node": ">=4" @@ -9624,8 +11985,6 @@ }, "node_modules/unique-string": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "dependencies": { "crypto-random-string": "^2.0.0" @@ -9653,8 +12012,6 @@ }, "node_modules/upath": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true, "engines": { "node": ">=4", @@ -9663,8 +12020,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -9693,8 +12048,6 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "punycode": "^2.1.0" @@ -9707,8 +12060,6 @@ }, "node_modules/uuid": { "version": "13.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -9718,10 +12069,26 @@ "uuid": "dist-node/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vite": { "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "dependencies": { "esbuild": "^0.27.0", @@ -9794,8 +12161,6 @@ }, "node_modules/vite-plugin-pwa": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.2.0.tgz", - "integrity": "sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==", "dev": true, "dependencies": { "debug": "^4.3.6", @@ -9822,16 +12187,18 @@ } } }, - "node_modules/vite-plugin-pwa/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/vite/node_modules/rollup": { + "version": "4.59.0", "dev": true, "dependencies": { - "ms": "^2.1.3" + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=6.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, "peerDependenciesMeta": { "supports-color": { @@ -9884,8 +12251,6 @@ }, "node_modules/which-boxed-primitive": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, "dependencies": { "is-bigint": "^1.1.0", @@ -9903,8 +12268,6 @@ }, "node_modules/which-builtin-type": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, "dependencies": { "call-bound": "^1.0.2", @@ -9930,8 +12293,6 @@ }, "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "dependencies": { "is-map": "^2.0.3", @@ -9946,10 +12307,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, "node_modules/which-typed-array": { "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", @@ -9969,17 +12335,20 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/workbox-background-sync": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.4.0.tgz", - "integrity": "sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==", "dev": true, "dependencies": { "idb": "^7.0.1", @@ -9988,8 +12357,6 @@ }, "node_modules/workbox-broadcast-update": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.4.0.tgz", - "integrity": "sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -9997,8 +12364,6 @@ }, "node_modules/workbox-build": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.4.0.tgz", - "integrity": "sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==", "dev": true, "dependencies": { "@apideck/better-ajv-errors": "^0.3.1", @@ -10145,9 +12510,9 @@ } }, "node_modules/workbox-build/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" @@ -10164,9 +12529,6 @@ }, "node_modules/workbox-build/node_modules/glob": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", - "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "dependencies": { "foreground-child": "^3.3.1", @@ -10194,8 +12556,6 @@ }, "node_modules/workbox-build/node_modules/minimatch": { "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "dependencies": { "brace-expansion": "^5.0.2" @@ -10209,8 +12569,6 @@ }, "node_modules/workbox-build/node_modules/pretty-bytes": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, "engines": { "node": ">=6" @@ -10236,8 +12594,6 @@ }, "node_modules/workbox-cacheable-response": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.4.0.tgz", - "integrity": "sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -10251,8 +12607,6 @@ }, "node_modules/workbox-expiration": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.4.0.tgz", - "integrity": "sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==", "dev": true, "dependencies": { "idb": "^7.0.1", @@ -10261,8 +12615,6 @@ }, "node_modules/workbox-google-analytics": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.4.0.tgz", - "integrity": "sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==", "dev": true, "dependencies": { "workbox-background-sync": "7.4.0", @@ -10273,8 +12625,6 @@ }, "node_modules/workbox-navigation-preload": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.4.0.tgz", - "integrity": "sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -10282,8 +12632,6 @@ }, "node_modules/workbox-precaching": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.4.0.tgz", - "integrity": "sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==", "dev": true, "dependencies": { "workbox-core": "7.4.0", @@ -10293,8 +12641,6 @@ }, "node_modules/workbox-range-requests": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.4.0.tgz", - "integrity": "sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -10302,8 +12648,6 @@ }, "node_modules/workbox-recipes": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.4.0.tgz", - "integrity": "sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==", "dev": true, "dependencies": { "workbox-cacheable-response": "7.4.0", @@ -10316,8 +12660,6 @@ }, "node_modules/workbox-routing": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.4.0.tgz", - "integrity": "sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -10325,8 +12667,6 @@ }, "node_modules/workbox-strategies": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.4.0.tgz", - "integrity": "sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==", "dev": true, "dependencies": { "workbox-core": "7.4.0" @@ -10334,8 +12674,6 @@ }, "node_modules/workbox-streams": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.4.0.tgz", - "integrity": "sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==", "dev": true, "dependencies": { "workbox-core": "7.4.0", @@ -10350,8 +12688,6 @@ }, "node_modules/workbox-window": { "version": "7.4.0", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.4.0.tgz", - "integrity": "sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==", "dev": true, "dependencies": { "@types/trusted-types": "^2.0.2", @@ -10359,9 +12695,7 @@ } }, "node_modules/workerd": { - "version": "1.20260301.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260301.1.tgz", - "integrity": "sha512-oterQ1IFd3h7PjCfT4znSFOkJCvNQ6YMOyZ40YsnO3nrSpgB4TbJVYWFOnyJAw71/RQuupfVqZZWKvsy8GO3fw==", + "version": "1.20260317.1", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -10372,11 +12706,29 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260301.1", - "@cloudflare/workerd-darwin-arm64": "1.20260301.1", - "@cloudflare/workerd-linux-64": "1.20260301.1", - "@cloudflare/workerd-linux-arm64": "1.20260301.1", - "@cloudflare/workerd-windows-64": "1.20260301.1" + "@cloudflare/workerd-darwin-64": "1.20260317.1", + "@cloudflare/workerd-darwin-arm64": "1.20260317.1", + "@cloudflare/workerd-linux-64": "1.20260317.1", + "@cloudflare/workerd-linux-arm64": "1.20260317.1", + "@cloudflare/workerd-windows-64": "1.20260317.1" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrangler": { @@ -10433,15 +12785,11 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/ws": { "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "license": "MIT", "engines": { @@ -10503,10 +12851,18 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" @@ -10517,8 +12873,6 @@ }, "node_modules/youch": { "version": "4.1.0-beta.10", - "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", - "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10531,8 +12885,6 @@ }, "node_modules/youch-core": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", - "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 3f08c8e86..e7fa05cc7 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,7 @@ "name": "monochrome", "type": "module", "version": "2.5.0", - "description": "[\"Monochrome](https://monochrome.samidy.com)", - "main": "sw.js", + "description": "[\"Monochrome](https://monochrome.tf)", "scripts": { "dev": "vite", "dev:capacitor": "npm run dev", @@ -17,21 +16,20 @@ "lint:js": "eslint .", "lint:css": "stylelint \"**/*.css\"", "lint:html": "htmlhint \"**/*.html\" --ignore=\"dist/**,legacy/**,node_modules/**\"", - "lint": "npm run lint:js && npm run lint:css && npm run lint:html", - "format": "prettier --write .", - "test": "echo \"Error: no test specified\" && exit 1" + "lint": "bun run lint:js && bun run lint:css && bun run lint:html", + "format": "prettier --write ." }, "repository": { "type": "git", - "url": "git+https://github.com/SamidyFR/monochrome.git" + "url": "git+https://github.com/monochrome-music/monochrome.git" }, "keywords": [], "author": "", "license": "ISC", "bugs": { - "url": "https://github.com/SamidyFR/monochrome/issues" + "url": "https://github.com/monochrome-music/monochrome/issues" }, - "homepage": "https://github.com/SamidyFR/monochrome#readme", + "homepage": "https://github.com/monochrome-music/monochrome#readme", "devDependencies": { "@capacitor/cli": "^7.4.3", "@types/node": "^25.3.5", @@ -80,13 +78,18 @@ "appwrite": "^23.0.0", "butterchurn": "^2.6.7", "butterchurn-presets": "^2.4.7", + "client-zip": "^2.5.0", "cookie-session": "^2.1.1", - "dashjs": "^5.1.1", + "eventemitter3": "^5.0.4", + "events": "^3.3.0", "fuse.js": "^7.1.0", "hls.js": "^1.6.15", "jose": "^6.2.0", "pocketbase": "^0.26.8", - "taglib-wasm": "^1.0.5", + "shaka-player": "^5.0.7", + "simple-icons": "^16.12.0", + "svgo": "^4.0.1", + "url-toolkit": "^2.2.5", "uuid": "^13.0.0" } } diff --git a/public/assets/icons/icon-128.webp b/public/assets/icons/icon-128.webp new file mode 100644 index 000000000..e00c05458 Binary files /dev/null and b/public/assets/icons/icon-128.webp differ diff --git a/public/assets/icons/icon-192.webp b/public/assets/icons/icon-192.webp new file mode 100644 index 000000000..549a2a881 Binary files /dev/null and b/public/assets/icons/icon-192.webp differ diff --git a/public/assets/icons/icon-256.webp b/public/assets/icons/icon-256.webp new file mode 100644 index 000000000..343c27f74 Binary files /dev/null and b/public/assets/icons/icon-256.webp differ diff --git a/public/assets/icons/icon-48.webp b/public/assets/icons/icon-48.webp new file mode 100644 index 000000000..a674dd80d Binary files /dev/null and b/public/assets/icons/icon-48.webp differ diff --git a/public/assets/icons/icon-512.webp b/public/assets/icons/icon-512.webp new file mode 100644 index 000000000..c20c724e0 Binary files /dev/null and b/public/assets/icons/icon-512.webp differ diff --git a/public/assets/icons/icon-72.webp b/public/assets/icons/icon-72.webp new file mode 100644 index 000000000..1cbddf864 Binary files /dev/null and b/public/assets/icons/icon-72.webp differ diff --git a/public/assets/icons/icon-96.webp b/public/assets/icons/icon-96.webp new file mode 100644 index 000000000..17fc371d5 Binary files /dev/null and b/public/assets/icons/icon-96.webp differ diff --git a/public/editors-picks.json b/public/editors-picks.json index 808fa8661..8cd41be97 100644 --- a/public/editors-picks.json +++ b/public/editors-picks.json @@ -1,4 +1,70 @@ [ + { + "type": "album", + "id": 18083938, + "title": "The Glow, Pt. 2", + "artist": { "id": 3941394, "name": "The Microphones" }, + "releaseDate": "2001-09-25", + "cover": "ec648c22-9140-41d3-a7ae-0ba69ef0420e", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 382839956, + "title": "my anti-aircraft friend", + "artist": { "id": 19359095, "name": "julie" }, + "releaseDate": "2024-09-13", + "cover": "ac790b52-61cc-460c-9277-bdac88722cc3", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 456475370, + "title": "It Aint Nun", + "artist": { "id": 9981740, "name": "CHRIST DILLINGER" }, + "releaseDate": "2024-09-12", + "cover": "3ffc27f6-a77c-4e68-ba44-e04f034783be", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 112547160, + "title": "R F Y", + "artist": { "id": 36042731, "name": "RFY" }, + "releaseDate": "2019-06-27", + "cover": "ffe3f6f9-5bc8-4b53-99c3-9b83676c099a", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 18658568, + "title": "100% Ghetto 4", + "artist": { "id": 4191963, "name": "DJ Clent" }, + "releaseDate": "2010-10-02", + "cover": "82b839bd-7cf6-4650-bade-192f47301ffd", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 504004321, + "title": "Half Blood (BloodLuxe)", + "artist": { "id": 50799233, "name": "slayr" }, + "releaseDate": "2025-11-05", + "cover": "2767cc63-7e92-4a48-aa4b-806a3ea7ec1c", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, { "type": "album", "id": 89313048, @@ -163,5 +229,71 @@ "explicit": true, "audioQuality": "LOSSLESS", "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 365819314, + "title": "One Life", + "artist": { "id": "17300439", "name": "1oneam" }, + "releaseDate": "2024-05-30", + "cover": "eb5d74f6-7403-4404-8452-9b68713445fe", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 379517195, + "title": "Haram", + "artist": { "id": 5225704, "name": "Armand Hammer" }, + "releaseDate": "2021-03-26", + "cover": "69ebc3e7-bd0b-4dd7-88a5-a2e180b84f0d", + "explicit": false, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 36160524, + "title": "Nasa Gang (Remastered)", + "artist": { "id": 4611745, "name": "SpaceGhostPurrp" }, + "releaseDate": "2014-10-07", + "cover": "359d42ec-1984-4d63-a4ae-ecf286463372", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 445752470, + "title": "FOR NOTHING", + "artist": { "id": 49124576, "name": "nine vicious" }, + "releaseDate": "2025-07-04", + "cover": "8b9018dd-d3c3-46e0-be5a-c16d48180176", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } + }, + { + "type": "album", + "id": 435083611, + "title": "Buddha Therapy", + "artist": { "id": 4858188, "name": "Metro Zu" }, + "releaseDate": "2017-05-01", + "cover": "5c6c367a-99ed-4fa4-8e91-ea10d6066e26", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS", "HIRES_LOSSLESS"] } + }, + { + "type": "album", + "id": 473188494, + "title": "Blue Flame", + "artist": { "id": 3799089, "name": "Lil B" }, + "releaseDate": "2010-09-13", + "cover": "35b19623-cb5c-491a-81ea-ebac108c58f2", + "explicit": true, + "audioQuality": "LOSSLESS", + "mediaMetadata": { "tags": ["LOSSLESS"] } } ] diff --git a/public/instances.json b/public/instances.json index 1b61974f3..d5a8bb968 100644 --- a/public/instances.json +++ b/public/instances.json @@ -19,6 +19,7 @@ "https://maus.qqdl.site", "https://vogel.qqdl.site", "https://katze.qqdl.site", - "https://hund.qqdl.site" + "https://hund.qqdl.site", + "https://hifi.p1nkhamster.xyz/" ] } diff --git a/public/lib/butterchurnPresets.min.js b/public/lib/butterchurnPresets.min.js index a16d7e477..e7fcf2c31 100644 --- a/public/lib/butterchurnPresets.min.js +++ b/public/lib/butterchurnPresets.min.js @@ -1 +1,8350 @@ -!function(a,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("butterchurnPresets",[],e):"object"==typeof exports?exports.butterchurnPresets=e():a.butterchurnPresets=e()}("undefined"!=typeof self?self:this,function(){return function(a){var e={};function t(r){if(e[r])return e[r].exports;var n=e[r]={i:r,l:!1,exports:{}};return a[r].call(n.exports,n,n.exports,t),n.l=!0,n.exports}return t.m=a,t.c=e,t.d=function(a,e,r){t.o(a,e)||Object.defineProperty(a,e,{configurable:!1,enumerable:!0,get:r})},t.n=function(a){var e=a&&a.__esModule?function(){return a.default}:function(){return a};return t.d(e,"a",e),e},t.o=function(a,e){return Object.prototype.hasOwnProperty.call(a,e)},t.p="",t(t.s=165)}([function(a,e,t){a.exports=!t(5)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(a,e){a.exports=function(a){return"object"==typeof a?null!==a:"function"==typeof a}},function(a,e){var t=a.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(a,e){var t=a.exports={version:"2.5.3"};"number"==typeof __e&&(__e=t)},function(a,e,t){var r=t(15),n=t(16),_=t(18),s=Object.defineProperty;e.f=t(0)?Object.defineProperty:function(a,e,t){if(r(a),e=_(e,!0),r(t),n)try{return s(a,e,t)}catch(a){}if("get"in t||"set"in t)throw TypeError("Accessors not supported!");return"value"in t&&(a[e]=t.value),a}},function(a,e){a.exports=function(a){try{return!!a()}catch(a){return!0}}},function(a,e,t){"use strict";e.__esModule=!0,e.default=function(a,e){if(!(a instanceof e))throw new TypeError("Cannot call a class as a function")}},function(a,e,t){"use strict";e.__esModule=!0;var r,n=t(8),_=(r=n)&&r.__esModule?r:{default:r};e.default=function(){function a(a,e){for(var t=0;t 1.0)\n ) * (\n (tmpvar_8 * -2.0)\n + 1.570796)));\n tmpvar_6 = (tmpvar_8 * sign((uv_1.y / uv_1.x)));\n if ((abs(uv_1.x) > (1e-08 * abs(uv_1.y)))) {\n if ((uv_1.x < 0.0)) {\n if ((uv_1.y >= 0.0)) {\n tmpvar_6 += 3.141593;\n } else {\n tmpvar_6 = (tmpvar_6 - 3.141593);\n };\n };\n } else {\n tmpvar_6 = (sign(uv_1.y) * 1.570796);\n };\n xlat_mutablers0.x = ((tmpvar_6 / 3.1416) * 2.0);\n xlat_mutablers0.y = (0.03 / sqrt(dot (uv_1, uv_1)));\n ret1_3 = vec3(0.0, 0.0, 0.0);\n for (int n_2 = 0; n_2 <= 10; n_2++) {\n float tmpvar_9;\n tmpvar_9 = fract((-(q9) + (\n float(n_2)\n / 10.0)));\n xlat_mutableang2 = (((q1 * 3.14) * float(n_2)) / 10.0);\n float tmpvar_10;\n tmpvar_10 = cos(xlat_mutableang2);\n float tmpvar_11;\n tmpvar_11 = sin(xlat_mutableang2);\n mat2 tmpvar_12;\n tmpvar_12[uint(0)].x = tmpvar_10;\n tmpvar_12[uint(0)].y = -(tmpvar_11);\n tmpvar_12[1u].x = tmpvar_11;\n tmpvar_12[1u].y = tmpvar_10;\n xlat_mutableuv2 = (uv_1 * ((q13 * tmpvar_9) * tmpvar_12));\n ret1_3 = max (ret1_3, (texture (sampler_main, (xlat_mutableuv2 + 0.5)).xyz * (1.0 - tmpvar_9)));\n };\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = ((ret1_3 * 2.0) + ((\n (bass_att * xlat_mutablers0.y)\n * texture (sampler_main, \n ((uv_1 * q12) + vec2(0.5, 0.0))\n ).yzx) * clamp (\n (1.0 - (ret1_3 * 32.0))\n , 0.0, 1.0)));\n ret = tmpvar_13.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:.965,echo_zoom:1.483827,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,wave_brighten:0,wrap:0,darken_center:1,darken:1,wave_a:.001,wave_scale:1.285751,wave_smoothing:.63,modwavealphastart:.71,modwavealphaend:1.3,warpanimspeed:.01,warpscale:1.470245,zoomexp:4.778023,zoom:.998162,warp:.01,sx:1.001828,wave_r:.65,wave_g:.65,wave_b:.65,ob_size:.005,ob_r:1,ob_g:.5,ob_b:.5,ob_a:1,ib_size:.5,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:4.800001,mv_dx:.4,mv_l:1,mv_r:0,mv_g:.5,mv_a:.1},shapes:[{baseVals:{enabled:1,sides:3,additive:1,thickoutline:1,textured:1,x:1,y:.59,rad:.559231,ang:3.39292,tex_zoom:100,r:0,g:1,b:1,g2:0,border_r:0,border_g:0,border_b:0,border_a:1},init_eqs_str:"",frame_eqs_str:"a.x=.1*Math.sin(div(a.time,10))+.5+.1*a.treb_att;"},{baseVals:{enabled:0}},{baseVals:{enabled:1,sides:6,textured:1,x:.3,y:.7,rad:1.089252,ang:.816814,tex_ang:3.141592,tex_zoom:.504215,g:1,b:1,r2:1,b2:1,border_a:0},init_eqs_str:"",frame_eqs_str:""},{baseVals:{enabled:1,sides:3,textured:1,rad:.284278,ang:3.141593,tex_ang:4.900885,tex_zoom:2.987755,g:1,b:1,r2:.95,b2:1,a2:1,border_r:0,border_g:0,border_b:0,border_a:1},init_eqs_str:'a["var"]=0;',frame_eqs_str:'a.ang=div(a.time,10);a.tex_zoom=3.4+.03*a.bass;a["var"]=above(a.bass_att,.7);a.a=a["var"];a.a2=a["var"];a.border_a=a["var"];'}],waves:[{baseVals:{enabled:1,usedots:1,thick:1,additive:1,r:0,a:.06},init_eqs_str:"a.px=0;a.xoffset2=0;a.py=0;a.xoffset1=0;a.pheight=0;a.pphase=0;a.yspout=0;a.pphase2=0;a.xspout=0;a.lrorient=0;a.yheight=0;",frame_eqs_str:"",point_eqs_str:"a.xspout=.5;a.yspout=-.01;a.pphase=9999*a.sample*a.sample*.0001;a.pphase2=.1+.01*mod(3349*a.sample*a.sample,100);a.pheight=.002*mod(9893*a.sample,100);a.yheight=.01*mod(1231*a.sample*a.sample,100);a.r=.01*mod(5454*a.sample,100)*Math.abs(Math.sin(.25*a.time));a.g=.01*mod(9954*a.sample,100);a.xoffset1=Math.cos(a.time*a.pphase2+a.pphase)*a.pheight;a.xoffset2=-1*Math.cos(a.time*a.pphase2+a.pphase)*a.pheight;a.lrorient=.00001 1.0)\n ) * (\n (tmpvar_8 * -2.0)\n + 1.570796)));\n tmpvar_6 = (tmpvar_8 * sign((uv_1.y / uv_1.x)));\n if ((abs(uv_1.x) > (1e-08 * abs(uv_1.y)))) {\n if ((uv_1.x < 0.0)) {\n if ((uv_1.y >= 0.0)) {\n tmpvar_6 += 3.141593;\n } else {\n tmpvar_6 = (tmpvar_6 - 3.141593);\n };\n };\n } else {\n tmpvar_6 = (sign(uv_1.y) * 1.570796);\n };\n xlat_mutablers0.x = (((tmpvar_6 / 3.1416) * 6.0) * q28);\n xlat_mutablers0.y = inversesqrt(dot (uv_1, uv_1));\n vec2 tmpvar_9;\n tmpvar_9.x = (xlat_mutablers0.x + (q9 * 8.0));\n tmpvar_9.y = (xlat_mutablers0.y + ((q9 * q28) * 4.0));\n xlat_mutablerss = (tmpvar_9 / 12.0);\n vec2 tmpvar_10;\n tmpvar_10.x = q5;\n tmpvar_10.y = q6;\n ofs_2 = (0.1 * tmpvar_10.yx);\n float tmpvar_11;\n float tmpvar_12;\n tmpvar_12 = -(q9);\n tmpvar_11 = fract(tmpvar_12);\n mat2 tmpvar_13;\n tmpvar_13[uint(0)].x = 1.0;\n tmpvar_13[uint(0)].y = -0.0;\n tmpvar_13[1u].x = 0.0;\n tmpvar_13[1u].y = 1.0;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_11)\n * tmpvar_13)) * aspect.yx);\n vec2 tmpvar_14;\n tmpvar_14 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_14).xyz + ((texture (sampler_blur1, tmpvar_14).xyz * scale1) + bias1));\n ret1_3 = max (vec3(0.0, 0.0, 0.0), ((xlat_mutableneu * \n (1.0 - (tmpvar_11 * tmpvar_11))\n ) * 2.0));\n float tmpvar_15;\n tmpvar_15 = fract((tmpvar_12 + 0.3333333));\n mat2 tmpvar_16;\n tmpvar_16[uint(0)].x = -0.4990803;\n tmpvar_16[uint(0)].y = -0.8665558;\n tmpvar_16[1u].x = 0.8665558;\n tmpvar_16[1u].y = -0.4990803;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_15)\n * tmpvar_16)) * aspect.yx);\n vec2 tmpvar_17;\n tmpvar_17 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_17).xyz + ((texture (sampler_blur1, tmpvar_17).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_15 * tmpvar_15))\n ) * 2.0));\n float tmpvar_18;\n tmpvar_18 = fract((tmpvar_12 + 0.6666667));\n mat2 tmpvar_19;\n tmpvar_19[uint(0)].x = -0.5018377;\n tmpvar_19[uint(0)].y = 0.8649619;\n tmpvar_19[1u].x = -0.8649619;\n tmpvar_19[1u].y = -0.5018377;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_18)\n * tmpvar_19)) * aspect.yx);\n vec2 tmpvar_20;\n tmpvar_20 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_20).xyz + ((texture (sampler_blur1, tmpvar_20).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_18 * tmpvar_18))\n ) * 2.0));\n float tmpvar_21;\n tmpvar_21 = fract((tmpvar_12 + 1.0));\n mat2 tmpvar_22;\n tmpvar_22[uint(0)].x = 0.9999949;\n tmpvar_22[uint(0)].y = 0.003185092;\n tmpvar_22[1u].x = -0.003185092;\n tmpvar_22[1u].y = 0.9999949;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_21)\n * tmpvar_22)) * aspect.yx);\n vec2 tmpvar_23;\n tmpvar_23 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_23).xyz + ((texture (sampler_blur1, tmpvar_23).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_21 * tmpvar_21))\n ) * 2.0));\n vec2 tmpvar_24;\n tmpvar_24.x = (ret1_3.x + ret1_3.z);\n tmpvar_24.y = (ret1_3.x - ret1_3.y);\n vec4 tmpvar_25;\n tmpvar_25.w = 1.0;\n tmpvar_25.xyz = ((ret1_3 + (\n ((bass_att * 0.004) / sqrt(dot (uv_1, uv_1)))\n * roam_sin).xyz) + ((2.0 * \n (bass_att * ((texture (sampler_blur1, fract(\n (xlat_mutablerss + (tmpvar_24 / 2.0))\n )).xyz * scale1) + bias1).zxy)\n ) * clamp (\n (1.0 - (ret1_3 * 4.0))\n , 0.0, 1.0)));\n ret = tmpvar_25.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.14,decay:1,echo_zoom:1,wave_mode:6,wave_thick:1,wave_brighten:0,wrap:0,darken:1,wave_a:1.17,wave_scale:.797,wave_smoothing:0,modwavealphastart:.71,modwavealphaend:1.3,warpscale:1.331,zoomexp:.9995,zoom:.9998,rot:.02,dy:-.008,warp:.01,sx:1.0098,wave_r:.5,wave_g:.5,wave_b:.5,wave_x:.9,ob_size:.005,ob_a:.8,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:44.8,mv_y:38.4,mv_l:5,mv_g:.91,mv_b:.71,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.q12=0;a.q18=0;a.q6=0;a.bass_thresh=0;a.wg=0;a.q11=0;a.q10=0;a.wb=0;a.q17=0;a.vol=0;a.q2=0;a.q3=0;a.wr=0;a.q7=0;a.q8=0;",frame_eqs_str:"a.wave_r+=.3*Math.sin(50*a.vol);a.wave_b+=.3*Math.sin(20*a.vol);a.wave_g+=.5*Math.sin(35*a.vol);a.q8=a.wave_r;a.q7=a.wave_b;a.q6=a.wave_g;a.wr=.5+.4*(.6*Math.sin(1.1*a.time)+.4*Math.sin(.8*a.time));a.wb=.5+.4*(.6*Math.sin(1.6*a.time)+.4*Math.sin(.5*a.time));a.wg=.5+.4*(.6*Math.sin(1.34*a.time)+.4*Math.sin(.4*a.time));a.monitor=a.wg;a.q10=a.wr;a.q11=a.wb;a.q12=a.wg;a.q18=.007*Math.sin(.1*a.time);a.q17=-.007*Math.sin(.254*a.time);a.q2=a.bass_thresh;a.vol=.25*(a.bass+a.mid+a.treb);\na.vol*=a.vol;a.q3=a.vol;a.warp=0;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec3 noise3_1;\n vec3 tmpvar_2;\n tmpvar_2 = (texture (sampler_main, uv).xyz + ((texture (sampler_blur1, uv).xyz * scale1) + bias1));\n vec2 tmpvar_3;\n tmpvar_3 = (0.5 + ((\n (uv - vec2(0.0, 1.0))\n - 0.5) * (1.0 + \n (tmpvar_2.y * 0.03)\n )));\n vec2 tmpvar_4;\n tmpvar_4.x = (tmpvar_3.x + pow (tmpvar_2.x, 0.0));\n tmpvar_4.y = (tmpvar_3.y + pow (tmpvar_2.x, 0.005));\n noise3_1 = (texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * texsize_noise_lq.zw) + rand_frame.xy)).xyz * fract(q15));\n vec3 tmpvar_5;\n tmpvar_5 = (noise3_1 * (vec3(1.0, 1.0, 1.0) - vec3(fract(\n (q3 * 0.5)\n ))));\n noise3_1 = tmpvar_5;\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_main, fract(tmpvar_4));\n vec3 tmpvar_7;\n tmpvar_7.x = q10;\n tmpvar_7.y = q11;\n tmpvar_7.z = q12;\n vec3 tmpvar_8;\n tmpvar_8 = mix (tmpvar_5, tmpvar_7, tmpvar_6.xxx);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = (tmpvar_6.xyz + clamp ((\n (tmpvar_6.yzx * tmpvar_8.zxy)\n - \n (tmpvar_6.zxy * tmpvar_8.yzx)\n ), 0.0, 1.0));\n ret = tmpvar_9.xyz;\n }",comp:" shader_body { \n vec2 uv1_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n vec2 tmpvar_4;\n tmpvar_4.x = (texture (sampler_main, (uv - tmpvar_2)).xyz - texture (sampler_main, (uv + tmpvar_2)).xyz).x;\n tmpvar_4.y = (texture (sampler_main, (uv - tmpvar_3)).xyz - texture (sampler_main, (uv + tmpvar_3)).xyz).x;\n uv1_1 = ((0.3 * cos(\n ((uv - 0.5) * 2.0)\n )) - tmpvar_4);\n float tmpvar_5;\n tmpvar_5 = clamp ((0.04 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0);\n uv1_1 = ((0.3 * cos(\n (uv1_1 * 12.0)\n )) - (9.0 * tmpvar_4));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = (tmpvar_5 + ((texture (sampler_main, uv).xyz * 12.0) * vec3(clamp (\n (0.04 / sqrt(dot (uv1_1, uv1_1)))\n , 0.0, 1.0))));\n ret = tmpvar_6.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.14,decay:1,echo_zoom:1,wave_mode:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:.179,wave_smoothing:0,wave_mystery:.3,modwavealphastart:.71,modwavealphaend:1.3,warpscale:1.331,zoomexp:.8195,zoom:1.0697,dy:.006,warp:.01,sx:.9996,wave_g:0,wave_b:0,ob_a:.8,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:0,mv_y:0,mv_l:1,mv_g:.91,mv_b:.71,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.q12=0;a.q18=0;a.q6=0;a.q5=0;a.bass_thresh=0;a.wg=0;a.q11=0;a.q10=0;a.wb=0;a.q17=0;a.vol=0;a.q2=0;a.q3=0;a.wr=0;a.q7=0;a.mtime=0;a.q8=0;",frame_eqs_str:"a.bass_thresh=2*above(a.bass_att,a.bass_thresh)+(1-above(a.bass_att,a.bass_thresh))*(.91*(a.bass_thresh-1.3)+1.3);a.wave_r=.5+.5*(.6*Math.sin(1.3*a.time)+.4*Math.sin(.98*a.time));a.wave_b=.5+.5*(.6*Math.sin(1.1*a.time)+.4*Math.sin(.78*a.time));a.wave_g=.5+.5*(.6*Math.sin(1.2*a.time)+.4*Math.sin(.6*a.time));a.q8=a.wave_r;a.q7=a.wave_b;a.q6=a.wave_g;a.wr=.5+.4*(.6*Math.sin(.2*a.time)+.4*Math.sin(.8*a.time));a.wb=.5+.4*(.6*Math.sin(.377*a.time)+.4*Math.sin(.5*a.time));a.wg=.5+\n.4*(.6*Math.sin(.7*a.time)+.4*Math.sin(.4*a.time));a.q10=a.wr;a.q11=a.wb;a.q12=a.wg;a.q10=.8;a.q11=.2;a.q12=.1;a.q18=.01*Math.sin(.1*a.mtime);a.q17=-.01*Math.sin(.254*a.mtime);a.q2=a.bass_thresh;a.vol=.25*(a.bass+a.mid+a.treb);a.vol*=a.vol;a.q3=a.vol;a.q5=.5*a.vol;a.mtime+=.01*a.vol;a.q2=.25*a.mtime;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec3 noise2_1;\n vec3 ret_2;\n vec3 tmpvar_3;\n tmpvar_3 = (((texture (sampler_blur1, uv).xyz * scale1) + bias1) + texture (sampler_main, uv).xyz);\n vec2 tmpvar_4;\n tmpvar_4 = (0.5 + ((uv - 0.5) * (1.0 + \n (tmpvar_3.y * 0.05)\n )));\n vec2 tmpvar_5;\n tmpvar_5.x = (tmpvar_4.x + pow (tmpvar_3.x, q17));\n tmpvar_5.y = (tmpvar_4.y + pow (tmpvar_3.x, q18));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_fc_main, fract(tmpvar_5));\n vec3 tmpvar_7;\n tmpvar_7.x = q10;\n tmpvar_7.y = q11;\n tmpvar_7.z = q12;\n noise2_1 = (texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * texsize_noise_lq.zw) + rand_frame.xy)).xyz + ((tmpvar_7 * vec3(rad)) * vol));\n vec3 a_8;\n a_8 = (1.0 - tmpvar_6.xyz);\n ret_2 = (tmpvar_6.xyz + (0.3 * clamp (\n ((a_8.yzx * noise2_1.zxy) - (a_8.zxy * noise2_1.yzx))\n , 0.0, 1.0)));\n ret_2 = (ret_2 * 0.97);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ret_2;\n ret = tmpvar_9.xyz;\n }",comp:" shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz * vec3(0.9, 0.3, 0.5));\n ret_1 = (ret_1 * 1.34);\n ret_1 = (ret_1 * ret_1);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.28,decay:.8,echo_zoom:1,echo_orient:3,wave_mode:7,additivewave:1,modwavealphabyvolume:1,wave_brighten:0,brighten:1,wave_a:.001,wave_scale:1.286,wave_smoothing:.63,modwavealphastart:.71,modwavealphaend:1.3,zoomexp:3.04777,zoom:1.0173,warp:.01605,wave_g:.65,wave_b:.65,ob_size:0,ob_a:1,mv_x:64,mv_y:48,mv_l:0,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,thick:1,additive:1,g:0,b:0},init_eqs_str:"a.ma=0;a.mx=0;a.my=0;",frame_eqs_str:"",point_eqs_str:"a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=\ndiv(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);a.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*\na.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):\na.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);",frame_eqs_str:"a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*\na.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;\na.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;\na.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?\n-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+\nMath.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;a.bb=.99*a.bb+.02*a.bass;a.mm=.99*a.mm+.02*a.mid;a.tt=.99*a.tt+.02*a.treb;a.mx=Math.max(Math.max(a.bb,a.mm),a.tt);a.mn=Math.min(Math.min(a.bb,a.mm),a.tt);a.h1=div(a.bb-a.mn,a.mx-a.mn);a.h2=div(a.mm-a.mn,a.mx-a.mn);a.h3=div(a.tt-a.mn,a.mx-a.mn);a.v=div(.1333,a.fps);a.bm+=(a.h1-a.h2)*a.v;a.mt+=(a.h2-a.h3)*a.v;a.bt+=(a.h1-a.h3)*a.v;a.w=2*a.bm;a.q3=\nMath.sin(a.w);a.q9=Math.cos(a.w);a.q17=a.bm;a.q18=a.mt;a.q19=a.bt;",pixel_eqs_str:"a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;",warp:"float sustain;\nfloat xlat_mutabledist;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (1.0123 - q14);\n vec2 uv_3;\n vec3 ret_4;\n vec2 tmpvar_5;\n tmpvar_5 = (uv - 0.5);\n xlat_mutableuv1 = ((tmpvar_5 * aspect.xy) * q16);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pc_main, uv);\n uv_3 = ((tmpvar_5 * (1.0 - \n (q10 / (1.0 - ((tmpvar_6.z + \n (0.003921569 * tmpvar_6.y)\n ) + (q10 * 0.7))))\n )) + 0.5);\n vec4 tmpvar_7;\n tmpvar_7 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n xlat_mutabledist = tmpvar_7.x;\n if ((tmpvar_7.y > 0.2)) {\n vec3 tmpvar_8;\n tmpvar_8 = (tmpvar_7.xyz - vec3(0.4, 0.5, 0.5));\n vec2 uvi_9;\n uvi_9 = ((tmpvar_8.zy * 0.003) + uv_3);\n vec2 pix_10;\n vec4 nb2_11;\n vec4 nb_12;\n vec2 x_13;\n x_13 = (uvi_9 - 0.5);\n pix_10 = (texsize.zw * (1.0 + (\n sqrt(dot (x_13, x_13))\n * 8.0)));\n float tmpvar_14;\n tmpvar_14 = (q10 * 0.7);\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pc_main, (uvi_9 - pix_10));\n nb_12.x = (1.0 - ((tmpvar_15.z + \n (0.003921569 * tmpvar_15.y)\n ) + tmpvar_14));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, -1.0))));\n nb_12.y = (1.0 - ((tmpvar_16.z + \n (0.003921569 * tmpvar_16.y)\n ) + tmpvar_14));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pc_main, (uvi_9 + pix_10));\n nb_12.z = (1.0 - ((tmpvar_17.z + \n (0.003921569 * tmpvar_17.y)\n ) + tmpvar_14));\n vec4 tmpvar_18;\n tmpvar_18 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 1.0))));\n nb_12.w = (1.0 - ((tmpvar_18.z + \n (0.003921569 * tmpvar_18.y)\n ) + tmpvar_14));\n vec4 tmpvar_19;\n tmpvar_19 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, -1.0))));\n nb2_11.x = (1.0 - ((tmpvar_19.z + \n (0.003921569 * tmpvar_19.y)\n ) + tmpvar_14));\n vec4 tmpvar_20;\n tmpvar_20 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, 0.0))));\n nb2_11.y = (1.0 - ((tmpvar_20.z + \n (0.003921569 * tmpvar_20.y)\n ) + tmpvar_14));\n vec4 tmpvar_21;\n tmpvar_21 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, 1.0))));\n nb2_11.z = (1.0 - ((tmpvar_21.z + \n (0.003921569 * tmpvar_21.y)\n ) + tmpvar_14));\n vec4 tmpvar_22;\n tmpvar_22 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 0.0))));\n nb2_11.w = (1.0 - ((tmpvar_22.z + \n (0.003921569 * tmpvar_22.y)\n ) + tmpvar_14));\n vec4 tmpvar_23;\n tmpvar_23 = min (nb_12, nb2_11);\n nb_12.zw = tmpvar_23.zw;\n nb_12.xy = min (tmpvar_23.xy, tmpvar_23.zw);\n xlat_mutabledist = (min (nb_12.x, nb_12.y) + ((0.008 * tmpvar_8.x) * abs(tmpvar_8.y)));\n };\n vec4 tmpvar_24;\n tmpvar_24 = texture (sampler_pc_main, uv_3);\n float tmpvar_25;\n tmpvar_25 = min (xlat_mutabledist, (1.0 - (\n (tmpvar_24.z + (0.003921569 * tmpvar_24.y))\n + \n (q10 * 0.7)\n )));\n xlat_mutabledist = tmpvar_25;\n float tmpvar_26;\n tmpvar_26 = (tmpvar_25 + pow (tmpvar_25, 3.0));\n vec3 tmpvar_27;\n tmpvar_27.xy = (xlat_mutableuv1 * tmpvar_26);\n tmpvar_27.z = tmpvar_26;\n xlat_mutableuv2 = (((tmpvar_27 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n float li_28;\n vec3 zz0_29;\n vec3 zz_30;\n zz0_29 = (xlat_mutableuv2 + q8);\n li_28 = 0.0;\n zz_30 = ((2.0 * clamp (xlat_mutableuv2, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - xlat_mutableuv2);\n float tmpvar_31;\n tmpvar_31 = dot (zz_30, zz_30);\n if ((tmpvar_31 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_31 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_31);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_32;\n tmpvar_32 = dot (zz_30, zz_30);\n if ((tmpvar_32 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_32 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_32);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_33;\n tmpvar_33 = dot (zz_30, zz_30);\n if ((tmpvar_33 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_33 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_33);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_34;\n tmpvar_34 = dot (zz_30, zz_30);\n if ((tmpvar_34 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_34 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_34);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_35;\n tmpvar_35 = dot (zz_30, zz_30);\n if ((tmpvar_35 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_35 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_35);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_36;\n tmpvar_36 = dot (zz_30, zz_30);\n if ((tmpvar_36 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_36 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_36);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_37;\n tmpvar_37 = dot (zz_30, zz_30);\n if ((tmpvar_37 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_37 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_37);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_38;\n tmpvar_38 = dot (zz_30, zz_30);\n if ((tmpvar_38 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_38 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_38);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n vec4 tmpvar_39;\n tmpvar_39.xyz = zz_30;\n tmpvar_39.w = li_28;\n float tmpvar_40;\n tmpvar_40 = sqrt(dot (zz_30, zz_30));\n xlat_mutablestruc = (sqrt(dot (tmpvar_39.xyw, tmpvar_39.xyw)) / 24.0);\n vec4 tmpvar_41;\n tmpvar_41 = texture (sampler_pc_main, uv_3);\n float tmpvar_42;\n float tmpvar_43;\n tmpvar_43 = (q10 * 0.7);\n tmpvar_42 = ((log(\n (1.0 + (tmpvar_40 / 24.0))\n ) * 0.02) * (1.0 - (1.0 - \n ((tmpvar_41.z + (0.003921569 * tmpvar_41.y)) + tmpvar_43)\n )));\n float tmpvar_44;\n vec4 tmpvar_45;\n tmpvar_45 = texture (sampler_pc_main, uv_3);\n tmpvar_44 = (1.0 - ((tmpvar_45.z + \n (0.003921569 * tmpvar_45.y)\n ) + tmpvar_43));\n if ((((tmpvar_25 <= tmpvar_44) && (tmpvar_40 < 24.0)) && (tmpvar_25 > 0.005))) {\n ret_4.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(\n (q14 * 4.0)\n )).x));\n float x_46;\n x_46 = ((1.0 - tmpvar_25) * 255.0);\n float ip_47;\n ip_47 = float(int(x_46));\n vec2 tmpvar_48;\n tmpvar_48.x = (x_46 - ip_47);\n tmpvar_48.y = (ip_47 / 255.0);\n ret_4.yz = tmpvar_48;\n } else {\n vec3 tmpvar_49;\n tmpvar_49.y = 0.0;\n tmpvar_49.x = sustain;\n tmpvar_49.z = (1.0 - tmpvar_42);\n vec3 tmpvar_50;\n tmpvar_50.xy = vec2(0.003921569, 0.0);\n tmpvar_50.z = (q14 / 6.0);\n ret_4 = ((texture (sampler_fc_main, uv_3).xyz * tmpvar_49) - tmpvar_50);\n };\n vec4 tmpvar_51;\n tmpvar_51.w = 1.0;\n tmpvar_51.xyz = ret_4;\n ret = tmpvar_51.xyz;\n }",comp:"vec2 xlat_mutabled;\nvec3 xlat_mutabledx;\nvec3 xlat_mutabledy;\n shader_body { \n vec3 ret_1;\n xlat_mutabled = (texsize.zw * 1.5);\n xlat_mutabledx = (texture (sampler_main, (uv_orig + (vec2(1.0, 0.0) * xlat_mutabled))).xyz - texture (sampler_main, (uv_orig - (vec2(1.0, 0.0) * xlat_mutabled))).xyz);\n xlat_mutabledy = (texture (sampler_main, (uv_orig + (vec2(0.0, 1.0) * xlat_mutabled))).xyz - texture (sampler_main, (uv_orig - (vec2(0.0, 1.0) * xlat_mutabled))).xyz);\n vec2 tmpvar_2;\n tmpvar_2.x = xlat_mutabledx.y;\n tmpvar_2.y = xlat_mutabledy.y;\n vec2 x_3;\n x_3 = (tmpvar_2 * 8.0);\n ret_1 = (((texture (sampler_main, uv).x * \n (1.0 - sqrt(dot (x_3, x_3)))\n ) * pow (hue_shader, vec3(6.0, 6.0, 6.0))) * 1.4);\n vec2 tmpvar_4;\n tmpvar_4.x = xlat_mutabledx.z;\n tmpvar_4.y = xlat_mutabledy.z;\n vec2 x_5;\n x_5 = (tmpvar_4 * 4.0);\n vec3 tmpvar_6;\n tmpvar_6 = mix (ret_1, vec3(1.0, 1.0, 1.0), vec3(sqrt(dot (x_5, x_5))));\n ret_1 = tmpvar_6;\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = tmpvar_6;\n ret = tmpvar_7.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.9,echo_zoom:1.169,echo_orient:1,wave_mode:5,additivewave:1,wave_a:0,wave_scale:.9,wave_smoothing:.63,wave_mystery:1,modwavealphastart:2,modwavealphaend:2,warpscale:2.853,rot:.006,warp:0,wave_r:.65,wave_g:.65,wave_b:.65,ob_size:.005,mv_x:0,mv_y:48,mv_dx:-.941,mv_dy:.426,mv_l:5,mv_r:.316,mv_g:.078,mv_b:.942,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:1,sides:100,textured:1,rad:.78903,ang:.62832,tex_zoom:1.02009,r:0,g:1,b:1,r2:.7,b2:1,border_a:0},init_eqs_str:"a.vx=0;a.vy=0;",frame_eqs_str:""},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.d=0;a.y3=0;a.y1=0;a.xx=0;a.res=0;a.q12=0;a.x1=0;a.vx3=0;a.q13=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.c_x=0;a.c_y=0;a.q9=0;a.d1=0;a.v=0;a.si1=0;a.vx4=0;a.diff=0;a.x3=0;a.q23=0;a.q24=0;a.d2=0;a.q11=0;a.q10=0;a.xx2=0;a.q4=0;a.yy1=0;a.vy4=0;a.dir=0;a.x4=0;a.r=0;a.x2=0;a.beat=0;a.vol=0;a.vy2=0;a.y2=0;a.size=0;a.q2=0;a.q14=0;a.si2=0;a.vx2=0;a.q3=0;a.yy=0;a.y4=0;a.q7=0;a.vy3=0;a.strength=0;a.xx1=0;a.velocity=0;a.q8=0;a.c_x=.5;a.c_y=.5;",frame_eqs_str:"a.sx=1+.01*mod(8*a.bass,8)*equal(mod(a.time,Math.floor(24-2*a.bass)),0);a.sy=1+.01*mod(8*a.mid,8)*equal(mod(a.time,12+Math.floor(24-2*a.bass)),0);a.q1=a.aspectx;a.q2=a.aspecty;a.rot=0;a.zoom=1;a.warp=0;a.vol=8*a.bass+4*a.mid+2*a.treb;a.vol*=above(a.vol,17);a.monitor=a.vol;a.beat=above(a.vol,a.res);a.diff=(1-a.beat)*a.diff+a.beat*(a.vol-a.res);a.res=a.beat*(a.vol+2*a.diff)+(1-a.beat)*(a.res-div(60*(.04*a.diff+.12),a.fps));a.res=Math.max(0,a.res);a.monitor=a.res;a.r=.00001 3.1)) {\n ret_2 = (ret_2 - 0.4);\n };\n bool tmpvar_4;\n if ((ret_2.x < 0.1)) {\n tmpvar_4 = (abs((n_1 - 3.0)) < 0.5);\n } else {\n tmpvar_4 = bool(0);\n };\n if (tmpvar_4) {\n ret_2 = (ret_2 + 0.4);\n };\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }",comp:" shader_body { \n vec3 ret2_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3 = (texsize.zw * 8.0);\n vec2 tmpvar_4;\n tmpvar_4.x = (((texture (sampler_blur1, \n (uv + (vec2(1.0, 0.0) * tmpvar_3))\n ).xyz * scale1) + bias1) - ((texture (sampler_blur1, \n (uv - (vec2(1.0, 0.0) * tmpvar_3))\n ).xyz * scale1) + bias1)).y;\n tmpvar_4.y = (((texture (sampler_blur1, \n (uv + (vec2(0.0, 1.0) * tmpvar_3))\n ).xyz * scale1) + bias1) - ((texture (sampler_blur1, \n (uv - (vec2(0.0, 1.0) * tmpvar_3))\n ).xyz * scale1) + bias1)).y;\n vec2 tmpvar_5;\n tmpvar_5 = (uv + (tmpvar_4 * 0.55));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_blur3, uv);\n ret_2 = (vec3((0.25 * dot (\n clamp ((2.0 * ((tmpvar_6.xyz * scale3) + bias3)), 0.0, 1.0)\n , vec3(0.32, 0.49, 0.29)))) - (0.8 * dot (\n clamp (((20.0 * (\n (0.6 * ((texture (sampler_blur2, uv).xyz * scale2) + bias2))\n - 0.01)) - 2.0), 0.0, 1.0)\n , vec3(0.32, 0.49, 0.29))));\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_blur1, uv);\n ret_2 = (ret_2 + dot (clamp (\n ((30.0 * ((texture (sampler_main, uv).xyz + \n (((tmpvar_7.xyz * scale1) + bias1) * 0.15)\n ) - 0.01)) - 2.0)\n , 0.0, 1.0), vec3(0.32, 0.49, 0.29)));\n ret_2 = (ret_2 + 1.0);\n vec3 tmpvar_8;\n tmpvar_8 = mix (ret_2, (ret_2 * (\n ((texture (sampler_blur3, tmpvar_5).xyz * scale3) + bias3)\n - \n ((texture (sampler_blur1, tmpvar_5).xyz * scale1) + bias1)\n )), pow (hue_shader, ret_2));\n ret2_1 = (vec3((-0.5 * dot (\n ((texture (sampler_blur3, tmpvar_5).xyz * scale3) + bias3)\n , vec3(0.32, 0.49, 0.29)))) + (0.8 * (\n (texture (sampler_blur1, tmpvar_5).xyz * scale1)\n + bias1)));\n ret2_1 = (ret2_1 - (0.9 * texture (sampler_main, tmpvar_5).xyz));\n ret2_1 = (ret2_1 - 1.5);\n vec3 tmpvar_9;\n tmpvar_9 = mix (ret2_1, (ret2_1 * (\n ((tmpvar_6.xyz * scale3) + bias3)\n - \n ((tmpvar_7.xyz * scale1) + bias1)\n )), pow (hue_shader.zxy, tmpvar_8));\n ret2_1 = tmpvar_9;\n vec3 tmpvar_10;\n tmpvar_10 = abs((tmpvar_8 - tmpvar_9));\n ret_2 = (tmpvar_10 * tmpvar_10);\n ret_2 = (ret_2 * 1.15);\n vec4 tmpvar_11;\n tmpvar_11.w = 1.0;\n tmpvar_11.xyz = ret_2;\n ret = tmpvar_11.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1,decay:.9,echo_zoom:1,wave_brighten:0,wrap:0,wave_a:.001,wave_scale:5.715,wave_smoothing:.9,modwavealphastart:1,modwavealphaend:1,warpanimspeed:.162,warpscale:5.582,zoomexp:.32104,zoom:.9901,warp:.11563,wave_r:0,wave_g:0,wave_b:0,ob_size:0,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:0,mv_b:0,mv_a:0},shapes:[{baseVals:{enabled:1,sides:100,thickoutline:1,textured:1,rad:.05343,tex_zoom:12.77228,g:1,b:1,a:0,r2:1,b2:1,a2:1,border_g:0,border_a:0},init_eqs_str:"a.vx=0;a.vy=0;",frame_eqs_str:""},{baseVals:{enabled:1,sides:100,textured:1,y:.75,rad:.46753,g:1,b:1,r2:1,b2:1,border_a:0},init_eqs_str:"a.w=0;a.q1=0;",frame_eqs_str:"a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);"},{baseVals:{enabled:1,sides:100,textured:1,y:.75,rad:.46753,g:1,b:1,r2:1,b2:1,border_a:0},init_eqs_str:"a.w=0;a.q1=0;",frame_eqs_str:"a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1)+div(2*Math.asin(1),3);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);"},{baseVals:{enabled:1,sides:100,textured:1,y:.75,rad:.46753,g:1,b:1,r2:1,b2:1,border_a:0},init_eqs_str:"a.w=0;a.q1=0;",frame_eqs_str:"a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1)-div(2*Math.asin(1),3);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);"}],waves:[{baseVals:{enabled:1,usedots:1,thick:1,additive:1,scaling:2.44415,smoothing:0},init_eqs_str:"a.d=0;a.n=0;a.y1=0;a.xx=0;a.z=0;a.w=0;a.t5=0;a.t1=0;a.x1=0;a.cl3=0;a.j3=0;a.cl2=0;a.zoom=0;a.j=0;a.cl1=0;a.t8=0;a.v=0;a.t3=0;a.t6=0;a.pi3=0;a.t7=0;a.c2=0;a.j2=0;a.s3=0;a.t=0;a.k=0;a.zz=0;a.c3=0;a.t2=0;a.bb=0;a.s1=0;a.s2=0;a.t4=0;a.yy=0;a.c=0;a.c1=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;",frame_eqs_str:"a.t1=0;a.v=.01;a.j+=.01*a.bass;a.j2+=.01*a.mid_att;a.j3+=.01*a.treb_att;a.t2=a.j;a.t3=a.j2;a.t4=a.j3;a.k=.99*a.k+div(10*a.mid,a.fps);a.t5=-a.k;a.cl1=a.cl1-.0005-.003*a.bass;a.cl1=.00001 0.0))))\n .xy * 0.025))));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = (((tmpvar_5.xyz * tmpvar_5.xyz) * 1.4) - 0.04);\n ret = tmpvar_6.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.56,decay:1,echo_zoom:.362,echo_orient:1,wave_thick:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:1.599,wave_smoothing:0,wave_mystery:-.5,modwavealphastart:2,modwavealphaend:2,warpscale:.107,zoomexp:.1584,fshader:1,warp:.01,wave_r:.51,wave_g:.5,ob_size:0,ob_a:1,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:.5,mv_r:0,mv_g:0,mv_b:0,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.d=0;a.y3=0;a.y1=0;a.xx=0;a.s=0;a.t1=0;a.x1=0;a.vx3=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.v=0;a.vx4=0;a.mm=0;a.tt=0;a.grav=0;a.x3=0;a.xx2=0;a.q4=0;a.a=0;a.yy1=0;a.vy4=0;a.dir=0;a.bounce=0;a.x4=0;a.r=0;a.x2=0;a.mx=0;a.mn=0;a.vy2=0;a.y2=0;a.bb=0;a.q2=0;a.m1=0;a.spring=0;a.vx2=0;a.q3=0;a.resist=0;a.yy=0;a.y4=0;a.vy3=0;a.xx1=0;a.b1=0;a.q8=0;",frame_eqs_str:"a.ib_r=.3*Math.sin(5*a.time)+.7;a.ib_g=.3*Math.sin(4*a.time)+.3;a.ib_b=.5*Math.sin(4*div(a.time,3))+.5;a.xx1=.9*a.xx1+.01*a.bass;a.xx2=.9*a.xx2+.01*a.treb;a.yy1=.94*a.yy1+.0075*(a.treb+a.bass);a.x1=.5+2*(a.xx1-a.xx2);a.y1=.4+a.yy1;a.x1=Math.max(0,Math.min(1,a.x1));a.y1=Math.max(0,Math.min(1,a.y1));a.spring=10;a.grav=.5;a.resist=1;a.bounce=.75;a.dt=.0002*div(60,a.fps);a.vx2=a.vx2*(1-a.resist*a.dt)+a.dt*(a.x1+a.x3-2*a.x2)*a.spring;a.vy2=a.vy2*(1-a.resist*a.dt)+a.dt*((a.y1+a.y3-\n2*a.y2)*a.spring-a.grav);a.vx3=a.vx3*(1-a.resist*a.dt)+a.dt*(a.x2+a.x4-2*a.x3)*a.spring;a.vy3=a.vy3*(1-a.resist*a.dt)+a.dt*((a.y2+a.y4-2*a.y3)*a.spring-a.grav);a.vx4=a.vx4*(1-a.resist*a.dt)+a.dt*(a.x3-a.x4)*a.spring;a.vy4=a.vy4*(1-a.resist*a.dt)+a.dt*((a.y3-a.y4)*a.spring-a.grav);a.x2+=a.vx2;a.y2+=a.vy2;a.x3+=a.vx3;a.y3+=a.vy3;a.x4+=a.vx4;a.y4+=a.vy4;a.vx2=.00001b;b++)a.gmegabuf[Math.floor(a.i)]=0,a.i+=1;a.count=50;a.attributes=32;a.nliststart=24;a.minradius=.004;a.maxradius=.04;a.v=0;for(b=a.index=0;b 1.0)\n ) * (\n (tmpvar_15 * -2.0)\n + 1.570796)));\n tmpvar_13 = (tmpvar_15 * sign((tmpvar_11.x / tmpvar_11.y)));\n if ((abs(tmpvar_11.y) > (1e-08 * abs(tmpvar_11.x)))) {\n if ((tmpvar_11.y < 0.0)) {\n if ((tmpvar_11.x >= 0.0)) {\n tmpvar_13 += 3.141593;\n } else {\n tmpvar_13 = (tmpvar_13 - 3.141593);\n };\n };\n } else {\n tmpvar_13 = (sign(tmpvar_11.x) * 1.570796);\n };\n vec2 tmpvar_16;\n tmpvar_16.x = (tmpvar_13 * 0.1591549);\n tmpvar_16.y = tmpvar_12;\n vec2 tmpvar_17;\n tmpvar_17.x = ((tmpvar_16.x * 2.0) + q11);\n tmpvar_17.y = ((0.3 * log(tmpvar_12)) + q12);\n vec2 tmpvar_18;\n tmpvar_18 = (0.5 + (0.5 - abs(\n ((fract((tmpvar_17 * 0.5)) * 2.0) - 1.0)\n )));\n vec2 tmpvar_19;\n tmpvar_19 = (texsize.zw * 3.0);\n vec3 tmpvar_20;\n tmpvar_20 = ((2.0 * (\n (texture (sampler_blur1, (tmpvar_18 + (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (tmpvar_18 - (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec3 tmpvar_21;\n tmpvar_21 = ((2.0 * (\n (texture (sampler_blur1, (tmpvar_18 + (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (tmpvar_18 - (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec2 tmpvar_22;\n tmpvar_22.x = tmpvar_20.x;\n tmpvar_22.y = tmpvar_21.x;\n mirror_uv_3 = (tmpvar_18 + ((tmpvar_22 * texsize.zw) * 4.0));\n ret_4 = ((mix (ret_4, vec3(1.0, 1.0, 1.0), \n ((((texture (sampler_blur1, mirror_uv_3).xyz * scale1) + bias1).x * (1.0 - (\n (texture (sampler_blur2, mirror_uv_3).xyz * scale2)\n + bias2).x)) * (pow (hue_shader, vec3(4.0, 4.0, 4.0)) * 1.4))\n ) * texture (sampler_main, mirror_uv_3).xxx) + ((\n (1.0 - texture (sampler_main, mirror_uv_3).x)\n * \n ((texture (sampler_blur1, mirror_uv_3).xyz * scale1) + bias1)\n .x) * vec3(3.0, 3.0, 3.0)));\n vec2 tmpvar_23;\n tmpvar_23.x = tmpvar_20.x;\n tmpvar_23.y = tmpvar_21.x;\n mirror_uv_3 = (mirror_uv_3 - ((tmpvar_23 * texsize.zw) * 24.0));\n dx_2 = ((2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 + (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 - (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n dy_1 = ((2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 + (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 - (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec2 tmpvar_24;\n tmpvar_24.x = -(dx_2.y);\n tmpvar_24.y = dy_1.y;\n vec2 tmpvar_25;\n tmpvar_25 = (tmpvar_24 * 0.25);\n vec3 tmpvar_26;\n tmpvar_26 = mix (ret_4, vec3(1.0, 1.0, 1.0), (mix (vec3(1.0, 0.7, 0.2), vec3(0.15, 0.0, 0.5), vec3(\n ((((\n ((mirror_uv_3.x * 0.8) - mirror_uv_3.y)\n + 0.75) + tmpvar_25.x) + tmpvar_25.y) - 0.1)\n )) * texture (sampler_main, mirror_uv_3).y));\n vec2 tmpvar_27;\n vec2 tmpvar_28;\n tmpvar_28 = ((0.5 + (\n (uv - 0.5)\n * aspect.wz)) - vec2(0.5, 0.5));\n vec2 tmpvar_29;\n tmpvar_29.x = ((q4 * tmpvar_28.x) - (q3 * tmpvar_28.y));\n tmpvar_29.y = ((q3 * tmpvar_28.x) + (q4 * tmpvar_28.y));\n tmpvar_27 = (vec2(0.5, 0.5) + tmpvar_29);\n mirror_uv_3 = tmpvar_27.yx;\n vec2 tmpvar_30;\n tmpvar_30 = (vec2(1.0, 0.0) * texsize.zw);\n dx_2 = ((2.0 * texture (sampler_main, (tmpvar_27.yx + tmpvar_30)).xyz) - (2.0 * texture (sampler_main, (tmpvar_27.yx - tmpvar_30)).xyz));\n vec2 tmpvar_31;\n tmpvar_31 = (vec2(0.0, 1.0) * texsize.zw);\n dy_1 = ((2.0 * texture (sampler_main, (tmpvar_27.yx + tmpvar_31)).xyz) - (2.0 * texture (sampler_main, (tmpvar_27.yx - tmpvar_31)).xyz));\n vec2 tmpvar_32;\n tmpvar_32.x = dx_2.z;\n tmpvar_32.y = dy_1.z;\n vec3 tmpvar_33;\n tmpvar_33 = mix (tmpvar_26, vec3(0.9, 0.9, 1.0), vec3((1.0 - texture (sampler_main, (tmpvar_27.yx - tmpvar_32)).z)));\n ret_4 = tmpvar_33;\n vec4 tmpvar_34;\n tmpvar_34.w = 1.0;\n tmpvar_34.xyz = tmpvar_33;\n ret = tmpvar_34.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:.995,echo_zoom:1.007,echo_orient:3,additivewave:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,wave_a:1.413,wave_scale:.418,wave_smoothing:0,wave_mystery:-.66,modwavealphastart:2,modwavealphaend:2,warpanimspeed:.626,warpscale:8.642,zoomexp:7.10084,zoom:.99951,warp:.09014,wave_r:0,wave_g:0,wave_x:.24,wave_y:.44,ob_size:0,ob_a:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:0,mv_a:0},shapes:[{baseVals:{enabled:1,sides:48,additive:1,rad:.0277,ang:6.03186,tex_ang:6.03186,tex_zoom:.6839,r:0,g:1,a2:1,border_r:0,border_g:0,border_b:0,border_a:0},init_eqs_str:"a.q3=0;a.q4=0;a.q5=0;a.q2=0;a.q1=0;",frame_eqs_str:"a.x=a.q3;a.y=a.q4;a.rad=a.q5;a.x=.5+div(a.x-.5,a.q2);a.y=.5+div(a.y-.5,a.q1);"},{baseVals:{enabled:1,sides:48,additive:1,rad:.0277,ang:6.03186,tex_ang:6.03186,tex_zoom:.6839,r:0,b:1,g2:0,b2:1,a2:1,border_r:0,border_g:0,border_b:0,border_a:0},init_eqs_str:"a.q6=0;a.q7=0;a.q8=0;a.q2=0;a.q1=0;",frame_eqs_str:"a.x=a.q6;a.y=a.q7;a.rad=a.q8;a.x=.5+div(a.x-.5,a.q2);a.y=.5+div(a.y-.5,a.q1);"},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,thick:1,additive:1,scaling:2.0231,smoothing:0,g:0,b:0},init_eqs_str:"a.d=0;a.tt2=0;a.res=0;a.tt1=0;a.diff=0;a.tt3=0;a.beat=0;a.vol=0;a.m=0;a.monitor=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;",frame_eqs_str:"a.vol=8*a.bass+5*a.mid+3*a.treb;a.m=.97*a.m+.08*a.vol;a.monitor=a.vol;a.beat=above(a.vol,a.res)*above(a.vol,a.m)*above(a.vol,16);a.diff=(1-a.beat)*a.diff+a.beat*(a.vol-a.res);a.res=a.beat*(a.vol+.04*a.m)+(1-a.beat)*(a.res-div(60*(.1+.02*a.diff),a.fps));a.res=Math.max(0,a.res);a.a=a.beat;",point_eqs_str:"a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.5+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.y3=0;a.y1=0;a.xx=0;a.q12=0;a.w2=0;a.ref_ang=0;a.q18=0;a.x1=0;a.vx3=0;a.q13=0;a.q15=0;a.q6=0;a.q1=0;a.q5=0;a.q9=0;a.d1=0;a.si1=0;a.vx1=0;a.vx4=0;a.x3=0;a.d2=0;a.q11=0;a.q10=0;a.q4=0;a.vy4=0;a.dir=0;a.bounce=0;a.q16=0;a.x4=0;a.w1=0;a.r=0;a.x2=0;a.q17=0;a.vy2=0;a.y2=0;a.vy1=0;a.q2=0;a.m1=0;a.q14=0;a.si2=0;a.v1=0;a.vx2=0;a.q3=0;a.yy=0;a.y4=0;a.q7=0;a.vy3=0;a.v2=0;a.b1=0;a.q8=0;a.x1=.5;a.x2=.51;a.y2=.9;a.y1=.7;a.x3=.8;a.y3=.5;a.x4=.2;a.y4=.5;a.ax1=0;a.ay1=0;a.ax2=0;a.ay2=0;a.ax3=\n0;a.ay3=0;a.vx1=0;a.vx2=0;",frame_eqs_str:"a.zoom=1.002;a.warp=.2;a.wave_a=0;a.r=.04+.008*Math.max(a.bass_att,a.treb_att);a.bounce=below(a.y1,a.r);a.y1+=a.vy1;a.vy1=.00001 1.0)\n ) * (\n (tmpvar_7 * -2.0)\n + 1.570796)));\n tmpvar_5 = (tmpvar_7 * sign((tmpvar_4.x / tmpvar_4.y)));\n if ((abs(tmpvar_4.y) > (1e-08 * abs(tmpvar_4.x)))) {\n if ((tmpvar_4.y < 0.0)) {\n if ((tmpvar_4.x >= 0.0)) {\n tmpvar_5 += 3.141593;\n } else {\n tmpvar_5 = (tmpvar_5 - 3.141593);\n };\n };\n } else {\n tmpvar_5 = (sign(tmpvar_4.x) * 1.570796);\n };\n vec2 tmpvar_8;\n tmpvar_8.x = ((tmpvar_5 * q11) - tmpvar_3);\n tmpvar_8.y = (((q13 * \n log(sqrt(dot (tmpvar_4, tmpvar_4)))\n ) + (tmpvar_5 * q11)) + tmpvar_3);\n uv_1 = (0.5 + (0.5 - abs(\n ((fract((tmpvar_8 * 0.5)) * 2.0) - 1.0)\n )));\n vec4 tmpvar_9;\n tmpvar_9 = texture (sampler_main, uv_1);\n ret_2 = (vec3(dot (tmpvar_9.xyz, vec3(0.32, 0.49, 0.29))) * mix (vec3(1.0, 1.0, 1.0), vec3(0.2, 0.5, 1.0), tmpvar_9.xxx));\n ret_2 = (ret_2 * 2.0);\n vec4 tmpvar_10;\n tmpvar_10.w = 1.0;\n tmpvar_10.xyz = ret_2;\n ret = tmpvar_10.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:1,echo_zoom:1,echo_alpha:.5,wave_thick:1,wave_brighten:0,wrap:0,wave_a:.004,wave_scale:.242,wave_smoothing:0,wave_mystery:-.44,modwavealphastart:1,modwavealphaend:1,warpanimspeed:.88,warpscale:9.181,zoomexp:.65309,zoom:.87866,warp:.04914,wave_y:.04,ob_size:.05,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:0,mv_b:0,mv_a:0},shapes:[{baseVals:{enabled:1,sides:100,thickoutline:1,y:.04,rad:.01,tex_ang:.12566,tex_zoom:1.51878,r:0,a:0,g2:0,b2:.01,border_a:0},init_eqs_str:"",frame_eqs_str:""},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,thick:1,additive:1,scaling:2.0231,smoothing:0,r:0,b:0},init_eqs_str:"a.tt3=0;a.tt2=0;a.tt1=0;a.d=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;",frame_eqs_str:"a.r=1;a.g=0;a.b=1;",point_eqs_str:"a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.6+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.c_inv_i=0;a.translation_x=0;a.q12=0;a.a_i=0;a.a_r=0;a.q18=0;a.q13=0;a.scale=0;a.q15=0;a.c_inv_r=0;a.angle=0;a.q11=0;a.bcad_r=0;a.b_r=0;a.q16=0;a.bcad_i=0;a.q17=0;a.q14=0;a.translation_y=0;a.translation_v=0;a.b_i=0;a.translation_u=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;",frame_eqs_str:"a.zoom=1;a.scale=1;a.angle=.1*a.time;a.translation_x=0;a.translation_y=.12;a.a_r=Math.cos(a.angle)*a.scale;a.a_i=Math.sin(a.angle)*a.scale;a.b_r=a.translation_x;a.b_i=a.translation_y;a.scale=1.6;a.angle=0;a.translation_u=0;a.translation_v=0;a.q15=Math.cos(a.angle)*a.scale;a.q16=Math.sin(a.angle)*a.scale;a.q17=a.translation_u;a.q18=a.translation_v;a.c_inv_r=div(a.q15,a.q15*a.q15+a.q16*a.q16);a.c_inv_i=div(a.q16,a.q15*a.q15+a.q16*a.q16);a.q11=a.a_r*a.c_inv_r-a.a_i*a.c_inv_i;a.q12=\na.a_r*a.c_inv_i-a.a_i*a.c_inv_r;a.bcad_r=a.b_r*a.q15-a.b_i*a.q16-(a.a_r*a.q17-a.a_i*a.q18);a.bcad_i=a.b_r*a.q16-a.b_i*a.q15-(a.a_r*a.q18-a.a_i*a.q17);a.q13=a.bcad_r*a.c_inv_r-a.bcad_i*a.c_inv_i;a.q14=a.bcad_r*a.c_inv_i-a.bcad_i*a.c_inv_r;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n float conway_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = (((\n ((texture (sampler_blur2, (uv + vec2(0.02, 0.0))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.02, 0.0))).xyz * scale2) + bias2)\n ).y * 1280.0) * texsize.z);\n tmpvar_3.y = (((\n ((texture (sampler_blur2, (uv + vec2(0.0, 0.02))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.0, 0.02))).xyz * scale2) + bias2)\n ).y * 1024.0) * texsize.w);\n ret_2.y = texture (sampler_pc_main, (uv - (tmpvar_3 * 0.004))).y;\n ret_2.y = (ret_2.y + ((\n ((ret_2.y - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).y) - 0.1)\n * 0.1) + 0.02));\n vec2 tmpvar_4;\n tmpvar_4 = (vec2(0.0, 1.0) * texsize.zw);\n ret_2.z = (texture (sampler_fc_main, (uv - tmpvar_4)).z - 0.004);\n conway_1 = (texture (sampler_pw_main, (uv_orig - texsize.zw)).x + texture (sampler_pw_main, (uv_orig + (vec2(0.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + tmpvar_4)).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + texsize.zw)).x);\n conway_1 = (conway_1 - fract(conway_1));\n float tmpvar_5;\n tmpvar_5 = clamp (texture (sampler_pc_main, uv_orig).x, 0.0, 1.0);\n ret_2.x = (clamp ((1.0 - \n abs((conway_1 - 3.0))\n ), 0.0, 1.0) * (1.0 - tmpvar_5));\n ret_2.x = (ret_2.x + (clamp (\n max ((1.0 - abs((conway_1 - 2.0))), (1.0 - abs((conway_1 - 3.0))))\n , 0.0, 1.0) * tmpvar_5));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = ret_2;\n ret = tmpvar_6.xyz;\n }",comp:" shader_body { \n vec2 moebius_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = q11;\n tmpvar_3.y = q12;\n vec2 tmpvar_4;\n tmpvar_4.x = q17;\n tmpvar_4.y = q18;\n vec2 tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (uv - 0.5);\n tmpvar_5 = (tmpvar_6 * aspect.xy);\n vec2 tmpvar_7;\n tmpvar_7.x = ((tmpvar_5.x * q15) - (tmpvar_5.y * q16));\n tmpvar_7.y = ((tmpvar_5.x * q16) - (tmpvar_5.y * q15));\n vec2 tmpvar_8;\n tmpvar_8 = (tmpvar_7 + tmpvar_4);\n vec2 tmpvar_9;\n tmpvar_9.x = ((q13 * tmpvar_8.x) + (q14 * tmpvar_8.y));\n tmpvar_9.y = ((q14 * tmpvar_8.x) - (q13 * tmpvar_8.y));\n moebius_1 = (((tmpvar_9 / \n ((tmpvar_8.x * tmpvar_8.x) + (tmpvar_8.y * tmpvar_8.y))\n ) + tmpvar_3) * 0.5);\n float tmpvar_10;\n tmpvar_10 = sqrt(dot (moebius_1, moebius_1));\n moebius_1 = (0.5 + ((\n (1.0 - abs(((\n fract((moebius_1 * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.95));\n vec2 tmpvar_11;\n tmpvar_11 = (0.5 + (tmpvar_6 * 0.2));\n ret_2 = (texture (sampler_main, tmpvar_11).z * vec3(0.4, 0.0, 0.7));\n ret_2 = (mix (ret_2, vec3(0.0, 1.0, 1.0), vec3(clamp (texture (sampler_fc_main, moebius_1).y, 0.0, 1.0))) * (1.4 - pow (\n (tmpvar_10 * 0.8)\n , 0.3)));\n vec3 tmpvar_12;\n tmpvar_12 = mix (mix (mix (ret_2, vec3(4.0, 1.0, 0.0), vec3(\n ((clamp ((texture (sampler_fc_main, tmpvar_11).y - texture (sampler_pc_main, tmpvar_11).y), 0.0, 1.0) * 4.0) * (tmpvar_10 * tmpvar_10))\n )), vec3(-4.0, -4.0, -4.0), texture (sampler_main, tmpvar_11).xxx), vec3(2.0, 2.0, 2.0), vec3((texture (sampler_pc_main, tmpvar_11).x * 0.75)));\n ret_2 = tmpvar_12;\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = tmpvar_12;\n ret = tmpvar_13.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:1,gammaadj:1.28,decay:.8,echo_zoom:1,echo_orient:3,wave_mode:7,additivewave:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,brighten:1,wave_a:.001,wave_scale:1.286,wave_smoothing:.63,modwavealphastart:.71,modwavealphaend:1.3,warpanimspeed:.01,warpscale:100,zoomexp:.92178,zoom:.9901,warp:.01,wave_r:.65,wave_g:.65,wave_b:.65,ob_size:.005,ob_g:1,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:0,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.d=0;a.y3=0;a.y1=0;a.xx=0;a.s=0;a.x1=0;a.vx3=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.v=0;a.vx4=0;a.grav=0;a.x3=0;a.q11=0;a.q10=0;a.xx2=0;a.q4=0;a.a=0;a.yy1=0;a.vy4=0;a.dir=0;a.bounce=0;a.x4=0;a.r=0;a.x2=0;a.vy2=0;a.y2=0;a.q2=0;a.spring=0;a.vx2=0;a.q3=0;a.resist=0;a.yy=0;a.y4=0;a.vy3=0;a.xx1=0;a.v2=0;a.q8=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;",frame_eqs_str:"a.xx1=.9*a.xx1+.01*a.bass;a.xx2=.9*a.xx2+.01*a.treb;a.yy1=.94*a.yy1+.0075*(a.treb+a.bass);a.x1=.5+2*(a.xx1-a.xx2);a.y1=.4+a.yy1;a.x1=Math.max(0,Math.min(1,a.x1));a.y1=Math.max(0,Math.min(1,a.y1));a.spring=10;a.grav=.5;a.resist=1;a.bounce=.75;a.dt=.0001*div(60,a.fps);a.vx2=a.vx2*(1-a.resist*a.dt)+a.dt*(a.x1+a.x3-2*a.x2)*a.spring;a.vy2=a.vy2*(1-a.resist*a.dt)+a.dt*((a.y1+a.y3-2*a.y2)*a.spring-a.grav);a.vx3=a.vx3*(1-a.resist*a.dt)+a.dt*(a.x2+a.x4-2*a.x3)*a.spring;a.vy3=a.vy3*(1-\na.resist*a.dt)+a.dt*((a.y2+a.y4-2*a.y3)*a.spring-a.grav);a.vx4=a.vx4*(1-a.resist*a.dt)+a.dt*(a.x3-a.x4)*a.spring;a.vy4=a.vy4*(1-a.resist*a.dt)+a.dt*((a.y3-a.y4)*a.spring-a.grav);a.x2+=a.vx2;a.y2+=a.vy2;a.x3+=a.vx3;a.y3+=a.vy3;a.x4+=a.vx4;a.y4+=a.vy4;a.vx2=.00001 1.0)\n ) * (\n (tmpvar_4 * -2.0)\n + 1.570796)));\n tmpvar_2 = (tmpvar_4 * sign((tmpvar_1.x / tmpvar_1.y)));\n if ((abs(tmpvar_1.y) > (1e-08 * abs(tmpvar_1.x)))) {\n if ((tmpvar_1.y < 0.0)) {\n if ((tmpvar_1.x >= 0.0)) {\n tmpvar_2 += 3.141593;\n } else {\n tmpvar_2 = (tmpvar_2 - 3.141593);\n };\n };\n } else {\n tmpvar_2 = (sign(tmpvar_1.x) * 1.570796);\n };\n vec2 tmpvar_5;\n tmpvar_5.x = (tmpvar_2 * q11);\n tmpvar_5.y = (((0.5 * \n log(sqrt(dot (tmpvar_1, tmpvar_1)))\n ) - (tmpvar_2 * q11)) + q12);\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = pow (texture (sampler_main, (0.5 + (\n (0.5 - abs(((\n fract((tmpvar_5 * 0.5))\n * 2.0) - 1.0)))\n * vec2(0.96, 1.0)))).xyz, vec3(0.618034, 0.618034, 0.618034));\n ret = tmpvar_6.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1,decay:1,echo_zoom:1,echo_alpha:.5,wave_thick:1,wave_brighten:0,wave_a:.004,wave_scale:.01,wave_smoothing:0,wave_mystery:-.44,modwavealphastart:1,modwavealphaend:1,warpanimspeed:.01,warpscale:100,zoomexp:.24298,zoom:.9901,warp:.01,wave_y:.04,ob_size:0,ob_g:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,mv_x:64,mv_y:48,mv_l:0,mv_b:0,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:1,sides:100,thickoutline:1,rad:.01,tex_ang:.12566,tex_zoom:1.51878,r:.05,a:.1,g2:0,border_a:0},init_eqs_str:"",frame_eqs_str:""},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;",frame_eqs_str:"a.zoom=1;a.warp=0;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec2 my_uv_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3 = (0.02 * aspect.zw);\n vec3 tmpvar_4;\n tmpvar_4 = (((texture (sampler_blur2, \n ((uv + (vec2(1.0, 0.0) * tmpvar_3)) - floor((uv + (vec2(1.0, 0.0) * tmpvar_3))))\n ).xyz * scale2) + bias2) - ((texture (sampler_blur2, \n ((uv - (vec2(1.0, 0.0) * tmpvar_3)) - floor((uv - (vec2(1.0, 0.0) * tmpvar_3))))\n ).xyz * scale2) + bias2));\n vec3 tmpvar_5;\n tmpvar_5 = (((texture (sampler_blur2, \n ((uv + (vec2(0.0, 1.0) * tmpvar_3)) - floor((uv + (vec2(0.0, 1.0) * tmpvar_3))))\n ).xyz * scale2) + bias2) - ((texture (sampler_blur2, \n ((uv - (vec2(0.0, 1.0) * tmpvar_3)) - floor((uv - (vec2(0.0, 1.0) * tmpvar_3))))\n ).xyz * scale2) + bias2));\n vec3 tmpvar_6;\n tmpvar_6 = ((texture (sampler_blur1, uv).xyz * scale1) + bias1);\n vec2 tmpvar_7;\n tmpvar_7.x = tmpvar_4.y;\n tmpvar_7.y = tmpvar_5.y;\n vec2 tmpvar_8;\n tmpvar_8.x = tmpvar_5.x;\n tmpvar_8.y = -(tmpvar_4.x);\n vec2 tmpvar_9;\n tmpvar_9 = ((uv - (tmpvar_7 * vec2(0.01, 0.01))) - (tmpvar_8 * -0.02));\n ret_2.y = texture (sampler_fc_main, (tmpvar_9 - floor(tmpvar_9))).y;\n ret_2.y = (ret_2.y + ((\n (ret_2.y - tmpvar_6.y)\n * 0.02) + 0.005));\n vec2 tmpvar_10;\n tmpvar_10.x = tmpvar_4.x;\n tmpvar_10.y = tmpvar_5.x;\n vec2 tmpvar_11;\n tmpvar_11.x = tmpvar_5.z;\n tmpvar_11.y = -(tmpvar_4.z);\n my_uv_1 = ((uv - (tmpvar_10 * vec2(0.01, 0.01))) - (tmpvar_11 * -0.02));\n ret_2.x = texture (sampler_fc_main, (my_uv_1 - floor(my_uv_1))).x;\n ret_2.x = (ret_2.x + ((\n (ret_2.x - tmpvar_6.x)\n * 0.02) + 0.005));\n vec2 tmpvar_12;\n tmpvar_12.x = tmpvar_4.z;\n tmpvar_12.y = tmpvar_5.z;\n vec2 tmpvar_13;\n tmpvar_13.x = tmpvar_5.y;\n tmpvar_13.y = -(tmpvar_4.y);\n my_uv_1 = ((uv - (tmpvar_12 * vec2(0.01, 0.01))) - (tmpvar_13 * -0.02));\n ret_2.z = texture (sampler_fc_main, (my_uv_1 - floor(my_uv_1))).z;\n ret_2.z = (ret_2.z + ((\n (ret_2.z - tmpvar_6.z)\n * 0.02) + 0.005));\n vec4 tmpvar_14;\n tmpvar_14.w = 1.0;\n tmpvar_14.xyz = ret_2;\n ret = tmpvar_14.xyz;\n }",comp:" shader_body { \n vec2 uv2_1;\n vec3 ret_2;\n uv2_1 = (uv + (vec2(1.0, 0.0) * texsize.zw));\n float tmpvar_3;\n tmpvar_3 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(-1.0, 0.0) * texsize.zw));\n float tmpvar_4;\n tmpvar_4 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, 1.0) * texsize.zw));\n float tmpvar_5;\n tmpvar_5 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, -1.0) * texsize.zw));\n vec3 tmpvar_6;\n tmpvar_6.z = 0.14;\n tmpvar_6.x = (tmpvar_3 - tmpvar_4);\n tmpvar_6.y = (tmpvar_5 - ((\n (texture (sampler_main, uv2_1).xyz + (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4))\n + \n (((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2) * 0.15)\n ) + (\n ((texture (sampler_blur3, uv2_1).xyz * scale3) + bias3)\n * 0.1)).x);\n ret_2 = (0.5 + (0.5 * normalize(tmpvar_6)));\n vec2 x_7;\n x_7 = (ret_2.xy - 0.5);\n ret_2 = (ret_2 * clamp ((\n sqrt(dot (x_7, x_7))\n * 5.0), 0.0, 1.0));\n ret_2 = ret_2.xxy;\n ret_2 = (ret_2 + 1.15);\n ret_2 = (ret_2 * mix (ret_2, (ret_2 * \n (((texture (sampler_blur3, uv).xyz * scale3) + bias3) - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n ), pow (hue_shader.zxy, ret_2)));\n ret_2 = (ret_2 * ret_2);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = ret_2;\n ret = tmpvar_8.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:1,echo_zoom:1,echo_alpha:.5,wave_thick:1,wave_brighten:0,wrap:0,wave_a:.004,wave_scale:.242,wave_smoothing:0,wave_mystery:-.44,modwavealphastart:1,modwavealphaend:1,warpanimspeed:.397,warpscale:15.099,zoomexp:.65309,zoom:.87866,warp:.04027,wave_y:.04,ob_size:0,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:0,mv_b:0,mv_a:0},shapes:[{baseVals:{enabled:1,sides:100,thickoutline:1,y:.04,rad:.01,tex_ang:.12566,tex_zoom:1.51878,r:0,a:0,g2:0,b2:.01,border_a:0},init_eqs_str:"",frame_eqs_str:""},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,thick:1,additive:1,scaling:2.0231,smoothing:0,r:0,b:0},init_eqs_str:"a.tt3=0;a.tt2=0;a.tt1=0;a.d=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;",frame_eqs_str:"a.r=1;a.g=0;a.b=1;",point_eqs_str:"a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.6+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.c_inv_i=0;a.translation_x=0;a.q12=0;a.a_i=0;a.a_r=0;a.q18=0;a.q13=0;a.scale=0;a.q15=0;a.c_inv_r=0;a.angle=0;a.q11=0;a.bcad_r=0;a.b_r=0;a.q16=0;a.bcad_i=0;a.q17=0;a.q14=0;a.translation_y=0;a.translation_v=0;a.b_i=0;a.translation_u=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;",frame_eqs_str:"a.zoom=.998;a.scale=1;a.angle=.02*a.time;a.translation_x=0;a.translation_y=.12;a.a_r=Math.cos(a.angle)*a.scale;a.a_i=Math.sin(a.angle)*a.scale;a.b_r=a.translation_x;a.b_i=a.translation_y;a.scale=1;a.angle=0*Math.sin(.1337*a.time);a.translation_u=0;a.translation_v=-.2;a.q15=Math.cos(a.angle)*a.scale;a.q16=Math.sin(a.angle)*a.scale;a.q17=a.translation_u;a.q18=a.translation_v;a.c_inv_r=div(a.q15,a.q15*a.q15+a.q16*a.q16);a.c_inv_i=div(a.q16,a.q15*a.q15+a.q16*a.q16);a.q11=a.a_r*\na.c_inv_r-a.a_i*a.c_inv_i;a.q12=a.a_r*a.c_inv_i-a.a_i*a.c_inv_r;a.bcad_r=a.b_r*a.q15-a.b_i*a.q16-(a.a_r*a.q17-a.a_i*a.q18);a.bcad_i=a.b_r*a.q16-a.b_i*a.q15-(a.a_r*a.q18-a.a_i*a.q17);a.q13=a.bcad_r*a.c_inv_r-a.bcad_i*a.c_inv_i;a.q14=a.bcad_r*a.c_inv_i-a.bcad_i*a.c_inv_r;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n float conway_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = (((\n ((texture (sampler_blur2, (uv + vec2(0.02, 0.0))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.02, 0.0))).xyz * scale2) + bias2)\n ).y * 1280.0) * texsize.z);\n tmpvar_3.y = (((\n ((texture (sampler_blur2, (uv + vec2(0.0, 0.02))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.0, 0.02))).xyz * scale2) + bias2)\n ).y * 1024.0) * texsize.w);\n ret_2.y = texture (sampler_pc_main, (uv - (tmpvar_3 * 0.004))).y;\n ret_2.y = (ret_2.y + ((\n ((ret_2.y - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).y) - 0.1)\n * 0.1) + 0.02));\n ret_2.z = (texture (sampler_fc_main, (0.5 + (\n (uv - 0.5)\n * 0.992))).z - 0.004);\n conway_1 = (texture (sampler_pw_main, (uv_orig - texsize.zw)).x + texture (sampler_pw_main, (uv_orig + (vec2(0.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(0.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + texsize.zw)).x);\n conway_1 = (conway_1 - fract(conway_1));\n float tmpvar_4;\n tmpvar_4 = clamp (texture (sampler_pc_main, uv_orig).x, 0.0, 1.0);\n ret_2.x = (clamp ((1.0 - \n abs((conway_1 - 3.0))\n ), 0.0, 1.0) * (1.0 - tmpvar_4));\n ret_2.x = (ret_2.x + (clamp (\n max ((1.0 - abs((conway_1 - 2.0))), (1.0 - abs((conway_1 - 3.0))))\n , 0.0, 1.0) * tmpvar_4));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }",comp:" shader_body { \n vec2 moebius_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = q11;\n tmpvar_3.y = q12;\n vec2 tmpvar_4;\n tmpvar_4.x = q17;\n tmpvar_4.y = q18;\n vec2 tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (uv - 0.5);\n tmpvar_5 = (tmpvar_6 * aspect.xy);\n vec2 tmpvar_7;\n tmpvar_7.x = ((tmpvar_5.x * q15) - (tmpvar_5.y * q16));\n tmpvar_7.y = ((tmpvar_5.x * q16) - (tmpvar_5.y * q15));\n vec2 tmpvar_8;\n tmpvar_8 = (tmpvar_7 + tmpvar_4);\n vec2 tmpvar_9;\n tmpvar_9.x = ((q13 * tmpvar_8.x) + (q14 * tmpvar_8.y));\n tmpvar_9.y = ((q14 * tmpvar_8.x) - (q13 * tmpvar_8.y));\n moebius_1 = (((tmpvar_9 / \n ((tmpvar_8.x * tmpvar_8.x) + (tmpvar_8.y * tmpvar_8.y))\n ) + tmpvar_3) * 0.5);\n float tmpvar_10;\n tmpvar_10 = sqrt(dot (moebius_1, moebius_1));\n moebius_1 = (0.5 + ((\n (1.0 - abs(((\n fract((moebius_1 * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.99));\n vec3 tmpvar_11;\n tmpvar_11 = mix (mix (mix (\n mix (mix ((mix (ret_2, vec3(0.2, 0.6, 1.0), vec3(\n (texture (sampler_pc_main, moebius_1).y * 2.0)\n )) * (vec3(1.0, 1.0, 1.0) - vec3(\n ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.5))\n ).xyz * scale1) + bias1).y * 2.0) * tmpvar_10)\n ))), vec3(1.0, 1.0, 1.0), texture (sampler_pc_main, moebius_1).xxx), vec3(4.0, 1.0, 0.0), vec3(clamp (((texture (sampler_pc_main, \n (0.5 + (tmpvar_6 * 0.2))\n ).y * 2.0) * (\n (tmpvar_10 * tmpvar_10)\n * tmpvar_10)), 0.0, 1.0)))\n , vec3(0.1, 0.0, 0.0), vec3(\n clamp ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.2))\n ).xyz * scale1) + bias1).x * 12.0), 0.0, 1.0)\n )), (vec3(0.5, 0.8, 1.0) * texture (sampler_pc_main, uv).z), vec3((\n clamp ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.2))\n ).xyz * scale1) + bias1).x * 4.0), 0.0, 1.0)\n * 1.4))), vec3(1.0, 1.0, 1.0), texture (sampler_pc_main, (0.5 + (tmpvar_6 * 0.2))).xxx);\n ret_2 = tmpvar_11;\n vec4 tmpvar_12;\n tmpvar_12.w = 1.0;\n tmpvar_12.xyz = tmpvar_11;\n ret = tmpvar_12.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.56,decay:1,echo_zoom:.362,echo_orient:1,wave_mode:7,additivewave:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:1.286,wave_smoothing:.63,modwavealphastart:.71,modwavealphaend:1.3,warpscale:1.331,fshader:1,zoom:1.004,warp:.19788,sx:.99967,sy:.9999,wave_g:.65,wave_b:.65,ob_size:0,ob_a:1,mv_x:64,mv_y:48,mv_l:0,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,thick:1,r:0,g:.3,b:.75},init_eqs_str:"a.ma=0;a.mx=0;a.my=0;",frame_eqs_str:"",point_eqs_str:"a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.tstart=\na.time;a.bd_recsz=8;a.bd_oct=4;a.bd_spo=30;a.bd_finc=pow(2,div(1,a.bd_spo));a.bd_nres=a.bd_oct*a.bd_spo;a.bd_minbpm=20;a.bd_maxbpm=pow(2,a.bd_oct)*a.bd_minbpm;a.bd_dat0=1E5;a.bd_tab0=a.bd_dat0+a.bd_nres*a.bd_recsz*3;a.reg00=a.bd_minbpm;a.reg01=a.bd_maxbpm;a.reg02=a.bd_recsz;a.reg03=a.bd_nres;a.reg05=a.bd_finc;a.reg06=a.bd_dat0;a.reg07=a.bd_mp0;a.time_st=0;a.timediff=1;",frame_eqs_str:"a.dt=Math.min(div(1,a.fps),.1);a.dec_m=1-4*a.dt;a.dec_s=1-a.dt;a.dec_xs=1-div(a.dt,6);a.t0=a.time-a.tstart;a.bd_b=a.bass;a.bd_bass_=a.bd_bass_*a.dec_m+(1-a.dec_m)*a.bd_b;a.bd_bass=a.bd_b-a.bd_bass_;a.bd_m=a.mid;a.bd_mid_=a.bd_mid_*a.dec_m+(1-a.dec_m)*a.bd_m;a.bd_mid=a.bd_m-a.bd_mid_;a.bd_t=a.treb;a.bd_treb_=a.bd_treb_*a.dec_m+(1-a.dec_m)*a.bd_t;a.bd_treb=a.bd_t-a.bd_treb_;a.n=0;a.bpm=a.bd_minbpm;for(var b=0;bb;b++){a.bd_exc=a.bd_bass*(.00001>Math.abs(a.bd_src-0)?1:0)+a.bd_mid*(.00001>Math.abs(a.bd_src-1)?1:0)+a.bd_treb*(.00001>Math.abs(a.bd_src-2)?1:0);for(var c=a.oct=0;ca.bd_pk?1:0)?a.bd_pk=a.bd_ampl:0;a.bd_slot+=1}a.bd_slot=0;a.bd_qual=pow(div(a.bd_pk,a.bd_mean)*a.bd_spo-1,1);a.gmegabuf[Math.floor(2*(a.bd_src*a.bd_oct+a.oct))]=a.bd_qual;for(d=0;da.bd_pk?1:0)?(a.bd_pk=a.gmegabuf[Math.floor(a.m)],a.maxind=a.bd_slot):0,a.bd_slot+=1;\na.quali=div(a.bd_pk,a.bd_mean)*a.bd_spo-1;for(b=a.n=0;150>b;b++)a.gmegabuf[Math.floor(50+a.n)]*=0,a.n+=1;a.bd_src=0;a.tsin=0;for(b=a.tcos=0;3>b;b++){for(c=a.oct=0;cb;b++){a.oct=1;for(c=0;ca.maxa?1:0)?(a.maxa=a.ampl,a.maxs=a.bd_src,a.maxo=a.oct):0,a.oct+=1;a.bd_src+=1}a.q28=pow(4*a.bd_qual,1.5);a.q31=a.q28;.00001Math.abs(a.prog-0)?1:0,2>Math.abs(a.testi-a.test0)?1:0))?a.test0=a.testi:0;a.n=a.bd_dat0+a.test0*a.bd_recsz;a.creep=a.gmegabuf[Math.floor(a.n+1)];a.beat=(0a.creepo?1:0);a.beatct=.000011.2*sqrt(a.bass_att)?1:0)?(a.rot=.00001 1.333)))).xyz;\n ret_1 = tmpvar_12;\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = tmpvar_12;\n ret = tmpvar_13.xyz;\n }",comp:" shader_body { \n vec3 ret_1;\n ret_1 = mix (texture (sampler_main, uv).xyz, texture (sampler_main, ((0.5 - uv) + 0.5)).xyz, vec3(0.5, 0.5, 0.5));\n ret_1 = (1.0 - ((ret_1 * \n (1.0 - ret_1)\n ) * 4.0));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:.925,echo_zoom:1.007,echo_orient:3,wave_brighten:0,brighten:1,darken:1,solarize:1,wave_a:.001,wave_scale:.01,wave_smoothing:0,modwavealphastart:1,modwavealphaend:1,warpanimspeed:1.459,warpscale:2.007,fshader:1,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,ob_size:.015,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:5,mv_a:0},shapes:[{baseVals:{enabled:1,sides:100,textured:1,rad:.789,ang:.6283,tex_zoom:1.17257,r:0,g:1,border_a:0},init_eqs_str:"a.an=0;a.vx=0;a.vy=0;",frame_eqs_str:"a.rad=.65+.1*a.bass;a.an=.99*a.an+.1*(a.bass-a.treb);a.ang=.1*a.an+.6;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:495,sep:4,spectrum:1,thick:1,additive:1,scaling:100,smoothing:1,r:0,g:.04,b:0,a:.99},init_eqs_str:"a.my_z=0;a.d=0;a.n=0;a.y3=0;a.z2=0;a.y1=0;a.w=0;a.t5=0;a.w2=0;a.t1=0;a.x1=0;a.q6=0;a.zoom=0;a.p=0;a.q1=0;a.q5=0;a.t8=0;a.z3=0;a.w3=0;a.t3=0;a.my_x=0;a.x3=0;a.t6=0;a.my_y=0;a.pi=0;a.q4=0;a.t7=0;a.rd=0;a.w1=0;a.x2=0;a.t2=0;a.l=0;a.y2=0;a.q2=0;a.z1=0;a.q3=0;a.t4=0;a.t2=0;a.t3=0;a.t4=0;a.ab=1;",frame_eqs_str:"a.t1=a.q1;a.t2=a.q2;a.t3=a.q3;a.t4=a.q4;a.t5=a.q5;a.t6=a.q6;a.t8=.07;a.t7=1;",point_eqs_str:"a.t7=-a.t7;a.pi=Math.asin(1);a.n=180;a.rd=.075;a.my_x=.5*Math.sin(a.sample*a.pi*4+(a.t7+1)*a.t8)+Math.cos(a.sample*a.pi*a.n)*a.rd*Math.sin(a.sample*a.pi*4+(a.t7+1)*a.t8);a.my_y=.5*Math.cos(a.sample*a.pi*4+(a.t7+1)*a.t8)+Math.cos(a.sample*a.pi*a.n)*a.rd*Math.cos(a.sample*a.pi*4+(a.t7+1)*a.t8);a.my_z=Math.sin(a.sample*a.pi*a.n)*a.rd;a.d=1.4;a.zoom=.65;a.w1=a.q2;a.w2=a.q3;a.w3=a.q4;a.x1=Math.cos(a.w1)*a.my_x+Math.sin(a.w1)*a.my_y;a.y1=-Math.sin(a.w1)*a.my_x+Math.cos(a.w1)*a.my_y;\na.z1=a.my_z;a.x2=Math.cos(a.w2)*a.x1+Math.sin(a.w2)*a.z1;a.z2=-Math.sin(a.w2)*a.x1+Math.cos(a.w2)*a.z1;a.y2=a.y1;a.y3=Math.cos(a.w3)*a.y2+Math.sin(a.w3)*a.z2;a.z3=-Math.sin(a.w3)*a.y2+Math.cos(a.w3)*a.z2;a.x3=a.x2;a.l=sqrt(a.x3*a.x3+a.y3*a.y3);a.w=Math.atan2(a.x3,a.y3);a.p=Math.tan(Math.asin(1)+Math.atan2(a.d+a.z3,a.l));a.d=sqrt(a.x3*a.x3+a.y3*a.y3+(a.z3+a.d)*(a.z3+a.d));a.my_x=a.zoom*Math.sin(a.w)*a.p;a.my_y=a.zoom*Math.cos(a.w)*a.p;a.x=.5+a.my_x;a.y=.5+a.my_y;a.b=-a.z3+.5;a.b=.5*Math.min(1,Math.max(0,\na.b));a.r=1-2*a.b;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q29=0;a.q1=0;a.dec_med=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q28=0;a.q30=0;a.q20=0;a.p4=0;a.step=0;a.step=0;",frame_eqs_str:"a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,-2+a.avg+a.peak)*above(a.time,a.t0+.1);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,16);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+\na.mid_att+a.treb_att;a.q27=a.index+1;a.q28=a.index2;a.q29=2*(mod(a.index,2)-.5);a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,8);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.step+=a.q24;a.p3=a.p3*a.dec_slow+(1-a.dec_slow)*a.step;a.q30=a.step;a.p4=a.dec_slow*a.p4+(1-a.dec_slow)*a.q27;a.q31=a.p4;a.q12=a.time-a.t0;a.monitor=a.q12;a.zoom=1;a.rot=-0;a.dx=0;",pixel_eqs_str:"a.zoom=1.3;",warp:" shader_body { \n vec2 uv_1;\n vec2 uv6_2;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv - 0.5) * aspect.xy);\n float tmpvar_4;\n tmpvar_4 = (((q29 * 2.0) * sqrt(\n dot (tmpvar_3, tmpvar_3)\n )) + (rand_frame * 64.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_4) / cos(tmpvar_4)) * normalize(tmpvar_3))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 20.0));\n uv6_2 = (0.4 * sin((tmpvar_3 * 22.0)));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (((q24 * \n (((texture (sampler_main, uv_1).xyz - (\n ((texture (sampler_blur1, fract(uv_1)).xyz * scale1) + bias1)\n * 0.04)) + (0.15 * (vec3(\n (0.1 / sqrt(dot (uv6_2, uv6_2)))\n ) * roam_cos.xyz))) - 0.02)\n ) * 0.98) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_5.xyz;\n }",comp:"uniform sampler2D sampler_rand00;\n shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ((texture (sampler_rand00, (0.4 + \n (0.6 * tmpvar_1.xy)\n )) * tmpvar_1.z) * 3.0).xyz;\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:2,gammaadj:2.7,wave_mode:1,modwavealphabyvolume:1,wave_a:2.707,wave_scale:1.025,wave_smoothing:.1,modwavealphastart:.77,modwavealphaend:1.01,warpscale:1.331,zoom:1.014,warp:.21786,wave_r:.65,wave_g:.65,wave_b:.65,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"",frame_eqs_str:"a.wave_r+=.35*(.6*Math.sin(3.98*a.time)+.4*Math.sin(11.047*a.time));a.wave_g+=.35*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.35*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.cx+=.11*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.cy+=.11*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.dx+=.005*(.6*Math.sin(.173*a.time)+.4*Math.sin(.223*a.time));a.decay-=.01*equal(mod(a.frame,20),0);",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (texture (sampler_main, (uv + (\n (texture (sampler_main, (mix (uv, uv_orig, vec2(-1.0, -1.0)) + texsize.zw)).xy - 0.37)\n * 0.01))).xyz - 0.004);\n ret = tmpvar_1.xyz;\n }",comp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = mix (vec3(dot (tmpvar_1.xyz, vec3(0.3333, 0.3333, 0.3333))), tmpvar_1.xyz, vec3(3.0, 3.0, 3.0));\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.9,echo_zoom:1.16936,wave_mode:7,modwavealphabyvolume:1,wave_a:0,wave_scale:1.015009,wave_smoothing:.522,modwavealphastart:.83,modwavealphaend:1.31,warpscale:3.138,zoom:1.009006,warp:536e-6,wave_r:.5,wave_g:.5,wave_b:.5,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.dx_residual=0;a.dy_residual=0;a.bass_thresh=0;",frame_eqs_str:"a.wave_r=.85+.25*Math.sin(.437*a.time+1);a.wave_g=.85+.25*Math.sin(.544*a.time+2);a.wave_b=.85+.25*Math.sin(.751*a.time+3);a.rot+=.01*(.6*Math.sin(.381*a.time)+.4*Math.sin(.579*a.time));a.cx+=.21*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.cy+=.21*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.dx+=.003*(.6*Math.sin(.234*a.time)+.4*Math.sin(.277*a.time));a.dy+=.003*(.6*Math.sin(.284*a.time)+.4*Math.sin(.247*a.time));a.decay-=.01*equal(mod(a.frame,6),0);a.dx+=\na.dx_residual;a.dy+=a.dy_residual;a.bass_thresh=2*above(a.bass_att,a.bass_thresh)+(1-above(a.bass_att,a.bass_thresh))*(.96*(a.bass_thresh-1.3)+1.3);a.dx_residual=.016*equal(a.bass_thresh,2.13)*Math.sin(7*a.time)+(1-equal(a.bass_thresh,2.13))*a.dx_residual;a.dy_residual=.012*equal(a.bass_thresh,2.13)*Math.sin(9*a.time)+(1-equal(a.bass_thresh,2.13))*a.dy_residual;a.wave_x-=7*a.dx_residual;a.wave_y-=7*a.dy_residual;a.wave_mystery=.03*a.time;a.zoom+=.005*(.6*Math.sin(.1934*a.time+3)+.4*Math.sin(.307*\na.time+9));a.zoom+=.4*Math.max(0,a.bass_att-1.1);",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec3 ret_1;\n ret_1 = texture (sampler_main, uv).xyz;\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n ret_1 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }",comp:" shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz + ((\n (texture (sampler_blur1, uv).xyz * scale1)\n + bias1) * 0.4));\n vec3 tmpvar_2;\n tmpvar_2 = pow (ret_1, vec3(0.5, 0.8, 1.7));\n ret_1 = tmpvar_2;\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = tmpvar_2;\n ret = tmpvar_3.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1,decay:1,wave_mode:6,additivewave:1,wave_dots:1,wave_thick:1,wave_brighten:0,wave_a:100,wave_scale:3.63,wave_smoothing:.9,wave_mystery:-.3,modwavealphastart:1.15,modwavealphaend:1.55,warpscale:1.331,zoom:.96971,warp:0,wave_r:.6,wave_g:.6,wave_b:.6,mv_x:64,mv_y:48,mv_l:0,mv_r:.35,mv_g:.35,mv_b:.35,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.decay_rate=0;a.q6=0;a.rot_sum=0;a.q1=0;a.q5=0;a.prev_beat=0;a.is_beat=0;a.min_att=0;a.beat=0;a.decay_to=0;a.rot_sim=0;a.q2=0;a.q3=0;a.beat_level=0;a.rot_sum=0;a.q2=.07+.00004*randint(1E3)+.00003*randint(1E3);a.q3=1.035+.06*(randint(1E3)+randint(1E3)+randint(1E3))*.000333;",frame_eqs_str:"a.wave_r+=.5*(.6*Math.sin(1.98*a.time)+.4*Math.sin(3.047*a.time));a.wave_g+=.5*(.6*Math.sin(2.835*a.time)+.4*Math.sin(2.081*a.time));a.wave_b+=.5*(.6*Math.sin(3.814*a.time)+.4*Math.sin(1.011*a.time));a.cx=.5;a.cy=.5;a.rot=a.q2;a.zoom=a.zoom-1+a.q3;a.rot_sum+=a.rot;a.q1=-a.rot_sum;a.q5=Math.cos(a.rot_sum);a.q6=Math.sin(a.rot_sim);a.monitor=a.q2;a.min_att=2.5;a.decay_to=.8;a.decay_rate=pow(.999,a.fps);a.beat=div(a.bass,Math.max(a.min_att,a.bass_att));a.beat=Math.max(a.beat,div(a.mid,\nMath.max(a.min_att,a.mid_att)));a.beat=Math.max(a.beat,div(a.treb,Math.max(a.min_att,a.treb_att)));a.beat=Math.max(a.beat,(a.prev_beat-a.decay_to)*a.decay_rate+a.decay_to);a.beat_level=24*(a.beat-a.prev_beat-.02);a.is_beat=above(a.beat_level,.5);a.prev_beat=a.beat;a.wave_a=a.beat_level;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (texture (sampler_pw_main, uv).xyz - 0.004);\n ret = tmpvar_1.xyz;\n }",comp:" shader_body { \n vec2 uv_1;\n vec2 uv2_2;\n uv_1 = (uv - 0.5);\n uv_1 = (uv_1 * (min (aspect.x, aspect.y) * 0.8));\n uv_1 = (uv_1 * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = sin(q1);\n float tmpvar_4;\n tmpvar_4 = cos(q1);\n uv2_2.x = ((uv_1.x * tmpvar_4) - (uv_1.y * tmpvar_3));\n uv2_2.y = ((uv_1.x * tmpvar_3) + (uv_1.y * tmpvar_4));\n uv2_2 = (uv2_2 * aspect.zw);\n uv2_2 = (uv2_2 + 0.5);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (abs((\n (texture (sampler_main, uv2_2).xyz * 2.65)\n + \n (((texture (sampler_blur1, uv2_2).xyz * scale1) + bias1) * -2.0)\n )) * 1.5);\n ret = tmpvar_5.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.9,echo_zoom:1.16936,wave_mode:5,additivewave:1,wave_a:0,wave_scale:.899719,wave_smoothing:.63,wave_mystery:1,modwavealphastart:2,modwavealphaend:2,warpscale:2.593743,zoom:1.00496,warp:.278033,sx:.999666,sy:.9999,wave_r:.65,wave_g:.65,wave_b:.65,mv_x:0,mv_y:48,mv_dx:-.941273,mv_dy:.426319,mv_l:5,mv_r:.315997,mv_g:.078173,mv_b:.941976,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.du=0;a.q1=0;a.rg=0;a.q9=0;a.mult=0;a.ang2=0;a.dv=0;a.q4=0;a.q2=0;a.dist=0;a.q3=0;a.rg=0;",frame_eqs_str:"a.wave_r+=.35*(.6*Math.sin(.98*a.time)+.4*Math.sin(1.047*a.time));a.wave_g+=.35*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.35*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.q1=2*a.cx-1+.52*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.q2=2*a.cy-1+.52*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.q3=2*a.cx-1+.52*(.6*Math.sin(.174*-a.time)+.4*Math.sin(.364*a.time));a.q4=2*a.cy-1+.52*(.6*Math.sin(.234*a.time)+.4*Math.sin(.271*-a.time));\na.decay-=.01*equal(mod(a.frame,5),0);a.rg=Math.max(.95*a.rg,.3+.5*Math.min(2,1.3*Math.max(0,a.mid_att-1)));a.q9=a.rg;",pixel_eqs_str:"a.du=2*a.x-1-a.q1;a.dv=2*a.y-1-a.q2;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv);a.mult=div(.008,a.dist+.4);a.dx=a.mult*Math.sin(a.ang2-1.5);a.dy=a.mult*Math.cos(a.ang2-1.5);a.du=2*a.x-1-a.q3;a.dv=2*a.y-1-a.q4;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv);a.mult=div(.008,a.dist+.4);a.dx+=a.mult*Math.sin(a.ang2+1.5);a.dy+=a.mult*Math.cos(a.ang2+1.5);",warp:" shader_body { \n vec3 ret_1;\n vec2 tmpvar_2;\n tmpvar_2 = mix (uv_orig, uv, vec2(q9));\n ret_1 = texture (sampler_main, tmpvar_2).xyz;\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur1, tmpvar_2).xyz * scale1) + bias1)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n ret_1 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = ret_1;\n ret = tmpvar_3.xyz;\n }",comp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (0.3 + (0.4 * vec3(dot (texture (sampler_main, uv).xyz, vec3(0.32, 0.49, 0.29)))));\n ret = tmpvar_1.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.9,echo_zoom:1.169,echo_orient:1,wave_mode:5,additivewave:1,wave_a:0,wave_scale:.9,wave_smoothing:.63,wave_mystery:1,modwavealphastart:2,modwavealphaend:2,warpscale:1.331,zoom:1.004,warp:.19788,sx:.99967,sy:.9999,wave_r:.65,wave_g:.65,wave_b:.65,mv_x:0,mv_y:48,mv_dx:-.941,mv_dy:.426,mv_l:5,mv_r:.316,mv_g:.078,mv_b:.942,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.du=0;a.q1=0;a.dv=0;a.q2=0;a.dist=0;a.ang2=0;a.mult=0;",frame_eqs_str:"a.wave_r+=.2*(.6*Math.sin(.98*a.time)+.4*Math.sin(1.047*a.time));a.wave_g+=.2*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.2*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.q1=2*a.cx-1+.6*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.q2=2*a.cy-1+.6*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));",pixel_eqs_str:"a.du=2*a.x-1-a.q1;a.dv=2*a.y-1-a.q2;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv)+.15*a.time;a.mult=.65*Math.sin(.05*a.dist);a.dx=a.mult*Math.sin(2*a.ang2-1.5);a.dy=a.mult*Math.cos(2*a.ang2-1.5);",warp:" shader_body { \n vec3 ret_1;\n vec4 tmpvar_2;\n tmpvar_2 = texture (sampler_main, uv);\n ret_1 = (tmpvar_2.xyz + ((tmpvar_2.xyz - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n vec3 tmpvar_3;\n tmpvar_3 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n ret_1 = tmpvar_3;\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = tmpvar_3;\n ret = tmpvar_4.xyz;\n }",comp:" shader_body { \n vec2 uv2_1;\n vec3 ret_2;\n uv2_1 = (uv + (vec2(1.0, 0.0) * texsize.zw));\n float tmpvar_3;\n tmpvar_3 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(-1.0, 0.0) * texsize.zw));\n float tmpvar_4;\n tmpvar_4 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, 1.0) * texsize.zw));\n float tmpvar_5;\n tmpvar_5 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, -1.0) * texsize.zw));\n vec3 tmpvar_6;\n tmpvar_6.z = 0.14;\n tmpvar_6.x = (tmpvar_3 - tmpvar_4);\n tmpvar_6.y = (tmpvar_5 - ((\n (texture (sampler_main, uv2_1).xyz + (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4))\n + \n (((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2) * 0.15)\n ) + (\n ((texture (sampler_blur3, uv2_1).xyz * scale3) + bias3)\n * 0.1)).x);\n ret_2 = (0.5 + (0.5 * normalize(tmpvar_6)));\n vec2 x_7;\n x_7 = (ret_2.xy - 0.5);\n ret_2 = (ret_2 * clamp ((\n sqrt(dot (x_7, x_7))\n * 5.0), 0.0, 1.0));\n ret_2 = ret_2.xxy;\n ret_2 = (ret_2 + 1.15);\n ret_2 = (ret_2 * mix (ret_2, (ret_2 * \n (((texture (sampler_blur3, uv).xyz * scale3) + bias3) - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n ), pow (hue_shader.yxz, ret_2)));\n ret_2 = (ret_2 * ret_2);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = ret_2;\n ret = tmpvar_8.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:2.4,decay:1,echo_zoom:.997,echo_alpha:.5,echo_orient:3,wave_mode:2,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:.28,wave_smoothing:.9,modwavealphastart:.71,modwavealphaend:1.3,warpanimspeed:2.599,warpscale:.01,zoomexp:.99817,zoom:.86978,warp:.01,sy:1.0017,wave_r:0,wave_g:0,wave_b:0,ob_size:0,ob_r:1,ob_g:1,ob_b:1,ib_size:.04,ib_r:0,ib_g:0,ib_b:0,ib_a:1,mv_x:64,mv_y:48,mv_l:.5,mv_r:.35,mv_g:.35,mv_b:.35,mv_a:.2},shapes:[{baseVals:{enabled:1,sides:20,additive:1,textured:1,rad:1.99867,tex_zoom:.49486,g:1,b:1,a:.75,r2:1,b2:1,a2:1,border_a:0},init_eqs_str:"",frame_eqs_str:""},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.ang2=0;a.redsine=0;a.greensine=0;a.bluesine=0;a.redif=0;a.greenif=0;a.blueif=0;a.decay=.1;",frame_eqs_str:"a.sx=1;a.sy=1;a.redsine=.5+.15*a.bass*Math.sin(3*a.time);a.greensine=.5+.15*a.mid*Math.sin(2*a.time);a.bluesine=.5+.15*a.treb*Math.sin(a.time);a.redif=.9*(.00001 (q21 * q13)) && (tmpvar_2.x <= (q24 * q11)))) {\n ret_1.y = (tmpvar_2.y - (tmpvar_3.x * 0.5));\n };\n if (((ret_1.y > (q22 * q11)) && (ret_1.y <= (q25 * q12)))) {\n ret_1.z = (tmpvar_2.z - (tmpvar_3.y * 0.5));\n };\n if (((ret_1.z > (q23 * q12)) && (ret_1.z <= (q26 * q13)))) {\n ret_1.x = (tmpvar_2.x - (tmpvar_3.z * 0.5));\n };\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur1, uv).xyz * scale1) + bias1)\n ) * 0.2));\n ret_1 = (ret_1 - 0.02);\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = ret_1;\n ret = tmpvar_4.xyz;\n }",comp:" shader_body { \n vec2 uv_1;\n vec3 ret_2;\n uv_1 = (0.05 + (0.9 * uv));\n vec4 tmpvar_3;\n tmpvar_3 = texture (sampler_main, uv_1);\n ret_2 = tmpvar_3.xyz;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_noisevol_hq, (((vec3(0.05, 0.05, 0.0) * uv_1.xyy) * (\n (q28 * texsize.xyy)\n * texsize_noisevol_hq.zww)) + ((time * vec3(0.0, 0.0, 1.0)) * q31)));\n if (((tmpvar_3.x > (q26 * q13)) && (tmpvar_3.x <= (q23 * q11)))) {\n ret_2.z = (tmpvar_3.z - (tmpvar_4.x * 0.5));\n };\n if (((tmpvar_3.y > (q25 * q11)) && (tmpvar_3.y <= (q22 * q12)))) {\n ret_2.x = (tmpvar_3.x - (tmpvar_4.y * 0.5));\n };\n if (((ret_2.z > (q24 * q12)) && (ret_2.z <= (q21 * q13)))) {\n ret_2.y = (tmpvar_3.y - (tmpvar_4.z * 0.5));\n };\n ret_2 = (abs((\n ((texture (sampler_blur1, uv_1).xyz * scale1) + bias1)\n - ret_2)) * 6.0);\n ret_2 = (ret_2 * 1.333);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:1.157,wave_smoothing:.63,modwavealphastart:.71,modwavealphaend:1.3,warpscale:1.331,zoom:.9995,warp:.009,wave_r:.65,wave_g:.65,wave_b:.65,ob_size:.5,ob_r:.01,ib_size:.26,mv_x:64,mv_y:48,mv_l:0,mv_a:0,b1x:.7,b1ed:0},shapes:[{baseVals:{enabled:1,sides:14,num_inst:512,rad:.1026,tex_ang:.62832,r2:1,g2:0,a2:1,border_a:0},init_eqs_str:"a.ma=0;a.mx=0;a.my=0;a.r_border=0;a.g_border=0;a.b_border=0;",frame_eqs_str:"a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001 1.0)\n ) * (\n (tmpvar_9 * -2.0)\n + 1.570796)));\n tmpvar_7 = (tmpvar_9 * sign((uv5_4.y / uv5_4.x)));\n if ((abs(uv5_4.x) > (1e-08 * abs(uv5_4.y)))) {\n if ((uv5_4.x < 0.0)) {\n if ((uv5_4.y >= 0.0)) {\n tmpvar_7 += 3.141593;\n } else {\n tmpvar_7 = (tmpvar_7 - 3.141593);\n };\n };\n } else {\n tmpvar_7 = (sign(uv5_4.y) * 1.570796);\n };\n xlat_mutablers0.x = (((tmpvar_7 / 3.1416) * 6.0) * q28);\n float tmpvar_10;\n tmpvar_10 = (1.5 / sqrt(dot (uv_1, uv_1)));\n xlat_mutablers0.y = tmpvar_10;\n vec2 tmpvar_11;\n tmpvar_11.x = (xlat_mutablers0.x + (q9 * 4.0));\n tmpvar_11.y = (tmpvar_10 + ((q9 * q28) * 4.0));\n xlat_mutablerss = (tmpvar_11 / 12.0);\n vec2 tmpvar_12;\n tmpvar_12.x = q5;\n tmpvar_12.y = q6;\n ofs_2 = (0.1 * tmpvar_12.yx);\n float tmpvar_13;\n float tmpvar_14;\n tmpvar_14 = -(q9);\n tmpvar_13 = fract(tmpvar_14);\n mat2 tmpvar_15;\n tmpvar_15[uint(0)].x = 1.0;\n tmpvar_15[uint(0)].y = -0.0;\n tmpvar_15[1u].x = 0.0;\n tmpvar_15[1u].y = 1.0;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_13)\n * tmpvar_15)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * (1.0 - \n (tmpvar_13 * tmpvar_13)\n )));\n float tmpvar_16;\n tmpvar_16 = fract((tmpvar_14 + 0.3333333));\n mat2 tmpvar_17;\n tmpvar_17[uint(0)].x = -0.4990803;\n tmpvar_17[uint(0)].y = -0.8665558;\n tmpvar_17[1u].x = 0.8665558;\n tmpvar_17[1u].y = -0.4990803;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_16)\n * tmpvar_17)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_16 * tmpvar_16)\n )));\n float tmpvar_18;\n tmpvar_18 = fract((tmpvar_14 + 0.6666667));\n mat2 tmpvar_19;\n tmpvar_19[uint(0)].x = -0.5018377;\n tmpvar_19[uint(0)].y = 0.8649619;\n tmpvar_19[1u].x = -0.8649619;\n tmpvar_19[1u].y = -0.5018377;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_18)\n * tmpvar_19)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_18 * tmpvar_18)\n )));\n float tmpvar_20;\n tmpvar_20 = fract((tmpvar_14 + 1.0));\n mat2 tmpvar_21;\n tmpvar_21[uint(0)].x = 0.9999949;\n tmpvar_21[uint(0)].y = 0.003185092;\n tmpvar_21[1u].x = -0.003185092;\n tmpvar_21[1u].y = 0.9999949;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_20)\n * tmpvar_21)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_20 * tmpvar_20)\n )));\n vec2 tmpvar_22;\n tmpvar_22.x = (ret1_3.x + ret1_3.z);\n tmpvar_22.y = (ret1_3.x - ret1_3.y);\n xlat_mutableret2 = (((\n (texture (sampler_blur1, fract((xlat_mutablerss + (tmpvar_22 / 2.0)))).xyz * scale1)\n + bias1) / tmpvar_10) * 12.0);\n vec4 tmpvar_23;\n tmpvar_23.w = 1.0;\n tmpvar_23.xyz = ((ret1_3 + (\n ((bass_att * 0.004) / sqrt(dot (uv_1, uv_1)))\n * roam_sin).xyz) + (sqrt(xlat_mutableret2.zxy) * clamp (\n (1.0 - (ret1_3 * 4.0))\n , 0.0, 1.0)));\n ret = tmpvar_23.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:2,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:.958,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,ob_size:0,ob_g:.1,ob_b:1,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,mv_x:25.6,mv_y:9.6,mv_l:0,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.n=0;a.reg26=0;a.uvx0=0;a.reg34=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.q12=0;a.v3=0;a.q22=0;a.q21=0;a.diry=0;a.q13=0;a.q6=0;a.posx=0;a.fps_=0;a.reg25=0;a.uvx=0;a.q1=0;a.travel=0;a.posz=0;a.q5=0;a.movz=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.slow=0;a.reg36=0;a.reg22=0;a.uvy=0;a.rotz=0;a.dist_=0;a.q23=0;a.q24=0;a.reg24=0;a.cran0=0;a.vx=0;a.ran2=0;a.q11=0;a.q10=0;a.reg14=0;a.posy=0;a.vy=0;a.vz=0;a.reg31=0;a.dirx=0;a.dec_m=0;a.q4=0;a.start=0;a.reg12=\n0;a.reg13=0;a.c2=0;a.reg37=0;a.s3=0;a.yslope=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.reg35=0;a.reg11=0;a.tx=0;a.avg=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.beat=0;a.q17=0;a.vol=0;a.reg32=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.reg30=0;a.q27=0;a.slen=0;a.q14=0;a.dist=0;a.reg17=0;a.v1=0;a.speed=0;a.s1=0;a.t0=0;a.s2=0;a.ran1=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.ty=0;a.c1=0;a.v2=0;a.q20=0;a.q8=0;a.avg=.01;a.q7=.2;a.q8=div(randint(200),100)-1;a.q16=1.2;a.q18=randint(.8)+.1;a.q17=2.6;a.start=1;a.travel=\n0;a.rotz=0;a.look=0;a.slow=0;a.t0=a.time+3;a.lampx=.5;a.lampy=.5;a.cran0=randint(1);for(var b=a.n=0;1E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(10)-5;a.posy=randint(10)-5;a.posz=randint(10)-5;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)*a.q17+a.uvx0,a.uvy=(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)*a.q17+a.uvy0,a.uvz=(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)*a.q17+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);",frame_eqs_str:"a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.03*30,a.fps_);a.dec_m=1-div(3,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001a.dist_?1:0);a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*\na.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+\na.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=\na.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001\na.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)*a.q17+a.uvx0,a.uvy=(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)*a.q17+a.uvy0,a.uvz=(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)*a.q17+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+\n2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.warp=0;a.zoom=1;a.dx=div(-a.v2,a.q16);a.dy=div(a.v3,a.q16);a.rot=a.v1;a.vx-=div(a.v2,a.q16);a.vy+=div(a.v3,a.q16);a.vz+=a.v1;a.q11=a.vx;a.q12=a.vy;a.movz+=a.ds;a.q13=a.movz;a.monitor=a.q13;",pixel_eqs_str:"",pixel_eqs:"",warp:"float sustain;\nfloat ffac;\nfloat xlat_mutabledist;\nfloat xlat_mutablelimit;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (0.98 - q14);\n ffac = q17;\n vec2 uv_3;\n uv_3 = (((uv - 0.5) * (1.0 - \n (q10 / (1.0 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).z))\n )) + 0.5);\n xlat_mutableuv1 = (((uv_orig - 0.5) * aspect.xy) * q16);\n vec4 tmpvar_4;\n tmpvar_4 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n vec3 tmpvar_5;\n tmpvar_5 = tmpvar_4.xyz;\n if ((tmpvar_4.y > (0.4 * rad))) {\n vec3 tmpvar_6;\n tmpvar_6 = (tmpvar_4.xyz - vec3(0.5, 0.5, 0.5));\n vec4 nb2_7;\n vec4 nb_8;\n vec2 tmpvar_9;\n tmpvar_9 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 - texsize.zw)).yz)\n + vec2(0.5, 0.5))));\n nb_8.x = (1.0 - (tmpvar_9.y + (0.015625 * \n (tmpvar_9.x - 0.5)\n )));\n vec2 tmpvar_10;\n tmpvar_10 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(1.0, -1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb_8.y = (1.0 - (tmpvar_10.y + (0.015625 * \n (tmpvar_10.x - 0.5)\n )));\n vec2 tmpvar_11;\n tmpvar_11 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + texsize.zw)).yz)\n + vec2(0.5, 0.5))));\n nb_8.z = (1.0 - (tmpvar_11.y + (0.015625 * \n (tmpvar_11.x - 0.5)\n )));\n vec2 tmpvar_12;\n tmpvar_12 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(-1.0, 1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb_8.w = (1.0 - (tmpvar_12.y + (0.015625 * \n (tmpvar_12.x - 0.5)\n )));\n vec2 tmpvar_13;\n tmpvar_13 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(0.0, -1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.x = (1.0 - (tmpvar_13.y + (0.015625 * \n (tmpvar_13.x - 0.5)\n )));\n vec2 tmpvar_14;\n tmpvar_14 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(1.0, 0.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.y = (1.0 - (tmpvar_14.y + (0.015625 * \n (tmpvar_14.x - 0.5)\n )));\n vec2 tmpvar_15;\n tmpvar_15 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(0.0, 1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.z = (1.0 - (tmpvar_15.y + (0.015625 * \n (tmpvar_15.x - 0.5)\n )));\n vec2 tmpvar_16;\n tmpvar_16 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(-1.0, 0.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.w = (1.0 - (tmpvar_16.y + (0.015625 * \n (tmpvar_16.x - 0.5)\n )));\n vec4 tmpvar_17;\n tmpvar_17 = min (nb_8, nb2_7);\n nb_8.zw = tmpvar_17.zw;\n nb_8.xy = min (tmpvar_17.xy, tmpvar_17.zw);\n xlat_mutabledist = (min (nb_8.x, nb_8.y) + ((0.006 * tmpvar_6.x) * abs(tmpvar_6.y)));\n } else {\n xlat_mutabledist = tmpvar_5.x;\n };\n vec2 tmpvar_18;\n tmpvar_18 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, uv_3).yz)\n + vec2(0.5, 0.5))));\n xlat_mutabledist = (min (xlat_mutabledist, (1.0 - \n (tmpvar_18.y + (0.015625 * (tmpvar_18.x - 0.5)))\n )) - (q10 * 0.8));\n xlat_mutablelimit = (15.0 + (10.0 * xlat_mutabledist));\n vec3 tmpvar_19;\n tmpvar_19.xy = (xlat_mutableuv1 * xlat_mutabledist);\n tmpvar_19.z = xlat_mutabledist;\n xlat_mutableuv2 = (((tmpvar_19 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n int iterations_21;\n vec3 zz0_22;\n vec3 zz_23;\n zz_23 = xlat_mutableuv2;\n zz0_22 = (xlat_mutableuv2 + q8);\n iterations_21 = int((8.0 - float(\n (xlat_mutabledist > 0.8)\n )));\n for (int n_20 = 0; n_20 <= iterations_21; n_20++) {\n zz_23 = ((2.0 * clamp (zz_23, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_23);\n zz_23 = (zz_23 * (clamp (\n max ((0.25 / dot (zz_23, zz_23)), 0.25)\n , 0.0, 1.0) * 4.0));\n zz_23 = ((ffac * zz_23) + zz0_22);\n };\n xlat_mutablestruc = (sqrt(dot (zz_23.xz, zz_23.xz)) / xlat_mutablelimit);\n vec2 tmpvar_24;\n tmpvar_24 = (0.0078125 * floor((\n (128.0 * vec2((1.0 - xlat_mutabledist)))\n + vec2(0.5, 0.5))));\n vec2 tmpvar_25;\n tmpvar_25.x = ((64.0 * (\n (1.0 - xlat_mutabledist)\n - tmpvar_24.x)) + 0.5);\n tmpvar_25.y = tmpvar_24.x;\n vec3 tmpvar_26;\n float tmpvar_27;\n tmpvar_27 = (q14 * 2.0);\n tmpvar_26.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(tmpvar_27)).x));\n tmpvar_26.yz = tmpvar_25;\n vec3 tmpvar_28;\n tmpvar_28.y = 1.0;\n tmpvar_28.x = sustain;\n tmpvar_28.z = 1.0;\n vec3 tmpvar_29;\n tmpvar_29.y = 0.0;\n tmpvar_29.x = 0.003921569;\n tmpvar_29.z = (0.01568628 * (0.2 + rad));\n vec4 tmpvar_30;\n tmpvar_30.w = 1.0;\n tmpvar_30.xyz = mix (tmpvar_26, ((\n mix (texture (sampler_main, uv_3).xyz, ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1), vec3(tmpvar_27))\n * tmpvar_28) - tmpvar_29), vec3(clamp ((\n sqrt(dot (zz_23, zz_23))\n - xlat_mutablelimit), 0.0, 1.0)));\n ret = tmpvar_30.xyz;\n }",comp:"float xlat_mutableinten;\nfloat xlat_mutabletmp;\nvec2 xlat_mutableuv1;\nvec2 xlat_mutableuv2;\nfloat xlat_mutablez;\n shader_body { \n float t_rel_2;\n vec3 ret1_3;\n float struc_4;\n xlat_mutableuv1 = ((uv * aspect.xy) - vec2(0.5, 0.5));\n vec4 tmpvar_5;\n tmpvar_5 = texture (sampler_main, uv);\n float tmpvar_6;\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_blur1, uv);\n tmpvar_6 = mix (min ((1.0 - tmpvar_5.z), (1.0 - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n .z)), (1.0 - (\n (tmpvar_7.xyz * scale1)\n + bias1).z), 0.5);\n struc_4 = ((mix (tmpvar_5.xyz, \n ((tmpvar_7.xyz * scale1) + bias1)\n , vec3(tmpvar_6)).x * (1.0 - tmpvar_6)) * tmpvar_6);\n vec2 tmpvar_8;\n tmpvar_8.x = q11;\n tmpvar_8.y = q12;\n xlat_mutableuv2 = ((xlat_mutableuv1 * 0.2) - (tmpvar_8 * 0.2));\n vec2 uvi_9;\n uvi_9 = (xlat_mutableuv2 * 4.0);\n float zv_10;\n zv_10 = (0.008 * time);\n xlat_mutabletmp = clamp (dot ((texture (sampler_noise_hq, \n (xlat_mutableuv2 + (0.03 * ((\n (dot (texture (sampler_noise_hq, uvi_9), vec4(0.32, 0.49, 0.29, 0.0)) + (dot (texture (sampler_noise_hq, (\n (uvi_9 * 2.0)\n + zv_10)), vec4(0.32, 0.49, 0.29, 0.0)) / 2.0))\n + \n (dot (texture (sampler_noise_hq, ((uvi_9 * 4.0) + (2.0 * zv_10))), vec4(0.32, 0.49, 0.29, 0.0)) / 4.0)\n ) + (\n dot (texture (sampler_noise_hq, ((uvi_9 * 8.0) + (4.0 * zv_10))), vec4(0.32, 0.49, 0.29, 0.0))\n / 8.0))))\n ) - 0.4), vec4(0.32, 0.49, 0.29, 0.0)), 0.0, 1.0);\n float tmpvar_11;\n tmpvar_11 = clamp ((pow (xlat_mutabletmp, 1.2) * sign(xlat_mutabletmp)), 0.0, 1.0);\n xlat_mutabletmp = tmpvar_11;\n vec3 tmpvar_12;\n tmpvar_12.xy = vec2(0.1, 0.1);\n tmpvar_12.z = (1.2 - uv.y);\n ret1_3 = ((tmpvar_12 + 0.07) + ((\n clamp (((tmpvar_6 * 2.0) - 1.5), 0.0, 1.0)\n * tmpvar_11) * 4.0));\n t_rel_2 = (q13 * 6.0);\n for (int n_1 = 1; n_1 <= 3; n_1++) {\n xlat_mutablez = (1.0 - fract((\n (float(n_1) / 3.0)\n - \n (fract(-(t_rel_2)) / 3.0)\n )));\n xlat_mutableinten = (((1.0 - xlat_mutablez) * xlat_mutablez) * 2.0);\n vec2 tmpvar_13;\n tmpvar_13.x = q11;\n tmpvar_13.y = q12;\n xlat_mutableuv2 = (((xlat_mutablez * xlat_mutableuv1) / 4.0) - (tmpvar_13 / 6.0));\n vec2 uvi_14;\n uvi_14 = (xlat_mutableuv2 * 4.0);\n float zv_15;\n zv_15 = (0.008 * time);\n xlat_mutabletmp = clamp (dot ((\n (texture (sampler_noise_hq, (xlat_mutableuv2 + (0.03 * (\n ((dot (texture (sampler_noise_hq, uvi_14), vec4(0.32, 0.49, 0.29, 0.0)) + (dot (texture (sampler_noise_hq, \n ((uvi_14 * 2.0) + zv_15)\n ), vec4(0.32, 0.49, 0.29, 0.0)) / 2.0)) + (dot (texture (sampler_noise_hq, (\n (uvi_14 * 4.0)\n + \n (2.0 * zv_15)\n )), vec4(0.32, 0.49, 0.29, 0.0)) / 4.0))\n + \n (dot (texture (sampler_noise_hq, ((uvi_14 * 8.0) + (4.0 * zv_15))), vec4(0.32, 0.49, 0.29, 0.0)) / 8.0)\n )))) - (xlat_mutablez * 0.5))\n - 0.3), vec4(0.32, 0.49, 0.29, 0.0)), 0.0, 1.0);\n xlat_mutabletmp = (((\n clamp ((xlat_mutabletmp * sign(xlat_mutabletmp)), 0.0, 1.0)\n * xlat_mutableinten) * q1) * 2.0);\n ret1_3 = (((ret1_3 + \n ((vec3(4.0, 3.0, 0.8) * q1) * struc_4)\n ) * clamp (\n (1.0 - xlat_mutabletmp)\n , 0.0, 1.0)) + xlat_mutabletmp);\n };\n vec4 tmpvar_16;\n tmpvar_16.w = 1.0;\n tmpvar_16.xyz = (1.0 - exp((-1.6 * ret1_3)));\n ret = tmpvar_16.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,additivewave:1,wave_dots:1,wave_thick:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.527,wave_smoothing:0,wave_mystery:.6,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_g:.49,ob_a:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b2x:.6,b3x:.4,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:1,sides:5,additive:1,num_inst:256,x:.26,y:.2,rad:.39317,tex_zoom:.9355,g2:0,a2:.2,border_g:0,border_b:0,border_a:0},init_eqs_str:"a.n=0;a.w=0;a.high=0;a.q12=0;a.arg=0;a.q13=0;a.y0=0;a.flen=0;a.x0=0;a.k1=0;a.q11=0;a.z0=0;a.exc=0;a.p2=0;a.p1=0;a.a0=0;a.q2=0;a.slen=0;a.q14=0;a.q3=0;a.q32=0;a.rad0=0;",frame_eqs_str:"a.n=a.instance;a.flen=a.reg00;a.slen=div(a.reg00,2);a.z0=10;a.y0=div(a.gmegabuf[Math.floor(2E3+a.n+a.flen)],a.z0);a.x0=div(a.gmegabuf[Math.floor(2E3+a.n)],a.z0);a.a0=a.gmegabuf[Math.floor(a.n+1E4)];a.k1=div(a.instance,a.num_inst)-.5;a.x=.5+a.x0+Math.sin(8*a.k1*Math.sin(.07*a.q12))*Math.sin(.13*a.q11)*a.q3*.7;a.y=.5+a.q32*(a.y0+Math.sin(8*a.k1*Math.sin(.1*a.q14))*Math.sin(.2*a.q13)*a.q3*.7);a.arg=div(a.q2,8);a.high=Math.exp(-500*pow(a.arg+.5-div(a.instance,a.num_inst),2));a.high+=\nMath.exp(-500*pow(-a.arg+.5-div(a.instance,a.num_inst),2));a.exc=sqrt(pow(a.x-.5,2)+pow(a.y-.5,2));a.rad0=above(a.z0,0)*Math.min(.1,div(a.a0,60))+.005;a.rad0=a.rad0*(1+2*a.exc)*(1+a.high);a.p1=.5+div(Math.sin(a.q12),2);a.p2=.5+div(Math.sin(1.4*a.q13),2);a.exc=pow(a.x-a.p1,2)+pow(a.y-a.p2,2);a.rad=Math.min(a.rad0*(1+div(.004*a.q3,Math.abs(a.exc))),1);a.a=Math.min(8*a.a0+.4,1);a.k1=5*div(a.instance,a.num_inst)+a.high;a.w=1-Math.exp(div(-a.treb_att,2)-.5);a.g=a.w+(1-a.w)*Math.sin(a.k1);a.r=a.w+(1-a.w)*\nMath.sin(a.k1-div(6.28,3));a.b=a.w+(1-a.w)*Math.sin(a.k1-div(12.56,3));a.a2=div(a.a,4);a.g2=0*a.g;a.b2=0*a.b;a.r2=0*a.r;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,sep:120,spectrum:1,additive:1,scaling:7.52386,smoothing:0,r:0,a:.7},init_eqs_str:"a.flen=0;a.n=0;a.vol=0;a.chg=0;a.dec=0;a.q1=0;a.q2=0;",frame_eqs_str:"",point_eqs_str:"a.flen=a.reg00;a.n=Math.floor(a.sample*a.flen);a.vol=(a.value1+a.value2)*(1+div(.1,a.sample+.03));a.chg=Math.min(Math.max(a.vol-a.gmegabuf[Math.floor(a.n)],-1),1);a.dec=.00001a.q2?1:0))]*(1-a.dec);a.gmegabuf[Math.floor(a.n+1E4)]=.2*a.gmegabuf[Math.floor(a.n+1E4)]+div(.8*a.vol,3);a.a=0;a.x=a.sample;a.y=.2+.23*a.gmegabuf[Math.floor(a.n+0)];"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.n=0;a.sw2=0;a.in1=0;a.q12=0;a.q13=0;a.sw3=0;a.dif=0;a.q1=0;a.lev3=0;a.flen=0;a.lev4=0;a.in2=0;a.lev1=0;a.k1=0;a.q11=0;a.ofs=0;a.dec_m=0;a.i=0;a.k=0;a.m2=0;a.vol=0;a.q2=0;a.slen=0;a.m1=0;a.q14=0;a.sw1=0;a.lev2=0;a.q3=0;a.reg00=0;a.vol_=0;a.dec=0;a.q32=0;a.sw4=0;for(var b=a.n=0;5E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.sw1=randint(8);a.sw2=randint(8);a.sw3=randint(8);a.sw4=randint(8);",frame_eqs_str:"a.flen=512;a.reg00=a.flen;a.slen=div(a.flen,2);a.dec_m=pow(.94,div(30,a.fps));a.n=0;for(var b=a.vol=0;ba.in1*a.in1+a.in2*a.in2?1:0)?.8:.94,a.dec=pow(a.dec,div(30,a.fps)),a.gmegabuf[Math.floor(2E3+a.n)]=a.gmegabuf[Math.floor(2E3+a.n)]*a.dec+(1-a.dec)*a.in1,a.gmegabuf[Math.floor(2E3+a.flen+a.n)]=a.gmegabuf[Math.floor(2E3+a.flen+a.n)]*a.dec+(1-a.dec)*a.in2,a.n+=1;a.q1=div(a.bass+a.treb+a.mid,3);a.q2=div(a.bass_att+a.treb_att+a.mid_att,3);a.q3=a.vol_;a.q11=a.sw1;a.q12=a.sw2;a.q13=\na.sw3;a.q14=a.sw4;a.rot=0;a.zoom=.98;a.warp=.3;a.rot=0;a.q32=a.aspecty;a.monitor=a.dif;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = ((texture (sampler_main, uv).xyz * clamp (\n (q1 - 0.8)\n , 0.0, 1.0)) * 0.92);\n ret = tmpvar_1.xyz;\n }",comp:" shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz + ((texture (sampler_blur2, uv).xyz * scale2) + bias2));\n ret_1 = (ret_1 + ((0.8 * \n (hue_shader - 0.8)\n ) * (1.0 - uv.y)));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:4,additivewave:1,wave_dots:1,modwavealphabyvolume:1,darken:1,wave_a:.33064,wave_scale:.897961,wave_smoothing:.108,wave_mystery:.1,modwavealphastart:.72,modwavealphaend:1.28,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:.5,wave_b:.5,wave_y:.54,ob_r:1,ob_g:1,ob_b:1,ib_size:.26,mv_x:24.799994,mv_dy:.16,mv_l:1.5,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:352,usedots:1,additive:1,scaling:.038558,smoothing:.2,g:0},init_eqs_str:"a.t02=0;a.q1=0;a.ratio=0;a.ampl=0;a.x1=0;a.y1=0;",frame_eqs_str:"a.q1=a.bass_att;",point_eqs_str:"a.r=Math.abs(Math.sin(div(a.frame,38)));a.g=.5*Math.abs(Math.cos(div(a.frame,45)));a.b=.5*Math.abs(Math.sin(div(a.frame,133)));a.a=.3;a.t02+=div(a.q1,10);a.ratio=Math.sin(div(a.frame,49));a.ampl=.01+.4*sqr(Math.sin(div(a.frame,18))*Math.cos(div(a.frame,123)));a.x1=div(a.r-.5,15)+.5+a.ampl*Math.sin(6.28*a.sample);a.y1=div(a.b-.5,15)+.5+a.ampl*Math.cos(6.28*a.sample);a.x=a.x1+.2*(a.ampl+a.ratio)*Math.sin(6.28*a.sample*a.ratio*7.3);a.y=a.y1+.2*(a.ampl+a.ratio)*Math.cos(37.68*a.sample);\n"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.q25=0;a.index=0;a.q18=0;a.q22=0;a.q21=0;a.q29=0;a.q6=0;a.movex=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.mov=0;a.avg=0;a.beat=0;a.p1=0;a.dx1=0;a.peak=0;a.q2=0;a.q27=0;a.clear=0;a.p3=0;a.q3=0;a.t0=0;a.rot1=0;a.q32=0;a.q28=0;a.q20=0;a.clear=.5;",frame_eqs_str:"a.dec_med=pow(.96,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,4);a.index2=mod(a.index2+a.is_beat*bnot(a.index),8);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.q20=a.avg;a.q21=\na.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.p3=a.dec_med*a.p3+(1-a.dec_med)*a.p2;a.rott=div(3.1416*a.p3,4);a.rot1+=a.q26;a.q25=.01*a.rot1;a.q27=8-a.index;a.q28=a.index3;a.dx1=a.dec_med*a.dx1+(1-a.dec_med)*bnot(a.index2);a.q29=a.dx1;a.monitor=a.q29;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.q5=1.5*Math.cos(div(a.time,9));a.q6=.5*Math.sin(div(a.time,\n7));a.clear=a.clear*a.dec_med+1-a.dec_med;a.q32=a.clear;a.mov=bnot(a.q24)*a.movex+(div(randint(100),100)-50)*a.q2;a.movex+=div(.2,a.fps)*a.q2;a.q18=a.movex;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec2 uv6_1;\n vec2 tmpvar_2;\n tmpvar_2 = ((uv - 0.5) * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = (rand_frame * 64.0).x;\n uv6_1 = (0.5 * cos((\n ((tmpvar_2 * mat2(0.7, -0.7, 0.7, 0.7)) * 17.0)\n + \n (rand_frame * 6.0)\n .xy)));\n float x_4;\n x_4 = (uv6_1.x + uv6_1.y);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ((0.147 * (\n (texture (sampler_main, (uv + clamp ((\n (sin(tmpvar_3) / cos(tmpvar_3))\n * \n normalize(tmpvar_2)\n ), vec2(-8.0, -8.0), vec2(8.0, 8.0)))).xyz + (0.15 * (vec3((0.01 / \n sqrt((x_4 * x_4))\n )) * roam_cos.xyz)))\n - 0.02)) + ((0.85 * \n (texture (sampler_main, uv_orig).xyz - 0.002)\n ) * q32));\n ret = tmpvar_5.xyz;\n }",comp:"vec2 xlat_mutabledz;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\nvec2 xlat_mutableuv4;\n shader_body { \n vec2 uv_1;\n float inten_2;\n float dist_3;\n vec3 ret_4;\n uv_1 = (uv - 0.5);\n float tmpvar_5;\n tmpvar_5 = (time / 2.0);\n dist_3 = (1.0 - fract(tmpvar_5));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_6;\n tmpvar_6.y = 0.4;\n tmpvar_6.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_6);\n vec2 tmpvar_7;\n tmpvar_7.y = 0.0;\n tmpvar_7.x = texsize.z;\n vec2 tmpvar_8;\n tmpvar_8.y = 0.0;\n tmpvar_8.x = texsize.z;\n xlat_mutabledz.x = (inten_2 * dot ((texture (sampler_main, \n (xlat_mutableuv3 + tmpvar_7)\n ).xyz - texture (sampler_main, \n (xlat_mutableuv3 - tmpvar_8)\n ).xyz), vec3(0.32, 0.49, 0.29)));\n vec2 tmpvar_9;\n tmpvar_9.x = 0.0;\n tmpvar_9.y = texsize.w;\n vec2 tmpvar_10;\n tmpvar_10.x = 0.0;\n tmpvar_10.y = texsize.w;\n xlat_mutabledz.y = (inten_2 * dot ((texture (sampler_main, \n (xlat_mutableuv3 + tmpvar_9)\n ).xyz - texture (sampler_main, \n (xlat_mutableuv3 - tmpvar_10)\n ).xyz), vec3(0.32, 0.49, 0.29)));\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((0.3333333 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_11;\n tmpvar_11.y = 0.4;\n tmpvar_11.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_11);\n vec2 tmpvar_12;\n tmpvar_12.y = 0.0;\n tmpvar_12.x = texsize.z;\n vec2 tmpvar_13;\n tmpvar_13.y = 0.0;\n tmpvar_13.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_12)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_13)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_14;\n tmpvar_14.x = 0.0;\n tmpvar_14.y = texsize.w;\n vec2 tmpvar_15;\n tmpvar_15.x = 0.0;\n tmpvar_15.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_14)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_15)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((0.6666667 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_16;\n tmpvar_16.y = 0.4;\n tmpvar_16.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_16);\n vec2 tmpvar_17;\n tmpvar_17.y = 0.0;\n tmpvar_17.x = texsize.z;\n vec2 tmpvar_18;\n tmpvar_18.y = 0.0;\n tmpvar_18.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_17)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_18)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_19;\n tmpvar_19.x = 0.0;\n tmpvar_19.y = texsize.w;\n vec2 tmpvar_20;\n tmpvar_20.x = 0.0;\n tmpvar_20.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_19)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_20)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((1.0 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_21;\n tmpvar_21.y = 0.4;\n tmpvar_21.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_21);\n vec2 tmpvar_22;\n tmpvar_22.y = 0.0;\n tmpvar_22.x = texsize.z;\n vec2 tmpvar_23;\n tmpvar_23.y = 0.0;\n tmpvar_23.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_22)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_23)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_24;\n tmpvar_24.x = 0.0;\n tmpvar_24.y = texsize.w;\n vec2 tmpvar_25;\n tmpvar_25.x = 0.0;\n tmpvar_25.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_24)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_25)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n uv_1 = (uv_1 + xlat_mutabledz);\n vec2 tmpvar_26;\n tmpvar_26.x = q5;\n tmpvar_26.y = q6;\n xlat_mutableuv4 = (uv_1 - (0.4 * tmpvar_26));\n float tmpvar_27;\n tmpvar_27 = (0.1 * clamp ((1.0/(\n (abs(uv_1.y) + 0.1)\n )), 0.0, 12.0));\n vec2 tmpvar_28;\n tmpvar_28.x = (uv_1.x * tmpvar_27);\n tmpvar_28.y = tmpvar_27;\n vec3 tmpvar_29;\n tmpvar_29.xy = vec2(0.0, 0.0);\n tmpvar_29.z = clamp ((1.0 - (3.0 * uv_1.y)), 0.0, 1.0);\n ret_4 = (vec3(0.0, 0.1, 0.1) + (0.1 * tmpvar_29));\n ret_4 = (ret_4 + (vec3(dot (texture (sampler_noise_hq, \n (tmpvar_28 + (0.1 * time))\n ), vec4(0.32, 0.49, 0.29, 0.0))) * (\n (clamp ((1.0 - (12.0 * uv_1.y)), 0.0, 1.0) * 0.1)\n / \n (0.05 + sqrt(dot (xlat_mutableuv4, xlat_mutableuv4)))\n )));\n ret_4 = (ret_4 + ((0.4 * xlat_mutableret1) + (xlat_mutableret1 * q22)));\n vec4 tmpvar_30;\n tmpvar_30.w = 1.0;\n tmpvar_30.xyz = ret_4;\n ret = tmpvar_30.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:2,modwavealphabyvolume:1,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:20.944651,wave_smoothing:0,wave_mystery:.08,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:.99,ob_size:.015,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:1,textured:1,y:.47,rad:.24057,tex_zoom:.14057,g:.3,b:.5,g2:0,b2:.3,a2:1,border_b:0,border_a:0},init_eqs_str:"a.q24=0;",frame_eqs_str:"a.x=.5;a.y=.5;a.a=a.q24;a.a2=a.q24;"},{baseVals:{enabled:1,sides:100,additive:1,thickoutline:1,rad:.05134,tex_zoom:.12288,r:.3,g:.2,b:.2,a:.7,g2:0,border_r:0,border_g:.5,border_b:.5,border_a:0},init_eqs_str:"",frame_eqs_str:"a.r=.5+.3*Math.sin(a.time);a.g=.5+.3*Math.sin(div(a.time,1.5));a.b=.5+.3*Math.sin(div(a.time,3.7));a.r2=0;a.b2=0;a.g2=0;a.a=.05;a.a2=0;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:100,thick:1,scaling:.045052,smoothing:.1,a:.6},init_eqs_str:"a.k1=0;a.dy=0;a.dx=0;a.t2=0;a.q24=0;a.q27=0;",frame_eqs_str:"a.t2=.45+div(randint(10),100);",point_eqs_str:"a.k1=bnot(mod(100*a.sample+a.time,2));a.dy=.015*above(Math.sin(11*a.sample),0)+.008*above(Math.sin(a.time+74*a.sample),0)+.008*above(Math.sin(a.time+128*a.sample),0);a.dx=.01*above(Math.sin(27*a.sample),0)+.01*above(Math.sin(a.time+134*a.sample),0);a.x=.2*(a.sample-.5)+.5+a.dx;a.y=a.t2+a.dy;a.a=a.q24*a.k1*bnot(mod(a.q27,4));a.r=.6;a.g=0;a.b=.6;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.dec_xlow=0;a.index2=0;a.speed_=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.q9=0;a.movx=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q10=0;a.tilt_=0;a.q4=0;a.peakx=0;a.dir__=0;a.dir=0;a.dir_=0;a.movy=0;a.q26=0;a.maxp=0;a.p2=0;a.avg=0;a.trig=0;a.beat=0;a.p1=0;a.peak=0;a.tilt=0;a.q2=0;a.q27=0;a.speed=0;a.q3=0;a.t0=0;a.q7=0;a.q20=0;a.q8=0;a.xk=0;",frame_eqs_str:"a.dec_med=pow(.8,div(30,a.fps));a.dec_slow=pow(.95,div(30,a.fps));a.dec_xlow=pow(.995,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,16);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=\na.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att;a.q27=a.index+1;a.peakx=above(a.q22,1.5*a.maxp);a.maxp=Math.max(a.maxp,a.q22);a.maxp*=a.dec_xlow;a.k1=a.is_beat*equal(mod(a.index,3),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.trig=a.q24*bnot(mod(a.index,4));a.dir=a.dir+div(a.trig*a.q26*(div(randint(100),100)-.5),2)+a.peakx;a.dir_=a.dir_*a.dec_slow+a.dir*(1-a.dec_slow);\na.dir__=a.dir__*a.dec_slow+a.dir_*(1-a.dec_slow);a.q5=Math.cos(a.dir__);a.q6=Math.sin(a.dir__);a.speed=a.speed*bnot(a.trig)+div(a.trig*a.q26*5,a.fps);a.speed_=a.speed_*a.dec_slow+a.speed*(1-a.dec_slow);a.movx+=a.speed_*a.q6;a.movy+=a.speed_*a.q5;a.q7=a.movx;a.q8=a.movy;a.tilt=a.dir-a.dir__;a.tilt_=a.dec_slow*a.tilt_+(1-a.dec_slow)*a.tilt;a.monitor=a.maxp;a.q9=Math.cos(a.tilt_*a.speed_);a.q10=Math.sin(a.tilt_*a.speed_);a.q12=a.time;",pixel_eqs_str:"a.zoom=1.3;",warp:" shader_body { \n vec2 uv_1;\n vec2 uv6_2;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv - 0.5) * aspect.xy);\n float tmpvar_4;\n tmpvar_4 = ((2.0 * sqrt(\n dot (tmpvar_3, tmpvar_3)\n )) + (rand_frame * 64.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_4) / cos(tmpvar_4)) * normalize(tmpvar_3))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 20.0));\n uv6_2 = (0.4 * sin((tmpvar_3 * 22.0)));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (((q24 * \n (((texture (sampler_main, uv_1).xyz - (\n ((texture (sampler_blur1, fract(uv_1)).xyz * scale1) + bias1)\n * 0.04)) + (0.15 * (vec3(\n (0.1 / sqrt(dot (uv6_2, uv6_2)))\n ) * roam_cos.xyz))) - 0.02)\n ) * 0.98) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_5.xyz;\n }",comp:"vec3 xlat_mutableret1;\nvec2 xlat_mutablers;\n shader_body { \n vec2 uv1_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)].x = q9;\n tmpvar_2[uint(0)].y = -(q10);\n tmpvar_2[1u].x = q10;\n tmpvar_2[1u].y = q9;\n uv1_1 = (((uv_orig - 0.5) * aspect.xy) * tmpvar_2);\n uv1_1 = (uv1_1 * aspect.yx);\n float tmpvar_3;\n tmpvar_3 = (3.0 / abs(uv1_1.y));\n xlat_mutablers.x = (uv1_1.x * tmpvar_3);\n xlat_mutablers.y = (tmpvar_3 / 2.0);\n mat2 tmpvar_4;\n tmpvar_4[uint(0)].x = q5;\n tmpvar_4[uint(0)].y = -(q6);\n tmpvar_4[1u].x = q6;\n tmpvar_4[1u].y = q5;\n xlat_mutablers = (tmpvar_4 * xlat_mutablers);\n vec2 tmpvar_5;\n tmpvar_5.x = q7;\n tmpvar_5.y = q8;\n xlat_mutablers = (xlat_mutablers + tmpvar_5);\n xlat_mutableret1 = ((texture (sampler_blur1, fract(\n (xlat_mutablers / 12.0)\n )).xyz * scale1) + bias1);\n vec2 tmpvar_6;\n tmpvar_6.y = 0.0;\n tmpvar_6.x = q5;\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (((xlat_mutableret1 * 32.0) / tmpvar_3) + ((\n ((q22 * sqrt(tmpvar_3)) / 4.0)\n * \n sin(((uv1_1 - q12) * q27))\n .x) * texture (sampler_main, (\n (((4.0 * xlat_mutableret1) / tmpvar_3).xy + ((uv1_1 / 2.0) / (0.5 + abs(uv1_1.y))))\n + tmpvar_6)).xyz));\n ret = tmpvar_7.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.98,decay:.5,echo_zoom:.952,echo_alpha:.5,echo_orient:3,wave_mode:5,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.474,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:.8,wave_g:.49,ob_size:0,ob_a:.3,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b1x:.8,b1ed:0},shapes:[{baseVals:{enabled:1,sides:7,additive:1,num_inst:1024,rad:.04896,tex_ang:1.00531,tex_zoom:1.53117,r:0,g:1,b:1,a:0,g2:0,border_b:0,border_a:0},init_eqs_str:"a.max_age=0;a.n=0;a.x0=0;a.y0=0;a.z0=0;a.rad0=0;",frame_eqs_str:"a.max_age=a.reg00;a.n=12*a.instance;a.x0=a.gmegabuf[Math.floor(a.n)];a.y0=a.gmegabuf[Math.floor(a.n+1)];a.z0=a.gmegabuf[Math.floor(a.n+2)];.00001a.z0?1:0)?(a.rad=0,a.gmegabuf[Math.floor(a.n+8)]=a.max_age):(a.rad0=div(pow(1-div(a.gmegabuf[Math.floor(a.n+8)],a.max_age),.2),a.z0)*a.gmegabuf[Math.floor(a.n+7)]+.01,a.rad=.032*Math.abs(a.rad0),a.x=.5+div(a.x0,a.z0),a.y=.5+div(a.y0,a.z0));a.a=1;a.a2=.2;a.g=.8;a.g2=0;a.b=.2*(3a.z0?1:0);a.b2=0;\n"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:160,sep:20,usedots:1,additive:1,scaling:7.858,smoothing:.1,r:.2,g:.3,a:.6},init_eqs_str:"a.q32=0;",frame_eqs_str:"",point_eqs_str:"a.x=div(randint(100),100);a.y=.5-div(1-.7,a.q32)-.15*(div(randint(100),100)-.5);a.a=.15;a.r=0;a.b=1;a.g=0;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:'a.max_age=0;a.ind2=0;a.n=0;a.free=0;a.high=0;a.index=0;a.tht=0;a.v00=0;a.yobf=0;a.dt=0;a.y0=0;a.q1=0;a.dec_med=0;a.q5=0;a.ran1_=0;a["new"]=0;a.push=0;a.new1=0;a.is_beat=0;a.q24=0;a.vol_alt=0;a.dec_slow=0;a.ran2=0;a.ind1=0;a.q10=0;a.v0=0;a.med=0;a.beat=0;a.vol=0;a.peak=0;a.dec_fast=0;a.q27=0;a.bass1=0;a.q3=0;a.t0=0;a.vol_=0;a.dec=0;a.m=0;a.ran1=0;a.q32=0;a.phi=0;a.air=0;a.max_age=4.5;a.reg00=a.max_age;for(var b=a.n=0;12288>b;b++)a.gmegabuf[Math.floor(a.n)]=a.max_age-1+randint(2),\na.n+=1;a.q9=2*(randint(25)-10);a.q3=div(randint(100),100);a.q4=div(randint(100),100);',frame_eqs_str:'a.dec_fast=1-div(8.8,a.fps);a.dec_med=1-div(6,a.fps);a.dec_slow=1-div(1.6,a.fps);a.vol=div(a.bass+a.med+a.treb,3);a.vol_=a.vol_*a.dec_slow+(1-a.dec_slow)*a.vol;a.beat=a.vol;a.is_beat=above(a.beat,1+4*a.peak)*above(a.time,a.t0+.2);a.t0=.00001b;b++)a.megabuf[Math.floor(a.n)]=a.gmegabuf[Math.floor(a.n)],a.megabuf[Math.floor(a.n+1)]=a.gmegabuf[Math.floor(a.n+\n1)],a.megabuf[Math.floor(a.n+2)]=a.gmegabuf[Math.floor(a.n+2)],.00001a.max_age?1:0)?.00001=10*a.dt*bnot(a.high)?1:0,200>a["new"]?1:0))?(--a.free,a["new"]+=1,a.tht=div(randint(100),500)*(1+1.5*a.high),a.phi=randint(12),a.v0=a.v00*(1+div(randint(10),40)),a.gmegabuf[Math.floor(a.n)]=1.7*a.ran1,a.gmegabuf[Math.floor(a.n+1)]=a.y0+2.2*a.high,a.gmegabuf[Math.floor(a.n+2)]=2,a.gmegabuf[Math.floor(a.n+3)]=a.v0*Math.sin(a.tht)*Math.cos(a.phi),a.gmegabuf[Math.floor(a.n+\n4)]=a.v0*Math.cos(4*a.tht)*(1-1.5*a.high),a.gmegabuf[Math.floor(a.n+5)]=a.v0*Math.sin(a.tht)*Math.sin(a.phi)*1.5*a.vol,a.gmegabuf[Math.floor(a.n+7)]=0,a.gmegabuf[Math.floor(a.n+8)]=div(randint(100),100)):0:(--a.free,a.gmegabuf[Math.floor(a.n)]+=a.gmegabuf[Math.floor(a.n+3)]*a.dt,a.gmegabuf[Math.floor(a.n+1)]+=a.gmegabuf[Math.floor(a.n+4)]*a.dt,a.gmegabuf[Math.floor(a.n+2)]+=a.gmegabuf[Math.floor(a.n+5)]*a.dt,a.gmegabuf[Math.floor(a.n+3)]*=1-a.air,a.gmegabuf[Math.floor(a.n+4)]*=1-a.air,a.gmegabuf[Math.floor(a.n+\n4)]-=.8*a.dt,a.gmegabuf[Math.floor(a.n+5)]*=1-a.air,a.gmegabuf[Math.floor(a.n+7)]=(a.gmegabuf[Math.floor(a.n+1)]>a.yobf?1:0)*Math.min(1,18*(a.gmegabuf[Math.floor(a.n+1)]-a.yobf)),.00001a.gmegabuf[Math.floor(a.n+4)]?1:0))?a.gmegabuf[8]=a.max_age:0,a.gmegabuf[Math.floor(a.n+8)]+=a.dt),a.n+=12;for(b=a.n=0;512>b;b++)a.m=6132+a.n,a.gmegabuf[Math.floor(a.m)]=div(a.gmegabuf[Math.floor(a.n)]+a.megabuf[Math.floor(a.n)],2),a.gmegabuf[Math.floor(a.m+\n1)]=div(a.gmegabuf[Math.floor(a.n+1)]+a.megabuf[Math.floor(a.n+1)],2),a.gmegabuf[Math.floor(a.m+2)]=div(a.gmegabuf[Math.floor(a.n+2)]+a.megabuf[Math.floor(a.n+2)],2),a.gmegabuf[Math.floor(a.m+7)]=a.gmegabuf[Math.floor(a.n+7)],a.gmegabuf[Math.floor(a.m+8)]=a.gmegabuf[Math.floor(a.n+8)],a.n+=12;a.dec=.00001a.bass1?1:0)?.5:.9;a.bass1=a.bass1*a.dec+a.bass*(1-a.dec);a.q1=Math.min(1,Math.max(0,a.bass1-1.5)*Math.abs(a.q3-.5)*3);a.q10=Math.max(a.vol_-.1,.1);a.vol_alt=a.vol;a.q32=a.aspecty;\na.new1=.00001 0.5))))\n , 0.0, 1.0)));\n vec3 tmpvar_21;\n tmpvar_21.z = 0.0;\n tmpvar_21.xy = (((texture (sampler_blur3, uv_2).xyz * scale3) + bias3).xy * vec2(3.0, 5.0));\n ret_3 = (ret_3 + ((xlat_mutablesmoke * \n dot (tmpvar_21, vec3(0.32, 0.49, 0.29))\n ) * vec3(1.0, 0.84, 0.62)));\n float tmpvar_22;\n tmpvar_22 = clamp (((1.2 * \n clamp (texture (sampler_main, uv_2).y, 0.0, 1.0)\n ) - 0.2), 0.0, 1.0);\n vec3 tmpvar_23;\n tmpvar_23.x = tmpvar_22;\n tmpvar_23.y = (tmpvar_22 * tmpvar_22);\n tmpvar_23.z = pow (tmpvar_22, 8.0);\n vec3 tmpvar_24;\n tmpvar_24 = clamp ((tmpvar_23 / vec3(0.8, 0.8, 0.8)), 0.0, 1.0);\n ret_3 = (ret_3 + (tmpvar_24 * (tmpvar_24 * \n (3.0 - (2.0 * tmpvar_24))\n )));\n float tmpvar_25;\n tmpvar_25 = clamp (0.52, 0.0, 1.0);\n vec3 tmpvar_26;\n tmpvar_26.x = tmpvar_25;\n tmpvar_26.y = (tmpvar_25 * tmpvar_25);\n tmpvar_26.z = pow (tmpvar_25, 8.0);\n vec3 tmpvar_27;\n tmpvar_27 = clamp ((tmpvar_26 / vec3(0.8, 0.8, 0.8)), 0.0, 1.0);\n vec3 tmpvar_28;\n tmpvar_28 = mix (clamp (ret_3, 0.0, 1.0), (tmpvar_27 * (tmpvar_27 * \n (3.0 - (2.0 * tmpvar_27))\n )), vec3((pow (\n ((1.0 - uv_2.y) - ((uv_2.x - 0.5) * (q3 - 0.5)))\n , 4.0) * q1)));\n ret_3 = tmpvar_28;\n vec4 tmpvar_29;\n tmpvar_29.w = 1.0;\n tmpvar_29.xyz = tmpvar_28;\n ret = tmpvar_29.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:.698,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,ob_size:0,ob_g:.1,ob_b:1,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,mv_x:25.6,mv_y:9.6,mv_l:5,mv_g:.5,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.n=0;a.maxbpm=0;a.reg26=0;a.maxind1=0;a.uvx0=0;a.cosb_=0;a.reg34=0;a.num_res=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.sinb_=0;a.index=0;a.quali=0;a.v3=0;a.q18=0;a.q22=0;a.q21=0;a.diry=0;a.q6=0;a.posx=0;a.dt=0;a.reg25=0;a.mean=0;a.uvx=0;a.q1=0;a.posz=0;a.q5=0;a.reg52=0;a.dt1=0;a.dec_f=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.bt2=0;a.reg36=0;a.minbpm=0;a.reg22=0;a.uvy=0;a.rotz=0;a.cosb=0;a.omega=0;a.dist_=0;a.ec_steps=0;a.bpm=0;a.q23=0;a.q24=0;a.reg24=\n0;a.ran2=0;a.pi=0;a.q10=0;a.reg14=0;a.sinb=0;a.reg53=0;a.posy=0;a.reg31=0;a.dirx=0;a.dec_m=0;a.q4=0;a.start=0;a.reg12=0;a.reg13=0;a.v2p=0;a.c2=0;a.reg37=0;a.ex=0;a.s3=0;a.yslope=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.v3p=0;a.reg35=0;a.p2=0;a.mov=0;a.reg11=0;a.tx=0;a.avg=0;a.bt1=0;a.beatsin=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.q17=0;a.vol=0;a.reg32=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.beatcos=0;a.reg30=0;a.q2=0;a.b1y=0;a.q27=0;a.bri=0;a.slen=0;a.q14=0;a.dist=0;a.trel1=0;a.p3=0;a.reg17=\n0;a.v1=0;a.speed=0;a.vol2=0;a.q3=0;a.s1=0;a.vol_=0;a.dec=0;a.s2=0;a.quad=0;a.b2y=0;a.ran1=0;a.q32=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.ty=0;a.excite=0;a.c1=0;a.v2=0;a.q20=0;a.p4=0;a.q8=0;a.maxvol=0;for(var b=a.n=0;2E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;a.minbpm=30;a.maxbpm=230;a.num_res=100;for(b=a.index=0;bc;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:\n.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);",frame_eqs_str:"a.dt=Math.min(div(1,a.fps),.1);a.dec_f=.8;a.dec_m=1-4*a.dt;a.dec_s=1-a.dt;a.vol=div(a.bass+div(a.mid,2)+a.treb,3);a.vol_=a.vol_*a.dec_m+(1-a.dec_m)*a.vol;a.dec=a.dec_s;a.vol2=a.vol2*a.dec+(1-a.dec)*Math.min(3,a.vol);a.maxvol=.00001a.maxvol?1:0)?a.vol:a.maxvol*a.dec_s;a.excite=a.vol-a.vol_;a.index=0;a.maxind1=0;for(var b=a.mean=0;ba.gmegabuf[Math.floor(12*a.maxind1+3)]?1:0)?a.maxind1=a.index:0;a.index+=1}a.quali=div(a.gmegabuf[Math.floor(12*a.maxind1+3)],a.mean);a.bpm=a.minbpm*pow(div(a.maxbpm,a.minbpm),div(a.maxind1,a.num_res));.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=\n-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+\na.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var d;c=0;do{c+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*\na.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=1+2*(div(a.uvx,4)+30.5-Math.floor(div(a.uvx,4)+30.5)-.5);a.uvy=2+2*(div(a.uvy,4)+30.5-Math.floor(div(a.uvy,4)+30.5)-.5);a.uvz=3+2*(div(a.uvz,4)+30.5-Math.floor(div(a.uvz,4)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(d=0;8>d;d++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?\n1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*\na.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;d=(.6>a.dist?1:0)*(30c);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(8*(a.megabuf[1]-a.megabuf[3]),-2),2);a.yslope=Math.min(Math.max(8*(a.megabuf[4]-a.megabuf[2]),-2),2);a.dist_=a.dist_*a.dec_m+(1-a.dec_m)*a.dist;\na.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+div(1,255)+0*a.start;a.start*=.9;a.reg52=-a.v2;a.reg53=a.v3;a.warp=0;a.zoom=1;a.rot=a.v1;a.sinb=Math.sin(a.trel1);a.cosb=Math.cos(a.trel1);a.bt1=0>a.sinb*a.sinb_?1:0;a.bt2=0>a.cosb*a.cosb_?1:0;.00001 0.16)) {\n vec4 nb2_8;\n vec4 nb_9;\n vec4 tmpvar_10;\n tmpvar_10 = texture (sampler_pw_main, (uv_3 + vec2(-(pix))));\n nb_9.x = (1.0 - (tmpvar_10.z + (0.003921569 * tmpvar_10.y)));\n vec4 tmpvar_11;\n tmpvar_11 = texture (sampler_pw_main, (uv_3 + (pix * vec2(1.0, -1.0))));\n nb_9.y = (1.0 - (tmpvar_11.z + (0.003921569 * tmpvar_11.y)));\n vec4 tmpvar_12;\n tmpvar_12 = texture (sampler_pw_main, (uv_3 + vec2(pix)));\n nb_9.z = (1.0 - (tmpvar_12.z + (0.003921569 * tmpvar_12.y)));\n vec4 tmpvar_13;\n tmpvar_13 = texture (sampler_pw_main, (uv_3 + (pix * vec2(-1.0, 1.0))));\n nb_9.w = (1.0 - (tmpvar_13.z + (0.003921569 * tmpvar_13.y)));\n vec4 tmpvar_14;\n tmpvar_14 = texture (sampler_pw_main, (uv_3 + (pix * vec2(0.0, -1.0))));\n nb2_8.x = (1.0 - (tmpvar_14.z + (0.003921569 * tmpvar_14.y)));\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pw_main, (uv_3 + (pix * vec2(1.0, 0.0))));\n nb2_8.y = (1.0 - (tmpvar_15.z + (0.003921569 * tmpvar_15.y)));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pw_main, (uv_3 + (pix * vec2(0.0, 1.0))));\n nb2_8.z = (1.0 - (tmpvar_16.z + (0.003921569 * tmpvar_16.y)));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pw_main, (uv_3 + (pix * vec2(-1.0, 0.0))));\n nb2_8.w = (1.0 - (tmpvar_17.z + (0.003921569 * tmpvar_17.y)));\n vec4 tmpvar_18;\n tmpvar_18 = min (nb_9, nb2_8);\n nb_9.zw = tmpvar_18.zw;\n nb_9.xy = min (tmpvar_18.xy, tmpvar_18.zw);\n xlat_mutabledist = ((min (nb_9.x, nb_9.y) + (\n (0.006 * (tmpvar_7.xyz - 0.5).x)\n * tmpvar_7.y)) - (q10 * 0.5));\n };\n float theta_19;\n theta_19 = (xlat_mutabledist * 1.35);\n float theta_20;\n theta_20 = (xlat_mutabledist * 1.35);\n vec3 tmpvar_21;\n tmpvar_21.xy = (xlat_mutableuv1 * ((\n sin(theta_19)\n / \n cos(theta_19)\n ) / 1.35));\n tmpvar_21.z = ((sin(theta_20) / cos(theta_20)) / 1.35);\n xlat_mutableuv2 = (((tmpvar_21 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = (((\n fract(((xlat_mutableuv2 / 4.0) + 0.5))\n - 0.5) * 2.0) + vec3(1.0, 2.0, 3.0));\n vec3 zz0_23;\n vec3 zz_24;\n zz_24 = xlat_mutableuv2;\n zz0_23 = (xlat_mutableuv2 + q8);\n for (int n_22 = 0; n_22 <= 8; n_22++) {\n zz_24 = ((2.0 * clamp (zz_24, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_24);\n zz_24 = (zz_24 * max ((1.0/(\n dot (zz_24, zz_24)\n )), 1.0));\n zz_24 = ((2.6 * zz_24) + zz0_23);\n };\n vec4 tmpvar_25;\n tmpvar_25.w = 0.0;\n tmpvar_25.xyz = zz_24;\n float tmpvar_26;\n tmpvar_26 = sqrt(dot (zz_24, zz_24));\n vec4 tmpvar_27;\n tmpvar_27.w = 0.0;\n tmpvar_27.xyz = mod1;\n xlat_mutablestruc = ((1.0 - (\n (1.4 * dot (tmpvar_25, tmpvar_27))\n / 40.0)) - (xlat_mutabledist * 0.3));\n if (((tmpvar_26 < 40.0) && (xlat_mutabledist > (0.04 * \n (1.0 - rad)\n )))) {\n ret_4.x = mix (xlat_mutablestruc, texture (sampler_main, uv_3).x, sustain);\n float x_28;\n x_28 = ((1.0 - xlat_mutabledist) * 255.0);\n float ip_29;\n ip_29 = float(int(x_28));\n vec2 tmpvar_30;\n tmpvar_30.x = (x_28 - ip_29);\n tmpvar_30.y = (ip_29 / 255.0);\n ret_4.yz = tmpvar_30;\n } else {\n ret_4 = ((texture (sampler_fc_main, uv_3) * sustain) - 0.003921569).xyz;\n };\n vec4 tmpvar_31;\n tmpvar_31.w = 1.0;\n tmpvar_31.xyz = ret_4;\n ret = tmpvar_31.xyz;\n }",comp:"float xlat_mutablecross1;\nvec2 xlat_mutabledz1;\nfloat xlat_mutablerdist;\nvec2 xlat_mutableuv0;\nvec2 xlat_mutableuv4;\nvec2 xlat_mutableuva;\nvec2 xlat_mutableuvb;\n shader_body { \n vec2 tmpvar_1;\n tmpvar_1.x = q1;\n tmpvar_1.y = q2;\n vec2 tmpvar_2;\n tmpvar_2.x = q17;\n tmpvar_2.y = q18;\n vec2 uv_3;\n vec3 ret_4;\n uv_3 = (uv + (texsize.zw / 2.0));\n xlat_mutableuv0 = uv_3;\n vec2 uvi_5;\n uvi_5 = (uv_3 + vec2(0.002, 0.0));\n float tmpvar_6;\n tmpvar_6 = mix (((texture (sampler_blur1, uvi_5).xyz * scale1) + bias1).x, texture (sampler_main, uvi_5).x, 0.1);\n vec2 uvi_7;\n uvi_7 = (uv_3 - vec2(0.002, 0.0));\n float tmpvar_8;\n tmpvar_8 = mix (((texture (sampler_blur1, uvi_7).xyz * scale1) + bias1).x, texture (sampler_main, uvi_7).x, 0.1);\n xlat_mutabledz1.x = ((tmpvar_6 * float(\n (tmpvar_6 > 0.02)\n )) - (tmpvar_8 * float(\n (tmpvar_8 > 0.02)\n )));\n vec2 uvi_9;\n uvi_9 = (uv_3 + vec2(0.0, 0.002));\n float tmpvar_10;\n tmpvar_10 = mix (((texture (sampler_blur1, uvi_9).xyz * scale1) + bias1).x, texture (sampler_main, uvi_9).x, 0.1);\n vec2 uvi_11;\n uvi_11 = (uv_3 - vec2(0.0, 0.002));\n float tmpvar_12;\n tmpvar_12 = mix (((texture (sampler_blur1, uvi_11).xyz * scale1) + bias1).x, texture (sampler_main, uvi_11).x, 0.1);\n xlat_mutabledz1.y = ((tmpvar_10 * float(\n (tmpvar_10 > 0.02)\n )) - (tmpvar_12 * float(\n (tmpvar_12 > 0.02)\n )));\n uv_3 = (uv_3 + (xlat_mutabledz1 * 0.26));\n xlat_mutablerdist = ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1).z;\n vec4 tmpvar_13;\n tmpvar_13.w = 0.0;\n tmpvar_13.xyz = texture (sampler_noise_hq, vec2(((xlat_mutablerdist * 0.05) + (time * 0.02)))).xyz;\n vec4 tmpvar_14;\n tmpvar_14 = mix (tmpvar_13, roam_sin, vec4(0.5, 0.5, 0.5, 0.5));\n xlat_mutableuv4 = (uv_3 - 0.4);\n xlat_mutableuva = ((xlat_mutableuv4 - tmpvar_1) - ((\n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n .x * 0.4) * float(\n (xlat_mutablerdist > 0.2)\n )));\n xlat_mutableuvb = ((xlat_mutableuv4 - tmpvar_2) - ((\n (texture (sampler_blur1, uv_3).xyz * scale1)\n + bias1).x * 0.4));\n float angle_15;\n float tmpvar_16;\n tmpvar_16 = abs(xlat_mutableuva.x);\n if ((xlat_mutableuva.y >= 0.0)) {\n angle_15 = (1.0 - ((xlat_mutableuva.y - tmpvar_16) / (xlat_mutableuva.y + tmpvar_16)));\n } else {\n angle_15 = (3.0 - ((xlat_mutableuva.y + tmpvar_16) / (tmpvar_16 - xlat_mutableuva.y)));\n };\n float tmpvar_17;\n if ((xlat_mutableuva.x < 0.0)) {\n tmpvar_17 = -(angle_15);\n } else {\n tmpvar_17 = angle_15;\n };\n xlat_mutablecross1 = ((pow (\n sin((3.141593 * (tmpvar_17 + (5.1 * q20))))\n , 1.5) + (xlat_mutablerdist / 2.0)) + 0.1);\n vec3 tmpvar_18;\n tmpvar_18 = vec3((((1.0/(\n dot (xlat_mutableuva, xlat_mutableuva)\n )) / xlat_mutablecross1) * q3));\n vec3 tmpvar_19;\n tmpvar_19 = vec3(((1.0/(dot (xlat_mutableuvb, xlat_mutableuvb))) * q19));\n ret_4 = (clamp ((1.0 - \n (2.0 * xlat_mutablerdist)\n ), 0.0, 1.0) * ((\n (tmpvar_18 * tmpvar_14.xyz)\n + \n (tmpvar_19 * (1.0 - tmpvar_14.xyz))\n ) + 0.1));\n ret_4 = (ret_4 + (clamp (\n (2.0 * xlat_mutablerdist)\n , 0.0, 1.0) * (\n (tmpvar_18 * tmpvar_14.zyx)\n + \n (tmpvar_19 * (1.0 - tmpvar_14.zyx))\n )));\n ret_4 = (ret_4 + ((\n (texture (sampler_blur1, xlat_mutableuv0).xyz * scale1)\n + bias1).x * 0.05));\n ret_4 = (1.0 - exp(-(ret_4)));\n vec4 tmpvar_20;\n tmpvar_20.w = 1.0;\n tmpvar_20.xyz = ret_4;\n ret = tmpvar_20.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:2,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:5,wave_dots:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:1.169162,wave_smoothing:0,wave_mystery:.08,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:.99,ob_size:.015,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:0,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b2x:.3,b1ed:0},shapes:[{baseVals:{enabled:1,sides:53,rad:.05408,tex_ang:1.00531,tex_zoom:1.531168,r:.2,g:.7,g2:0,a2:1,border_b:0,border_a:0},init_eqs_str:"a.q24=0;a.rad0=0;",frame_eqs_str:"a.x=.5;a.y=.5;a.a=a.q24;a.a2=0;a.a=0;a.rad0=bnot(a.q24)*a.rad0+div(randint(10),50)*a.q24;a.rad=a.rad0;a.b=0;a.r=div(randint(10),10);a.g=1;a.a2=a.q24;"},{baseVals:{enabled:1,sides:44,textured:1,x:.7,rad:.2173,tex_zoom:3.277448,g:1,b:.5,r2:1,b2:1,a2:1,border_r:.5,border_g:.5,border_b:0},init_eqs_str:"a.rot0=0;a.q1=0;a.posx=0;a.q24=0;a.posy=0;a.rad0=0;",frame_eqs_str:"a.textured=1;a.rot0+=div(1,a.fps)*a.q1;a.posx=(1-a.q24)*a.posx+a.q24*(.3+div(randint(100),200));a.posy=(1-a.q24)*a.posy+a.q24*(.3+div(randint(100),200));a.rad0=(1-a.q24)*a.rad0+a.q24*(.05+div(randint(100),300));a.rad=a.rad0;a.x=a.posx;a.y=a.posy;a.ang=a.rot0;"},{baseVals:{enabled:1,sides:63,x:.503,rad:.038857,tex_zoom:2.2233,g:.1,r2:1,b2:1,a2:.7,border_a:0},init_eqs_str:"a.rot0=0;a.q2=0;a.posx=0;a.q24=0;a.posy=0;a.rad0=0;a.q26=0;",frame_eqs_str:"a.textured=1;a.rot0+=div(.1,a.fps)*a.q2;a.posx=(1-a.q24)*a.posx+a.q24*(.3+div(randint(100),200));a.posy=(1-a.q24)*a.posy+a.q24*(.3+div(randint(100),200));a.rad0=(1-a.q24)*a.rad0+a.q24*(.05+div(randint(100),400));a.rad=a.rad0;a.x=a.posx+a.q26;a.y=a.posy;a.ang=a.rot0;"},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.q25=0;a.index=0;a.q22=0;a.q21=0;a.q29=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.t_rel=0;a.dec_slow=0;a.q10=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q7=0;a.ds=0;a.q28=0;a.q30=0;a.q20=0;a.p4=0;a.q8=0;",frame_eqs_str:"a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.beat=a.bass+a.mid+a.treb;a.beat*=a.beat;a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2*a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;\na.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att+3;a.q27=a.index+1;a.q28=a.index2;a.q29=a.index2;a.monitor=a.q29;a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.q5=Math.cos(div(a.time,17));a.q6=Math.sin(div(a.time,17));a.q7=-a.q2;a.q8=a.q1;a.ds=a.ds*a.dec_med+a.q24*(1-a.dec_med);a.q25=a.q24;a.q10=a.q22+3;a.t_rel=8*a.time;a.p3=\na.p3*a.dec_med+(1-a.dec_med)*(100*a.index+0*a.q26);a.q30=a.p3;a.p4=a.dec_med*a.p4+(1-a.dec_med)*a.q27;a.q31=a.p4;a.zoom=1.1+.2*a.q1;a.warp=0;a.ob_size=.01;a.ob_r=.9;a.ob_g=1;a.ob_b=0;a.ob_a=.2*Math.sin(div(a.time,7));",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec2 uv_1;\n vec2 tmpvar_2;\n tmpvar_2 = ((uv - 0.5) * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = (sqrt(dot (tmpvar_2, tmpvar_2)) + (rand_frame * 13.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_3) / cos(tmpvar_3)) / normalize(tmpvar_2))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 16.0));\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = ((q24 * (\n ((texture (sampler_main, uv_1).xyz + ((0.1 * vec3(\n ((q1 * cos((uv_1.x * 44.0))) - cos((uv_1.y * 82.0)))\n )) * (1.0 + texture (sampler_noise_lq, \n ((uv_1 / 16.0) + (time / 100.0))\n )).xyz)) * 0.98)\n - 0.025)) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_4.xyz;\n }",comp:"vec2 xlat_mutabledz;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\n shader_body { \n vec2 uv2_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n xlat_mutabledz.x = dot ((texture (sampler_main, (uv + tmpvar_2)).xyz - texture (sampler_main, (uv - tmpvar_2)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledz.y = dot ((texture (sampler_main, (uv + tmpvar_3)).xyz - texture (sampler_main, (uv - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n uv2_1 = (uv - 0.5);\n vec2 tmpvar_4;\n tmpvar_4.y = 0.0;\n float tmpvar_5;\n tmpvar_5 = (time / 8.0);\n tmpvar_4.x = tmpvar_5;\n float tmpvar_6;\n tmpvar_6 = (q27 * 2.0);\n xlat_mutableuv3 = (((tmpvar_6 * uv2_1) * 0.1) + tmpvar_4);\n xlat_mutableuv3 = (fract(xlat_mutableuv3) * aspect.yx);\n xlat_mutableuv3 = ((0.1 * cos(\n (22.0 * xlat_mutableuv3)\n )) + (18.0 * xlat_mutabledz));\n float tmpvar_7;\n tmpvar_7 = clamp ((0.02 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n vec4 tmpvar_8;\n tmpvar_8 = (1.0 + roam_cos);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_7)) + ((0.45 * \n dot (vec3(tmpvar_7), vec3(0.32, 0.49, 0.29))\n ) * tmpvar_8).xyz);\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * 1.252262));\n vec2 tmpvar_9;\n tmpvar_9.y = 0.0;\n tmpvar_9.x = tmpvar_5;\n xlat_mutableuv3 = (((tmpvar_6 * uv2_1) * 0.1) + tmpvar_9);\n xlat_mutableuv3 = (fract(xlat_mutableuv3) * aspect.yx);\n xlat_mutableuv3 = ((0.1 * cos(\n (22.0 * xlat_mutableuv3)\n )) + (18.0 * xlat_mutabledz));\n float tmpvar_10;\n tmpvar_10 = clamp ((0.02 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_10)) + ((0.45 * \n dot (vec3(tmpvar_10), vec3(0.32, 0.49, 0.29))\n ) * tmpvar_8).xyz);\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * 1.252262));\n vec4 tmpvar_11;\n tmpvar_11.w = 1.0;\n tmpvar_11.xyz = (xlat_mutableret1 + clamp ((\n (texture (sampler_main, uv).xyz * 4.0)\n * \n (0.2 + xlat_mutableret1)\n ), 0.0, 1.0));\n ret = tmpvar_11.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:6,wave_thick:1,modwavealphabyvolume:1,darken:1,wave_a:.001,wave_scale:.159809,wave_smoothing:.45,wave_mystery:.08,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,wave_y:.9,ob_r:1,ob_g:1,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b1x:.6999,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q7=0;a.q20=0;",frame_eqs_str:"a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=\na.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_slow*a.p2+(1-a.dec_slow)*a.p1;a.rott=div(3.1416*a.p2,4);a.q27=a.index+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1;a.rot=-0*a.index;a.q32=pow(.996,div(30,a.fps));a.q5=div(Math.sin(div(a.time,11))+1,5);a.movez+=div(.06,a.fps)*(1.1+a.q1);a.q6=a.movez;a.q7=.005*Math.sin(div(a.time,15));",pixel_eqs_str:"",pixel_eqs:"",warp:"vec3 xlat_mutablenoise;\nvec2 xlat_mutablers;\nvec2 xlat_mutablers0;\nvec2 xlat_mutableuv1;\n shader_body { \n vec3 copy_1;\n vec2 tmpvar_2;\n tmpvar_2.x = 0.5;\n tmpvar_2.y = q5;\n xlat_mutableuv1 = (uv - tmpvar_2);\n float tmpvar_3;\n tmpvar_3 = (1.0/(xlat_mutableuv1.y));\n xlat_mutablers0.x = (xlat_mutableuv1.x * tmpvar_3);\n xlat_mutablers0.y = tmpvar_3;\n xlat_mutablers.x = xlat_mutablers0.x;\n xlat_mutablers.y = (tmpvar_3 + (time * 0.3));\n xlat_mutablenoise = (vec3(dot (texture (sampler_pw_noise_lq, (xlat_mutablers / 63.0)), vec4(0.32, 0.49, 0.29, 0.0))) * (dot (texture (sampler_pw_noise_lq, \n (xlat_mutablers / 12.0)\n ), vec4(0.32, 0.49, 0.29, 0.0)) + 0.5));\n xlat_mutablenoise = (xlat_mutablenoise * (clamp (\n ((10.0 * xlat_mutablenoise) - 8.0)\n , 0.0, 1.0) * clamp (\n (2.0 / tmpvar_3)\n , 0.0, 1.0)));\n vec2 tmpvar_4;\n tmpvar_4.x = uv.x;\n tmpvar_4.y = (uv.y - (0.024 / tmpvar_3));\n vec2 tmpvar_5;\n tmpvar_5.x = uv.x;\n tmpvar_5.y = (uv.y - (0.012 / tmpvar_3));\n copy_1 = (texture (sampler_main, tmpvar_4).xyz + texture (sampler_main, tmpvar_5).xyz);\n vec2 tmpvar_6;\n tmpvar_6.x = uv.x;\n tmpvar_6.y = (uv.y - (0.006 / tmpvar_3));\n copy_1 = (copy_1 + texture (sampler_main, tmpvar_6).xyz);\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = ((xlat_mutablenoise + (\n (((copy_1 / 3.0) * (1.0 + slow_roam_cos).xyz) / 2.0)\n * 0.99)) - 0.005);\n ret = tmpvar_7.xyz;\n }",comp:"vec3 xlat_mutablecont;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers2;\n shader_body { \n vec2 uv_1;\n float inten_2;\n float dist_3;\n uv_1 = (uv - 0.5);\n uv_1 = (uv_1 * aspect.xy);\n dist_3 = (1.0 - fract(q6));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_4;\n tmpvar_4 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_4).xyz;\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (vec3(0.0, 0.0, 0.0), ((\n -(texture (sampler_main, tmpvar_4).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_4 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n dist_3 = (1.0 - fract((0.5 + q6)));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_5;\n tmpvar_5 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_5).xyz;\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (xlat_mutablecont, ((\n -(texture (sampler_main, tmpvar_5).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_5 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n dist_3 = (1.0 - fract((1.0 + q6)));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_6;\n tmpvar_6 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_6).xyz;\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (xlat_mutablecont, ((\n -(texture (sampler_main, tmpvar_6).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_6 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n vec2 tmpvar_7;\n tmpvar_7.y = 5.0;\n tmpvar_7.x = (time / 12.0);\n xlat_mutablers2 = ((0.1 * cos(\n ((uv_1 * 3.0) + tmpvar_7)\n )) + (0.1 * xlat_mutableret1).xy);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = (((-0.1 * xlat_mutableret1) + (\n (clamp ((0.005 / sqrt(\n dot (xlat_mutablers2, xlat_mutablers2)\n )), 0.0, 1.0) * vec3(18.0, 16.2, 10.8))\n * \n (0.2 + (0.3 * xlat_mutableret1))\n )) + ((\n dot (xlat_mutablecont, vec3(0.32, 0.49, 0.29))\n * \n (1.0 + slow_roam_cos)\n ) / 2.0).xyz);\n ret = tmpvar_8.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:6,wave_dots:1,modwavealphabyvolume:1,darken:1,wave_a:.001,wave_scale:1.740724,wave_smoothing:.45,wave_mystery:.08,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_g:.99,ob_size:0,ob_r:1,ob_b:1,ob_a:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.t_rel=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q7=0;a.q28=0;a.q30=0;a.q20=0;a.q8=0;a.p3=0;a.t_rel=0;",frame_eqs_str:"a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),4);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.monitor=a.index4;\na.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att+1;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.p3=a.dec_med*a.p3+(1-a.dec_med)*a.p2;a.rott=div(3.14159265359*a.p3,2);a.q27=8-a.index;a.q28=a.index2+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.t_rel+=div(.6,a.fps)*a.q1*a.q1;a.q5=Math.cos(a.t_rel);a.q6=Math.sin(a.t_rel);a.q7=-a.q6;a.q8=a.q5;a.movez+=div(div(.6,\na.fps),(1.4-a.q5)*(1.4-a.q5));a.q30=a.movez;a.zoom=1;",pixel_eqs_str:"a.dx=div(0*a.q28,8);",warp:"vec3 xlat_mutablenoise;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers;\n shader_body { \n float z_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)] = _qb.xy;\n tmpvar_2[1u] = _qb.zw;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv * tmpvar_2) - 0.5);\n float tmpvar_4;\n tmpvar_4 = (0.4 / abs(tmpvar_3.y));\n xlat_mutablers.x = (tmpvar_3.x * tmpvar_4);\n xlat_mutablers.y = (tmpvar_4 + q30);\n vec4 tmpvar_5;\n tmpvar_5 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_5.xyz * vec3(greaterThanEqual (tmpvar_5.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutablenoise = (xlat_mutablenoise * (1.0 + (0.5 * \n (dot (texture (sampler_noise_hq, (16.0 * xlat_mutablers)), vec4(0.32, 0.49, 0.29, 0.0)) - 0.5)\n )));\n xlat_mutableret1 = xlat_mutablenoise;\n z_1 = (1.2 / abs(tmpvar_3.y));\n xlat_mutablers.x = (tmpvar_3.x * z_1);\n xlat_mutablers.y = (z_1 + q30);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_6.xyz * vec3(greaterThanEqual (tmpvar_6.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n z_1 = (0.4 / abs(tmpvar_3.x));\n xlat_mutablers.y = (tmpvar_3.y * z_1);\n xlat_mutablers.x = (z_1 + q30);\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_7.xyz * vec3(greaterThanEqual (tmpvar_7.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutablenoise = (xlat_mutablenoise * (1.0 + (0.5 * \n (dot (texture (sampler_noise_hq, (16.0 * xlat_mutablers)), vec4(0.32, 0.49, 0.29, 0.0)) - 0.5)\n )));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n z_1 = (1.2 / abs(tmpvar_3.x));\n xlat_mutablers.y = (tmpvar_3.y * z_1);\n xlat_mutablers.x = (z_1 + q30);\n vec4 tmpvar_8;\n tmpvar_8 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_8.xyz * vec3(greaterThanEqual (tmpvar_8.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = xlat_mutableret1;\n ret = tmpvar_9.xyz;\n }",comp:"uniform sampler2D sampler_clouds2;\n shader_body { \n vec2 uv_1;\n vec2 uv1_2;\n uv_1 = (uv * aspect.xy);\n vec2 tmpvar_3;\n tmpvar_3.y = 0.0;\n tmpvar_3.x = texsize.z;\n vec2 tmpvar_4;\n tmpvar_4.x = 0.0;\n tmpvar_4.y = texsize.w;\n vec2 tmpvar_5;\n tmpvar_5.x = (dot (texture (sampler_main, (uv_1 - tmpvar_3)).xyz, vec3(0.32, 0.49, 0.29)) - dot (texture (sampler_main, (uv_1 + tmpvar_3)).xyz, vec3(0.32, 0.49, 0.29)));\n tmpvar_5.y = (dot (texture (sampler_main, (uv_1 - tmpvar_4)).xyz, vec3(0.32, 0.49, 0.29)) - dot (texture (sampler_main, (uv_1 + tmpvar_4)).xyz, vec3(0.32, 0.49, 0.29)));\n uv1_2 = ((0.3 * sin(\n ((uv_1 + (0.02 * time)) * 6.0)\n )) + (0.2 * tmpvar_5));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_clouds2, (uv_orig + tmpvar_5));\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (((-2.0 * \n (0.1 * texture (sampler_main, uv_1))\n .xyz) + (\n clamp (((0.004 * q26) / sqrt(dot (uv1_2, uv1_2))), 0.0, 1.0)\n * vec3(1.0, 0.8, 0.4))) + (0.4 * (tmpvar_6.xyz + \n (dot (tmpvar_6.xyz, vec3(0.32, 0.49, 0.29)) - 0.7)\n )));\n ret = tmpvar_7.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.780001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:5,wave_dots:1,wave_thick:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:5.552,wave_smoothing:.504,wave_mystery:-1,modwavealphastart:.71,modwavealphaend:1.3,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_g:0,wave_b:0,ob_size:.06,ob_r:1,ob_g:1,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b1x:.6999,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:1,sides:5,additive:1,x:.9,rad:.22613,g:.6,g2:0,border_a:0},init_eqs_str:"",frame_eqs_str:"a.x=.05+div(randint(900),1E3);a.y=.05+div(randint(900),1E3);a.ang=div(randint(320),100);"},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.ready=0;a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.sp0=0;a.q29=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.go=0;a.q4=0;a.is_beat2=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.q19=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q28=0;a.q30=0;a.q20=0;a.index4=randint(2);a.index3=randint(4);",frame_eqs_str:"a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,4);a.index2=mod(a.index2+a.is_beat*bnot(a.index),4);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),4);a.index4=mod(a.index4+\na.is_beat*bnot(a.index)*bnot(a.index2)*bnot(a.index3),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.ready=a.is_beat*bnot(a.ready)+bnot(a.is_beat2)*a.ready;a.is_beat2=a.ready*above(a.time,a.t0+.2);a.q19=a.is_beat2;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265359*a.p2,2);a.q27=a.index+1;a.q28=a.index2+1;a.q29=4*a.index3+1;a.q30=a.index4;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);\na.q3=-a.q2;a.q4=a.q1;a.sp0=a.dec_slow*a.sp0+(a.q24+.05)*(1-a.dec_slow);a.go=a.go*a.dec_med+(1-a.dec_med)*(1-bnot(a.index2+a.index3));a.movez+=div(.015*30,a.fps)*a.go;a.q31=a.movez;a.q32=.5+.02*Math.sin(div(a.time,5));a.q5=mod(a.index4,2);a.zoom=1;a.rot=0;a.dx=.05*Math.max(Math.sin(div(a.time,9.7))-.95,0);a.dy=.002*(1-a.go);a.rot=50*(a.dx-a.dy);",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec2 tmpvar_1;\n tmpvar_1 = ((uv * texsize.xy) * 0.03);\n vec2 tmpvar_2;\n tmpvar_2.x = (cos((tmpvar_1.y * q1)) * sin(-(tmpvar_1.y)));\n tmpvar_2.y = (sin(tmpvar_1.x) * cos((tmpvar_1.y * q2)));\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = ((texture (sampler_main, (uv - \n ((tmpvar_2 * texsize.zw) * 18.0)\n )).xyz * 0.99) - 0.01);\n ret = tmpvar_3.xyz;\n }",comp:" shader_body { \n vec2 uv1_1;\n vec3 tmpvar_2;\n tmpvar_2 = texture (sampler_main, uv).xyz;\n vec2 tmpvar_3;\n tmpvar_3.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_3.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_1 = ((0.3 * cos(\n ((uv - 0.5) + 1.8)\n )) - (2.0 * tmpvar_3));\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = (0.8 * ((0.3 * \n dot (tmpvar_2, vec3(0.32, 0.49, 0.29))\n ) + (\n (22.0 * clamp ((0.01 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0))\n * \n (tmpvar_2 + 0.1)\n )));\n ret = tmpvar_4.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:3,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,wrap:0,darken:1,wave_a:.001,wave_scale:.958,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,ob_size:.05,ob_g:.1,ob_b:1,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,mv_x:25.6,mv_y:9.6,mv_l:0,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.look=0;a.n=0;a.reg26=0;a.uvx0=0;a.reg34=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.q12=0;a.v3=0;a.q22=0;a.q21=0;a.diry=0;a.q13=0;a.q6=0;a.posx=0;a.fps_=0;a.reg25=0;a.uvx=0;a.q1=0;a.travel=0;a.posz=0;a.q5=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.slow=0;a.reg36=0;a.reg22=0;a.uvy=0;a.rotz=0;a.ly=0;a.dist_=0;a.q23=0;a.q24=0;a.reg24=0;a.cran0=0;a.ran2=0;a.q11=0;a.q10=0;a.reg14=0;a.posy=0;a.reg31=0;a.dirx=0;a.q4=0;a.start=0;a.reg12=0;a.reg13=0;a.c2=0;a.reg37=\n0;a.s3=0;a.yslope=0;a.lampy=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.reg35=0;a.reg11=0;a.tx=0;a.avg=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.beat=0;a.reg32=0;a.lx=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.reg30=0;a.q2=0;a.q27=0;a.slen=0;a.q14=0;a.dist=0;a.reg17=0;a.v1=0;a.speed=0;a.s1=0;a.t0=0;a.s2=0;a.ran1=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.lampx=0;a.ty=0;a.c1=0;a.v2=0;a.q20=0;a.q8=0;a.avg=.01;a.q7=.25;a.q8=randint(2)-1;a.q16=1+randint(2);a.q18=randint(.8)+.1;a.q30=1;a.q31=128;a.start=1;a.travel=\n0;a.rotz=0;a.look=0;a.slow=0;a.t0=a.time+3;a.lampx=.5;a.lampy=.5;a.cran0=randint(1);for(var b=a.n=0;1E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30\nd);d=.06>a.dist?1:0}while(.00001b);",frame_eqs_str:"a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*\na.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;\na.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;\na.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?\n-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+\nMath.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;",pixel_eqs_str:"a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;",warp:"float sustain;\nfloat xlat_mutabledist;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (0.98 - q14);\n vec2 uv_3;\n vec3 ret_4;\n vec2 tmpvar_5;\n tmpvar_5 = (uv - 0.5);\n xlat_mutableuv1 = ((tmpvar_5 * aspect.xy) * q16);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pc_main, uv);\n uv_3 = ((tmpvar_5 * (1.0 - \n (q10 / (1.0 - ((tmpvar_6.z + \n (0.003921569 * tmpvar_6.y)\n ) + (q10 * 0.7))))\n )) + 0.5);\n vec4 tmpvar_7;\n tmpvar_7 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n xlat_mutabledist = tmpvar_7.x;\n if ((tmpvar_7.y > 0.2)) {\n vec3 tmpvar_8;\n tmpvar_8 = (tmpvar_7.xyz - vec3(0.4, 0.5, 0.5));\n vec2 uvi_9;\n uvi_9 = ((tmpvar_8.zy * 0.003) + uv_3);\n vec2 pix_10;\n vec4 nb2_11;\n vec4 nb_12;\n vec2 x_13;\n x_13 = (uvi_9 - 0.5);\n pix_10 = (texsize.zw * (1.0 + (\n sqrt(dot (x_13, x_13))\n * 8.0)));\n float tmpvar_14;\n tmpvar_14 = (q10 * 0.7);\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pc_main, (uvi_9 - pix_10));\n nb_12.x = (1.0 - ((tmpvar_15.z + \n (0.003921569 * tmpvar_15.y)\n ) + tmpvar_14));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, -1.0))));\n nb_12.y = (1.0 - ((tmpvar_16.z + \n (0.003921569 * tmpvar_16.y)\n ) + tmpvar_14));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pc_main, (uvi_9 + pix_10));\n nb_12.z = (1.0 - ((tmpvar_17.z + \n (0.003921569 * tmpvar_17.y)\n ) + tmpvar_14));\n vec4 tmpvar_18;\n tmpvar_18 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 1.0))));\n nb_12.w = (1.0 - ((tmpvar_18.z + \n (0.003921569 * tmpvar_18.y)\n ) + tmpvar_14));\n vec4 tmpvar_19;\n tmpvar_19 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, -1.0))));\n nb2_11.x = (1.0 - ((tmpvar_19.z + \n (0.003921569 * tmpvar_19.y)\n ) + tmpvar_14));\n vec4 tmpvar_20;\n tmpvar_20 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, 0.0))));\n nb2_11.y = (1.0 - ((tmpvar_20.z + \n (0.003921569 * tmpvar_20.y)\n ) + tmpvar_14));\n vec4 tmpvar_21;\n tmpvar_21 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, 1.0))));\n nb2_11.z = (1.0 - ((tmpvar_21.z + \n (0.003921569 * tmpvar_21.y)\n ) + tmpvar_14));\n vec4 tmpvar_22;\n tmpvar_22 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 0.0))));\n nb2_11.w = (1.0 - ((tmpvar_22.z + \n (0.003921569 * tmpvar_22.y)\n ) + tmpvar_14));\n vec4 tmpvar_23;\n tmpvar_23 = min (nb_12, nb2_11);\n nb_12.zw = tmpvar_23.zw;\n nb_12.xy = min (tmpvar_23.xy, tmpvar_23.zw);\n xlat_mutabledist = (min (nb_12.x, nb_12.y) + ((0.008 * tmpvar_8.x) * abs(tmpvar_8.y)));\n };\n vec4 tmpvar_24;\n tmpvar_24 = texture (sampler_pc_main, uv_3);\n float tmpvar_25;\n tmpvar_25 = min (xlat_mutabledist, (1.0 - (\n (tmpvar_24.z + (0.003921569 * tmpvar_24.y))\n + \n (q10 * 0.7)\n )));\n xlat_mutabledist = tmpvar_25;\n float tmpvar_26;\n tmpvar_26 = (tmpvar_25 + pow (tmpvar_25, 3.0));\n vec3 tmpvar_27;\n tmpvar_27.xy = (xlat_mutableuv1 * tmpvar_26);\n tmpvar_27.z = tmpvar_26;\n xlat_mutableuv2 = (((tmpvar_27 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n float li_28;\n vec3 zz0_29;\n vec3 zz_30;\n zz0_29 = (xlat_mutableuv2 + q8);\n li_28 = 0.0;\n zz_30 = ((2.0 * clamp (xlat_mutableuv2, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - xlat_mutableuv2);\n float tmpvar_31;\n tmpvar_31 = dot (zz_30, zz_30);\n if ((tmpvar_31 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_31 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_31);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_32;\n tmpvar_32 = dot (zz_30, zz_30);\n if ((tmpvar_32 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_32 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_32);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_33;\n tmpvar_33 = dot (zz_30, zz_30);\n if ((tmpvar_33 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_33 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_33);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_34;\n tmpvar_34 = dot (zz_30, zz_30);\n if ((tmpvar_34 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_34 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_34);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_35;\n tmpvar_35 = dot (zz_30, zz_30);\n if ((tmpvar_35 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_35 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_35);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_36;\n tmpvar_36 = dot (zz_30, zz_30);\n if ((tmpvar_36 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_36 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_36);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_37;\n tmpvar_37 = dot (zz_30, zz_30);\n if ((tmpvar_37 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_37 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_37);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_38;\n tmpvar_38 = dot (zz_30, zz_30);\n if ((tmpvar_38 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_38 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_38);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n vec4 tmpvar_39;\n tmpvar_39.xyz = zz_30;\n tmpvar_39.w = li_28;\n float tmpvar_40;\n tmpvar_40 = sqrt(dot (zz_30, zz_30));\n xlat_mutablestruc = (sqrt(dot (tmpvar_39.xyw, tmpvar_39.xyw)) / 24.0);\n vec4 tmpvar_41;\n tmpvar_41 = texture (sampler_pc_main, uv_3);\n float tmpvar_42;\n float tmpvar_43;\n tmpvar_43 = (q10 * 0.7);\n tmpvar_42 = ((log(\n (1.0 + (tmpvar_40 / 24.0))\n ) * 0.02) * (1.0 - (1.0 - \n ((tmpvar_41.z + (0.003921569 * tmpvar_41.y)) + tmpvar_43)\n )));\n float tmpvar_44;\n vec4 tmpvar_45;\n tmpvar_45 = texture (sampler_pc_main, uv_3);\n tmpvar_44 = (1.0 - ((tmpvar_45.z + \n (0.003921569 * tmpvar_45.y)\n ) + tmpvar_43));\n if ((((tmpvar_25 <= tmpvar_44) && (tmpvar_40 < 24.0)) && (tmpvar_25 > 0.005))) {\n ret_4.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(\n (q14 * 4.0)\n )).x));\n float x_46;\n x_46 = ((1.0 - tmpvar_25) * 255.0);\n float ip_47;\n ip_47 = float(int(x_46));\n vec2 tmpvar_48;\n tmpvar_48.x = (x_46 - ip_47);\n tmpvar_48.y = (ip_47 / 255.0);\n ret_4.yz = tmpvar_48;\n } else {\n vec3 tmpvar_49;\n tmpvar_49.y = 0.0;\n tmpvar_49.x = sustain;\n tmpvar_49.z = (1.0 - tmpvar_42);\n vec3 tmpvar_50;\n tmpvar_50.xy = vec2(0.003921569, 0.0);\n tmpvar_50.z = (q14 / 6.0);\n ret_4 = ((texture (sampler_fc_main, uv_3).xyz * tmpvar_49) - tmpvar_50);\n };\n vec4 tmpvar_51;\n tmpvar_51.w = 1.0;\n tmpvar_51.xyz = ret_4;\n ret = tmpvar_51.xyz;\n }",comp:" shader_body { \n vec3 tmpvar_1;\n tmpvar_1.x = q4;\n tmpvar_1.y = q5;\n tmpvar_1.z = q6;\n mat3 tmpvar_2;\n tmpvar_2[uint(0)].x = q20;\n tmpvar_2[uint(0)].y = q23;\n tmpvar_2[uint(0)].z = q26;\n tmpvar_2[1u].x = q21;\n tmpvar_2[1u].y = q24;\n tmpvar_2[1u].z = q27;\n tmpvar_2[2u].x = q22;\n tmpvar_2[2u].y = q25;\n tmpvar_2[2u].z = q28;\n vec2 tmpvar_3;\n tmpvar_3.x = q1;\n tmpvar_3.y = q2;\n vec2 uv_4;\n vec3 ret_5;\n uv_4 = (((uv - 0.5) * 0.9) + 0.5);\n vec3 tmpvar_6;\n tmpvar_6.xy = ((uv_4 - 0.5) * min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z)));\n tmpvar_6.z = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n float tmpvar_7;\n tmpvar_7 = clamp ((abs(\n ((1.0 - ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2).z) - clamp ((1.0 - (\n (texture (sampler_blur2, tmpvar_3).xyz * scale2)\n + bias2).z), 0.1, 0.4))\n ) + 0.2), 0.0, 1.0);\n float tmpvar_8;\n tmpvar_8 = clamp (((1.0 - \n exp(-(((texture (sampler_blur1, uv_4).xyz * scale1) + bias1).x))\n ) - 0.2), 0.0, 1.0);\n ret_5 = ((mix (texture (sampler_main, uv_4).xyz, \n ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1)\n , vec3(tmpvar_7)).x * (0.2 + \n ((1.0 - tmpvar_7) * (1.0 - min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z))))\n )) * (1.0 + (0.5 * \n sin((((tmpvar_6 / q7) * tmpvar_2) + tmpvar_1))\n )));\n vec3 tmpvar_9;\n tmpvar_9.xy = vec2(0.0, 1.0);\n tmpvar_9.z = (tmpvar_8 * 3.0);\n ret_5 = (mix (ret_5, tmpvar_9, vec3(tmpvar_8)) + ((\n pow ((1.0 - mix (texture (sampler_main, uv_4).xyz, (\n (texture (sampler_blur1, uv_4).xyz * scale1)\n + bias1), vec3(0.8, 0.8, 0.8)).z), 3.0)\n * \n (0.5 + (0.5 * slow_roam_cos))\n ) * q19).xyz);\n ret_5 = (1.0 - exp((-2.0 * ret_5)));\n vec4 tmpvar_10;\n tmpvar_10.w = 1.0;\n tmpvar_10.xyz = ret_5;\n ret = tmpvar_10.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:0,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,wave_mode:7,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.958178,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,ob_r:.3999,ob_a:.2,ib_size:0,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:1,sides:100,additive:1,x:.26,y:.2,rad:.393173,tex_zoom:.9355,r:0,g:.55,b:.5,g2:.4,b2:.4,a2:.07,border_r:.3,border_g:.7,border_b:.8,border_a:0},init_eqs_str:"a.g0=0;a.y0=0;a.q1=0;a.x0=0;a.q24=0;a.q26=0;a.r0=0;a.trig=0;a.q2=0;a.b0=0;a.rad0=0;",frame_eqs_str:"a.trig=a.q24;a.x0=a.x0*bnot(a.trig)+a.trig*(.5+div(randint(100),200));a.y0=a.y0*bnot(a.trig)+a.trig*(.5+div(randint(100),200));a.x0+=div(.1*a.q1*(3+a.q26),a.fps);a.y0+=div(.1*a.q2*(3+a.q26),a.fps);a.x0-=Math.floor(a.x0);a.y0-=Math.floor(a.y0);a.tex_ang=a.time;a.tex_zoom=a.q1;a.ang=div(a.time,100)*a.q2;a.x=a.x0;a.y=a.y0;a.rad0=a.rad0*bnot(a.trig)+a.trig*(.04+div(randint(100),1E3));a.rad=a.rad0;a.r0=bnot(a.trig)*a.r0+div(a.trig*randint(10),10);a.g0=bnot(a.trig)*a.g0+div(a.trig*\nrandint(10),10);a.b0=bnot(a.trig)*a.b0+div(a.trig*randint(10),10);a.r=a.r0;a.b=a.b0;a.g=a.g0;a.r2=0;a.b2=0;a.g2=0;a.a=1;a.a2=.3;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.q1=0;a.dec_med=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q11=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q28=0;a.q20=0;",frame_eqs_str:"a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.monitor=a.index4;\na.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.q11=Math.min(a.q22,3);a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265359*a.p2,2);a.q27=8-a.index;a.q28=a.index2;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1+.02*a.q1;a.rot=.01*a.q2;a.dx=0*a.index;a.wave_a=0;",pixel_eqs_str:"",pixel_eqs:"",warp:"float xlat_mutabledx;\nfloat xlat_mutabledy;\nvec2 xlat_mutableuv2;\nvec2 xlat_mutablezz;\n shader_body { \n vec2 uv_1;\n vec3 crisp_2;\n vec2 tmpvar_3;\n tmpvar_3.y = 0.0;\n tmpvar_3.x = texsize.w;\n vec2 tmpvar_4;\n tmpvar_4.x = 0.0;\n tmpvar_4.y = texsize.z;\n xlat_mutablezz = ((uv * texsize.xy) * 0.01);\n vec2 tmpvar_5;\n tmpvar_5.x = (cos((xlat_mutablezz.y * q1)) * sin(-(xlat_mutablezz.y)));\n tmpvar_5.y = (sin(xlat_mutablezz.x) * cos((xlat_mutablezz.y * q2)));\n uv_1 = (uv - ((tmpvar_5 * texsize.zw) * (8.0 + \n (6.0 * q11)\n )));\n xlat_mutableuv2 = (((uv_1 / 2.0) * q27) / 4.0);\n xlat_mutabledx = dot ((texture (sampler_main, (xlat_mutableuv2 + tmpvar_3)).xyz - texture (sampler_main, (xlat_mutableuv2 - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledy = dot ((texture (sampler_main, (xlat_mutableuv2 + tmpvar_4)).xyz - texture (sampler_main, (xlat_mutableuv2 - tmpvar_4)).xyz), vec3(0.32, 0.49, 0.29));\n float tmpvar_6;\n tmpvar_6 = (0.15 + (0.1 * q28));\n vec2 tmpvar_7;\n tmpvar_7 = (xlat_mutableuv2 + (time / 100.0));\n xlat_mutabledx = (xlat_mutabledx + (tmpvar_6 * (texture (sampler_noise_hq, tmpvar_7).x - 0.5)));\n xlat_mutabledy = (xlat_mutabledy + (tmpvar_6 * (texture (sampler_noise_hq, tmpvar_7).y - 0.5)));\n vec2 tmpvar_8;\n tmpvar_8.x = xlat_mutabledx;\n tmpvar_8.y = xlat_mutabledy;\n xlat_mutablezz = tmpvar_8;\n crisp_2 = (texture (sampler_main, (uv_1 + (tmpvar_8 * 0.04))).xyz + texture (sampler_main, uv_1).xyz);\n crisp_2 = (crisp_2 * 0.5);\n crisp_2 = (crisp_2 + ((0.05 * \n (0.9 + (0.1 * roam_cos))\n .xyz) - (\n sqrt(dot (tmpvar_8, tmpvar_8))\n * 0.3)));\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ((crisp_2 * 0.97) - 0.015);\n ret = tmpvar_9.xyz;\n }",comp:"vec2 xlat_mutabledz;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\n shader_body { \n vec2 uv2_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n xlat_mutabledz.x = dot ((texture (sampler_main, (uv + tmpvar_2)).xyz - texture (sampler_main, (uv - tmpvar_2)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledz.y = dot ((texture (sampler_main, (uv + tmpvar_3)).xyz - texture (sampler_main, (uv - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n uv2_1 = (uv - 0.5);\n xlat_mutableuv3 = ((0.2 * uv2_1) + 0.5);\n float tmpvar_4;\n tmpvar_4 = (time / 2.0);\n xlat_mutableuv3 = ((0.2 * cos(\n ((42.0 * fract(xlat_mutableuv3)) + tmpvar_4)\n )) + (99.0 * xlat_mutabledz));\n float tmpvar_5;\n tmpvar_5 = clamp ((0.01 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_5)) + (0.9 * dot (vec3(tmpvar_5), vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * 1.252262));\n xlat_mutableuv3 = ((0.2 * uv2_1) + 0.5);\n xlat_mutableuv3 = ((0.2 * cos(\n ((42.0 * fract(xlat_mutableuv3)) + tmpvar_4)\n )) + (99.0 * xlat_mutabledz));\n float tmpvar_6;\n tmpvar_6 = clamp ((0.01 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_6)) + (0.9 * dot (vec3(tmpvar_6), vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * 1.252262));\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (xlat_mutableret1 + clamp ((\n (16.0 * ((0.5 * texture (sampler_main, (uv + \n (0.1 * xlat_mutabledz)\n )).xyz) + 0.01))\n * \n (0.1 + xlat_mutableret1)\n ), 0.0, 1.0));\n ret = tmpvar_7.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:4,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.527,wave_smoothing:.45,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:.8,wave_g:.49,ob_size:.015,ob_a:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b2x:.3,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:506,sep:116,spectrum:1,thick:1,scaling:1.07408,smoothing:0,a:.7},init_eqs_str:"a.n=0;a.m=0;",frame_eqs_str:"",point_eqs_str:"a.n=Math.floor((a.reg00+.5)*a.sample);a.m=30001+div(a.n,div(a.reg00,a.reg01));a.gmegabuf[Math.floor(a.m)]=a.value1+a.value2;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;"},{baseVals:{enabled:1,samples:506,thick:1,scaling:.89152,smoothing:.82},init_eqs_str:"a.n=0;",frame_eqs_str:"",point_eqs_str:"a.n=Math.floor((a.reg00+.5)*a.sample)+a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;"},{baseVals:{enabled:1,samples:506,thick:1,scaling:.89152,smoothing:.82},init_eqs_str:"a.n=0;",frame_eqs_str:"",point_eqs_str:"a.n=Math.floor((a.reg00+.5)*a.sample)+2*a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;"},{baseVals:{enabled:1,samples:506,spectrum:1,thick:1},init_eqs_str:"a.n=0;",frame_eqs_str:"",point_eqs_str:"a.n=Math.floor((a.reg00-.5)*a.sample)+3*a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;"}],init_eqs_str:"a.xang=0;a.fov=0;a.hell=0;a.cbeat=0;a.index2=0;a.bindex=0;a.ran4=0;a.index=0;a.dec_v=0;a.yang=0;a.q29=0;a.q6=0;a.amp_=0;a.xlen=0;a.smooth=0;a.q1=0;a.dec_med=0;a.sum=0;a.q5=0;a.dec_f=0;a.trely=0;a.flen=0;a.reg01=0;a.my=0;a.oz=0;a.imag=0;a.is_beat=0;a.yind=0;a.oy0a=0;a.dec_slow=0;a.ran2=0;a.ind=0;a.z0=0;a.ylen=0;a.real=0;a.ran4_=0;a.ran3=0;a.q4=0;a.mz=0;a.oy0=0;a.amp=0;a.tc0=0;a.oy=0;a.avg=0;a.mx=0;a.vol=0;a.ran2_=0;a.peak=0;a.decc=0;a.q2=0;a.bd_bt=0;a.zang=0;a.q3=0;a.reg00=0;\na.trelz=0;a.q32=0;a.ran3_=0;a.q28=0;a.trelx=0;a.q30=0;a.ox=0;a.xind=0;for(var b=a.index=0;7E4>b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.zang=1;a.yang=0;a.zang=2;",frame_eqs_str:"a.xlen=45;a.ylen=45;a.flen=30;a.reg00=div(a.xlen*a.ylen,4);a.reg01=div(a.reg00,4);a.dec_med=1-div(.06*30,a.fps);a.dec_slow=1-div(.6,a.fps);a.dec_f=pow(.8,div(30,a.fps));a.q30=a.dec_slow;a.smooth=Math.max(1,pow(6,div(a.fps,30))-2);a.cbeat=a.bass+a.mid+a.treb;a.decc=.00001a.cbeat?1:0)?.8:a.dec_med;a.vol=a.vol*a.decc+(1-a.decc)*a.cbeat;a.avg=a.avg*a.dec_slow+a.cbeat*(1-a.dec_slow);a.is_beat=above(a.cbeat,1.5*a.avg)*above(a.time,a.tc0+.2);a.tc0=.00001c;c++){a.xind=-1;for(var d=0;3>d;d++)a.ox=mod((a.cx+.5)*a.xlen+a.xind,a.xlen),a.oy=mod((a.cy+.5)*a.ylen+a.yind,a.ylen),a.amp=3*(a.cx*a.cx+a.cy*a.cy),a.megabuf[Math.floor(a.oy*a.ylen+a.ox)]-=div(div(60,a.fps)*sqrt(a.amp)*above(a.amp,.02),1+a.xind*a.xind+a.yind*a.yind),a.xind+=1;a.yind+=1}a.ind+=1}for(b=a.yind=0;bMath.abs(mod(a.bindex,4)-0)?1:0)?a.ran2=div(randint(100)-30,60):0;.00001\nMath.abs(mod(a.bindex,4)-2)?1:0)?a.ran3=div(randint(100)-30,60):0;.00001Math.abs(mod(a.bindex,6)-2)?1:0)?a.ran4=div(randint(100)-30,60):0;a.dec_v=Math.min(Math.max(0,1-div(8*a.vol,a.fps)),a.dec_slow);a.ran2_=a.ran2_*a.dec_v+(1-a.dec_v)*a.ran2;a.ran3_=a.ran3_*a.dec_v+(1-a.dec_v)*a.ran3;a.ran4_=a.ran4_*a.dec_v+(1-a.dec_v)*a.ran4;a.trelx+=div(div(a.ran2_,a.fps),7);a.trely+=div(div(a.ran3_,a.fps),2);a.trelz+=div(div(a.ran4_,a.fps),6);a.zang=6*Math.sin(a.trelz);a.xang=6*Math.sin(div(a.zang,\n5)+a.trelx);a.yang=6*Math.sin(0*div(a.zang,3)+a.trely);a.q1=Math.cos(a.xang);a.q2=Math.sin(a.xang);a.q3=Math.cos(a.yang);a.q4=Math.sin(a.yang);a.q5=Math.cos(a.zang);a.q6=Math.sin(a.zang);a.fov=1;for(b=a.yind=0;b 0.0))\n ) * 0.2) * min (1.0, (1.0/(tmpvar_8))));\n ret_4 = (ret_4 + tmpvar_14);\n ret_4 = (ret_4 + ((\n (sin((12.0 * q2)) * tmpvar_7)\n * tmpvar_14) * dot (\n (12.0 * ((texture (sampler_blur1, (tmpvar_10 - vec2(-0.5, 0.3))).xyz * scale1) + bias1))\n , vec3(0.32, 0.49, 0.29))));\n ret_4 = (ret_4 + ((\n ((0.5 / abs(tmpvar_8)) * normalize(xlat_mutablecol))\n * \n float((tmpvar_8 < 0.0))\n ) * tmpvar_7));\n vec4 tmpvar_15;\n tmpvar_15.w = 1.0;\n tmpvar_15.xyz = ret_4;\n ret = tmpvar_15.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:5,gammaadj:1.980001,decay:.5,echo_zoom:.999998,echo_alpha:.5,echo_orient:3,modwavealphabyvolume:1,darken:1,wave_a:.001,wave_scale:10.437056,wave_smoothing:.45,wave_mystery:.08,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.4595,warpscale:2.0067,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:.99,ob_size:0,ob_r:1,ob_g:1,ob_b:1,ib_size:0,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.4999,mv_g:.4999,mv_b:.4999,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:1,rad:.048958,tex_ang:1.00531,tex_zoom:1.531168,r:.5,g:1,b:.9,r2:.83,g2:.93,b2:.8,a2:1,border_b:0,border_a:0},init_eqs_str:"a.trel=0;a.q20=0;a.q28=0;a.q26=0;",frame_eqs_str:"a.trel=div(a.time,2)+a.q20;a.x=.5+Math.sin(2*a.trel);a.y=.5+Math.cos(1.3*a.trel+div(a.q28,3));a.a=div(a.q26,4)+.2;"},{baseVals:{enabled:0}},{baseVals:{enabled:1,x:.503,rad:.038857,tex_zoom:.609857,g:.1,a:.9,r2:1,b2:1,border_r:.5,border_g:.5,border_b:.5,border_a:0},init_eqs_str:"a.is_beat=0;a.t0=0;a.q21=0;",frame_eqs_str:"a.x=div(randint(10),10);a.y=div(randint(10),10);a.r=div(randint(4),3);a.g=div(randint(4),3);a.b=div(randint(4),3);a.is_beat=above(a.time,a.t0+.03);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.a=Math.min(div(a.q21,2),.9)*a.is_beat;a.rad=div(a.a*a.a,3);"},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,sep:120,additive:1,scaling:.891519,smoothing:.82,a:.6},init_eqs_str:"a.k1=0;a.k2=0;a.xi=0;a.yi=0;a.dx=0;a.dy=0;a.q22=0;a.t2=0;a.t1=1+.3*(.01*randint(101)-.01*randint(101));a.t2=1+.3*(.01*randint(101)-.01*randint(101));a.t3=1+.3*(.01*randint(101)-.01*randint(101));a.t4=1+.3*(.01*randint(101)-.01*randint(101));a.t5=1+.3*(.01*randint(101)-.01*randint(101));a.t6=1+.3*(.01*randint(101)-.01*randint(101));a.t7=1+.3*(.01*randint(101)-.01*randint(101));a.t8=1+.3*(.01*randint(101)-.01*randint(101));",frame_eqs_str:"a.t2+=a.bass_att;",point_eqs_str:"a.k1=mod(100*a.sample,8);a.k2=bnot(a.k1);a.xi=a.value1*a.k2+a.xi*(1-a.k2);a.yi=a.value2*(1-a.k2)+a.yi*a.k2;a.dx=.99*a.dx+a.xi;a.dy=.99*a.dy+a.yi;a.x=.5+div(a.xi,2);a.y=.5+div(a.yi,2);a.a=div(a.q22,8);a.a=Math.min(a.a,.2);"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index=0;a.q22=0;a.q21=0;a.fade=0;a.q1=0;a.dec_med=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q20=0;a.fade=.5;",frame_eqs_str:"a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=\na.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265358*a.p2,2);a.q27=a.index+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1;a.rot=-0*a.index;a.fade=a.fade*a.dec_med+pow(.996,div(30,a.fps))*(1-a.dec_med);a.q32=a.fade;",pixel_eqs_str:"",pixel_eqs:"",warp:" shader_body { \n vec2 zz_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)] = _qa.xy;\n tmpvar_2[1u] = _qa.zw;\n zz_1 = (((\n (uv - vec2(0.5, 0.5))\n * texsize.xy) * (0.015 * q27)) * tmpvar_2);\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = (((q32 * texture (sampler_main, \n (uv + ((clamp (\n (sin(zz_1) / cos(zz_1))\n , vec2(-20.0, -20.0), vec2(20.0, 20.0)) * texsize.zw) * 8.0))\n ).xyz) + (\n (0.03 * texture (sampler_noise_lq, ((uv * 0.3) + (0.01 * rand_frame).xy)))\n .xyz * \n (1.0 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n )) - 0.02);\n ret = tmpvar_3.xyz;\n }",comp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ((tmpvar_1.xyz + clamp (\n (3.0 * (((texture (sampler_blur1, \n (uv - (0.01 * tmpvar_1.xyz).xy)\n ).xyz * scale1) + bias1) - vec3(0.1, 0.1, 0.2)))\n , 0.0, 1.0)) * 1.3);\n ret = tmpvar_2.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.98,decay:.5,echo_zoom:.952,echo_alpha:.5,echo_orient:3,wave_mode:6,additivewave:1,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:2.103,wave_smoothing:.54,wave_mystery:.38,modwavealphastart:.81,modwavealphaend:1.4,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:0,wave_g:0,wave_b:0,ob_size:.015,ob_b:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:1,sides:16,thickoutline:1,textured:1,num_inst:3,x:.73,rad:.29466,tex_zoom:1.87511,r:.7,g:.7,b:1,g2:0,border_b:0,border_a:0},init_eqs_str:"a.trig=0;a.q25=0;a.x0=0;a.y0=0;",frame_eqs_str:"a.trig=a.q25;a.a=.8*a.trig;a.a2=0;a.x0=a.x0*bnot(a.trig)+div(a.trig*randint(100),100);a.y0=a.y0*bnot(a.trig)+div(a.trig*randint(100),100);a.tex_ang=randint(20);a.rad=.1+div(randint(10),8);a.x=a.x0;a.y=a.y0;a.r=.7+.3*Math.sin(div(a.time,12));a.b=.7+.3*Math.sin(div(a.time,15));a.g=.7+.3*Math.sin(div(a.time,8));a.r2=a.r;a.b2=a.b;a.g2=a.g;"},{baseVals:{enabled:1,sides:36,thickoutline:1,textured:1,num_inst:4,x:.3,rad:.05429,ang:1.25664,tex_ang:.37699,tex_zoom:1.02841,g:.7,b:.5,r2:1,g2:0,border_g:.59,border_b:0,border_a:0},init_eqs_str:"a.q31=0;a.q32=0;a.q30=0;",frame_eqs_str:"a.x=a.q31;a.y=a.q32;a.rad=.06;a.tex_ang=a.time;a.a=a.q30;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.q25=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q15=0;a.q29=0;a.q6=0;a.dec_med=0;a.q5=0;a.mindev=0;a.trel=0;a.t0a=0;a.mov1=0;a.vis=0;a.is_beat=0;a.q31=0;a.q23=0;a.q24=0;a.dec_slow=0;a.q11=0;a.hpeak=0;a.q10=0;a.sdev=0;a.med=0;a.spb=0;a.dir=0;a.spb_=0;a.q16=0;a.rota=0;a.q19=0;a.vol=0;a.peak=0;a.trig1=0;a.wamp=0;a.speed=0;a.t0=0;a.vol_=0;a.q32=0;a.q7=0;a.wamp_=0;a.q30=0;a.q20=0;a.q8=0;a.t0a=a.time;a.t0=a.time+.5;a.spb_=.5;a.volb=.5;a.volx=.5;a.vol_=1;a.index=0;a.mov1=0;a.sdev=.1;a.wamp_=\n.1;",frame_eqs_str:"a.dec_med=pow(.8,div(30,a.fps));a.dec_slow=pow(.95,div(30,a.fps));a.vol=div(a.bass+a.med+a.treb,1.5);a.vol_=a.vol_*a.dec_slow+(1-a.dec_slow)*a.vol;a.is_beat=above(a.vol,a.vol_+2*a.peak)*above(a.time,a.t0+.45*a.spb_);a.t0a=.00001= 0.0)\n )) + (q30 * 0.02));\n xlat_mutablered = (xlat_mutablered + ((\n (xlat_mutablewave / abs(sin((\n (1.0/(tmpvar_12))\n + \n (q1 / 8.0)\n ))))\n * xlat_mutablegreen) * ky_3));\n xlat_mutablezv = ((time * 0.08) + (0.2 * sin(\n ((uv * 16.0) + time)\n ))).x;\n vec2 tmpvar_13;\n tmpvar_13.x = q28;\n tmpvar_13.y = (0.2 * time);\n xlat_mutableuv2 = ((tmpvar_4 * 2.0) + tmpvar_13);\n vec3 tmpvar_14;\n tmpvar_14.xy = xlat_mutableuv2;\n tmpvar_14.z = xlat_mutablezv;\n vec3 tmpvar_15;\n tmpvar_15.xy = (xlat_mutableuv2 * vec2(2.0, 2.0));\n tmpvar_15.z = (xlat_mutablezv * 2.0);\n vec3 tmpvar_16;\n tmpvar_16.xy = (xlat_mutableuv2 * vec2(4.0, 4.0));\n tmpvar_16.z = (xlat_mutablezv * 3.0);\n vec3 tmpvar_17;\n tmpvar_17.xy = (xlat_mutableuv2 * vec2(8.0, 8.0));\n tmpvar_17.z = (xlat_mutablezv * 7.0);\n xlat_mutableuv2 = (tmpvar_4 + ((\n ((texture (sampler_noisevol_hq, tmpvar_14).z + (texture (sampler_noisevol_hq, tmpvar_15).z / 2.0)) + (texture (sampler_noisevol_hq, tmpvar_16).z / 4.0))\n + \n (texture (sampler_noisevol_hq, tmpvar_17).z / 8.0)\n ) * 0.1));\n vec3 tmpvar_18;\n tmpvar_18.x = xlat_mutablered;\n tmpvar_18.y = xlat_mutablegreen;\n tmpvar_18.z = ((1.0 + xlat_mutableuv2.y) * sqrt(dot (xlat_mutableuv2, xlat_mutableuv2)));\n vec4 tmpvar_19;\n tmpvar_19.w = 1.0;\n tmpvar_19.xyz = ((tmpvar_18 * 0.8) - 0.005);\n ret = tmpvar_19.xyz;\n }",comp:"float trel;\nfloat vshift;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers;\nvec2 xlat_mutablers0;\nfloat xlat_mutablesmoke;\nfloat xlat_mutablesmoke2;\nvec2 xlat_mutableuv_l;\nfloat xlat_mutablew;\nfloat xlat_mutablez;\n shader_body { \n trel = (time / 2.0);\n vshift = (0.5 - q29);\n vec2 tmpvar_1;\n tmpvar_1.x = rand_preset.x;\n tmpvar_1.y = ((-0.1 - (rand_preset.y / 2.0)) + vshift);\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = (0.005 * time);\n xlat_mutableuv_l = (uv + tmpvar_2);\n vec2 tmpvar_3;\n vec2 tmpvar_4;\n tmpvar_4 = (uv - 0.5);\n tmpvar_3 = sin(((\n (tmpvar_4 * aspect.xy)\n + 0.5) - (tmpvar_1 * aspect.xy)));\n vec2 tmpvar_5;\n tmpvar_5 = fract(uv);\n vec3 tmpvar_6;\n tmpvar_6 = vec3((texture (sampler_fc_main, tmpvar_5).x + (2.0 * (\n (texture (sampler_blur2, tmpvar_5).xyz * scale2)\n + bias2).x)));\n vec3 tmpvar_7;\n tmpvar_7.x = tmpvar_6.x;\n tmpvar_7.y = pow (tmpvar_6.x, 2.1);\n tmpvar_7.z = pow (tmpvar_6.x, 4.0);\n xlat_mutablew = ((uv.y - (\n ((dot (texture (sampler_noise_hq, vec2((xlat_mutableuv_l.x / 6.0))), vec4(0.32, 0.49, 0.29, 0.0)) + uv.x) - 0.5)\n / 4.0)) - vshift);\n xlat_mutablez = (0.2 / xlat_mutablew);\n float tmpvar_8;\n tmpvar_8 = clamp ((-0.2 - (\n (8.0 * q5)\n * xlat_mutablew)), 0.0, 1.0);\n xlat_mutablers0.x = (((uv.x - 0.5) * (1.0 + \n abs(xlat_mutablez)\n )) * 2.0);\n xlat_mutablers0.y = xlat_mutablez;\n xlat_mutablers0 = (xlat_mutablers0 * ((4.0 * \n float((xlat_mutablez <= 0.0))\n ) + 1.0));\n vec2 tmpvar_9;\n tmpvar_9.x = 0.0;\n tmpvar_9.y = (1.5 + xlat_mutablew);\n vec2 x_10;\n x_10 = (xlat_mutablers0 - tmpvar_9);\n float tmpvar_11;\n tmpvar_11 = ((q26 / sqrt(\n dot (x_10, x_10)\n )) / 4.0);\n xlat_mutablers0 = (xlat_mutablers0 * (1.0 + (tmpvar_11 * tmpvar_11)));\n xlat_mutablers.x = (xlat_mutablers0 * 2.0).x;\n xlat_mutablers.y = (xlat_mutablers0.y + (trel * 0.5));\n float tmpvar_12;\n tmpvar_12 = (texture (sampler_main, uv).y * tmpvar_8);\n vec3 tmpvar_13;\n tmpvar_13.xy = (xlat_mutablers * 2.0);\n tmpvar_13.z = (0.2 * trel);\n float tmpvar_14;\n tmpvar_14 = dot (((\n ((2.0 * clamp ((texture (sampler_noisevol_hq, \n (tmpvar_13 * float((xlat_mutablez >= 0.0)))\n ) - 0.2), 0.0, 1.0)).xyz * clamp ((texture (sampler_noise_hq, (xlat_mutablers / 16.0)) - 0.5), 0.0, 1.0).x)\n / \n sqrt(abs(xlat_mutablez))\n ) + tmpvar_11), vec3(0.32, 0.49, 0.29));\n vec3 tmpvar_15;\n tmpvar_15.x = tmpvar_14;\n tmpvar_15.y = pow (tmpvar_14, 2.1);\n tmpvar_15.z = pow (tmpvar_14, 6.0);\n xlat_mutableret1 = (((\n ((uv.y * (1.0 + q23)) + (0.1 / sqrt(dot (tmpvar_3, tmpvar_3))))\n * vec3(0.1, 0.1, 0.2)) * tmpvar_8) + (clamp (tmpvar_15, 0.0, 1.0) * (1.0 - \n clamp ((-1.0 - (12.0 * xlat_mutablew)), 0.0, 1.0)\n )));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((1.0 - \n (tmpvar_12 * 8.0)\n ), 0.0, 1.0));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_main, fract((tmpvar_4 + 0.5)));\n xlat_mutablesmoke = (tmpvar_16.z * (tmpvar_16.z * q5));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((1.0 - \n ((xlat_mutablesmoke * q32) * tmpvar_8)\n ), 0.0, 1.0));\n xlat_mutablesmoke2 = (texture (sampler_main, ((tmpvar_4 / 2.0) + 0.5)).z * q30);\n xlat_mutableret1 = (xlat_mutableret1 + (clamp (tmpvar_7, 0.0, 1.0) - (\n ((xlat_mutablez * clamp ((xlat_mutablesmoke + \n (xlat_mutablew * q31)\n ), 0.0, 1.0)) * vec3(1.0, 0.4, 0.1))\n * tmpvar_8)));\n float tmpvar_17;\n tmpvar_17 = clamp (((\n (tmpvar_12 * xlat_mutablez)\n * xlat_mutablez) / 16.0), 0.0, 1.0);\n vec3 tmpvar_18;\n tmpvar_18.x = tmpvar_17;\n tmpvar_18.y = pow (tmpvar_17, 2.1);\n tmpvar_18.z = pow (tmpvar_17, 6.0);\n xlat_mutableret1 = (xlat_mutableret1 + clamp (tmpvar_18, 0.0, 1.0));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((\n (((dot (texture (sampler_noise_mq, vec2(\n ((xlat_mutableuv_l.x / 4.0) + (0.02 * trel))\n )), vec4(0.32, 0.49, 0.29, 0.0)) / 6.0) - uv.y) + 0.8)\n * 32.0), 0.0, 1.0));\n vec3 tmpvar_19;\n tmpvar_19.x = xlat_mutablesmoke2;\n tmpvar_19.y = pow (xlat_mutablesmoke2, 2.1);\n tmpvar_19.z = pow (xlat_mutablesmoke2, 6.0);\n xlat_mutableret1 = ((xlat_mutableret1 * clamp (\n (1.0 - xlat_mutablesmoke2)\n , 0.0, 1.0)) + clamp (tmpvar_19, 0.0, 1.0));\n vec4 tmpvar_20;\n tmpvar_20.w = 1.0;\n tmpvar_20.xyz = (1.0 - exp((\n -(xlat_mutableret1)\n * 2.0)));\n ret = tmpvar_20.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:3,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:6,wave_thick:1,modwavealphabyvolume:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.527,wave_smoothing:.09,modwavealphastart:0,modwavealphaend:1.32,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:.8,wave_g:.49,ob_a:1,ib_size:.26,mv_x:64,mv_y:48,mv_l:1.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0,b2x:.7,b1ed:0},shapes:[{baseVals:{enabled:1,sides:12,num_inst:1024,rad:.03632,tex_ang:1.00531,tex_zoom:1.53117,b:1,a:0,g2:0,border_b:0,border_a:0},init_eqs_str:"a.fov=0;a.n=0;a.x0=0;a.y0=0;a.z0=0;a.q32=0;a.t1=0;",frame_eqs_str:"a.fov=a.reg03;a.n=a.instance*a.reg00;a.x0=a.gmegabuf[Math.floor(a.n)];a.y0=a.gmegabuf[Math.floor(a.n+1)];a.z0=a.gmegabuf[Math.floor(a.n+2)]+a.reg02;a.x=div(a.x0,a.z0)*a.fov+.5;a.y=div(a.y0,a.z0)*a.q32*a.fov+.5;a.r=a.gmegabuf[Math.floor(a.n+3)];a.g=a.gmegabuf[Math.floor(a.n+4)];a.b=a.gmegabuf[Math.floor(a.n+5)];a.r2=div(a.r,2);a.g2=div(a.g,2);a.b2=div(a.b2,2);a.a=div(a.instance,1024);a.a2=.5*a.a;a.rad=Math.min(div(.02,a.z0),.5)*(0b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.recsize=8;a.reg00=a.recsize;a.points=1024;a.reg01=0;a.zofs=1+2*div(randint(100),100);a.reg02=a.zofs;a.fov=.3;a.reg03=a.fov;',frame_eqs_str:'a.dec_f=pow(.3,div(30,a.fps));a.dec_m=pow(.85,div(30,a.fps));a.dec_s=pow(.95,div(30,a.fps));a.beat=a.bass+a.mid+a.treb-(a.bass_att+a.mid_att+a.treb_att)+(a.bass+a.mid+a.treb);a.beat/=3;a.peak=a.peak*a.dec_m+(1-a.dec_m)*pow(a.beat-1,1)*(1Math.abs(a.index-2)?1:0))?(a.ran4=div(randint(100),50)-1,a.ran5=div(randint(100),50)-1,a.ran6=div(randint(100),50)-1):0;a.ran4_=a.dec_m*a.ran4_+(1-a.dec_m)*a.ran4;a.ran5_=a.dec_m*a.ran5_+(1-a.dec_m)*a.ran5;a.ran6_=\na.dec_m*a.ran6_+(1-a.dec_m)*a.ran6;.00001Math.abs(a.index-6)?1:0))?(a.ran7=div(randint(100),50)-1,a.ran8=div(randint(100),50)-1,a.ran9=div(randint(100),50)-1):0;a.ran7_=a.dec_m*a.ran7_+(1-a.dec_m)*a.ran7;a.ran8_=a.dec_m*a.ran8_+(1-a.dec_m)*a.ran8;a.ran9_=a.dec_m*a.ran9_+(1-a.dec_m)*a.ran9;a.pk=sqrt(a.peak+.1);a["new"]=Math.floor(12*(a.ran4-a.ran5)*a.pk-div(12*(a.ran3-a.ran1),a.pk));a["new"]=Math.max(Math.min(a["new"],20),2);a.reg01+=a["new"];a.dec=a.dec_m;a.n=a.recsize*\na.points;a.m=0;a.dt1=div(div(.00001 0.5)))\n * 2.0)));\n flash_1 = tmpvar_14;\n float angle_15;\n float tmpvar_16;\n tmpvar_16 = abs(xlat_mutableuv2.x);\n if ((xlat_mutableuv2.y >= 0.0)) {\n angle_15 = (1.0 - ((xlat_mutableuv2.y - tmpvar_16) / (xlat_mutableuv2.y + tmpvar_16)));\n } else {\n angle_15 = (3.0 - ((xlat_mutableuv2.y + tmpvar_16) / (tmpvar_16 - xlat_mutableuv2.y)));\n };\n angle_15 = (angle_15 * 0.25);\n float tmpvar_17;\n if ((xlat_mutableuv2.x < 0.0)) {\n tmpvar_17 = -(angle_15);\n } else {\n tmpvar_17 = angle_15;\n };\n flash_1 = (tmpvar_14 * (tmpvar_14 / (\n abs((fract((\n (3.0 * tmpvar_17)\n + \n (time * 2.0)\n )) - 0.5))\n + 0.18)));\n vec3 tmpvar_18;\n tmpvar_18 = max ((texture (sampler_main, uv).xyz * 2.0), ((\n (texture (sampler_blur2, uv).xyz * scale2)\n + bias2) * 2.0));\n vec2 tmpvar_19;\n tmpvar_19 = sin(xlat_mutableuv3);\n ret_4 = (clamp ((0.025 / \n sqrt(dot (tmpvar_19, tmpvar_19))\n ), 0.0, 1.0) * vec3(0.4, 0.1, 1.0));\n ret_4 = (ret_4 + clamp ((stars_3 * stars_3), 0.0, 1.0));\n ret_4 = (ret_4 * clamp ((1.0 - \n (2.0 * dot (tmpvar_18, vec3(0.32, 0.49, 0.29)))\n ), 0.0, 1.0));\n ret_4 = (ret_4 + tmpvar_18);\n vec3 tmpvar_20;\n tmpvar_20.x = q10;\n tmpvar_20.y = q11;\n tmpvar_20.z = q12;\n ret_4 = (ret_4 + ((2.0 * \n clamp (flash_1, 0.0, 1.0)\n ) * tmpvar_20));\n vec4 tmpvar_21;\n tmpvar_21.w = 1.0;\n tmpvar_21.xyz = ret_4;\n ret = tmpvar_21.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:4,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,additivewave:1,wave_thick:1,modwavealphabyvolume:1,darken:1,wave_a:.001,wave_scale:.133,wave_smoothing:0,wave_mystery:-1,modwavealphastart:1,modwavealphaend:1.3,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:.5,wave_g:.5,wave_b:.5,ob_size:.015,ob_b:1,ib_size:.26,mv_a:0,b2x:.3,b1ed:0},shapes:[{baseVals:{enabled:1,sides:40,thickoutline:1,rad:.06623,tex_zoom:1.79845,r:0,a:.1,g2:0,border_b:0,border_a:0},init_eqs_str:"a.vol=0;a.bob=0;a.border_1=0;a.ro=0;a.sp=0;a.red=0;a.spi=0;a.tm=0;a.bob=1.5;a.ro=0;a.red=randint(20);",frame_eqs_str:"a.vol=1+.2*div(a.bass_att+a.treb_att+a.mid_att,3);a.bob=a.bob*above(a.bob,.01)-.01+(1-above(a.bob,.01));a.bob=.4+.4*Math.sin(.8*a.time);a.bob*=a.vol;a.border_1=.4;a.sides=30;a.ro+=.02;a.ang=a.ro;a.sp=.025*a.red;a.spi=.5-a.sp;a.tm=.1*a.time;a.border_r=.5+a.sp*Math.sin(.6*a.tm)+a.spi*Math.cos(1.46*a.tm);a.border_g=.5+a.sp*Math.sin(1.294*a.tm)+a.spi*Math.cos(.87*a.tm);a.border_b=.5+a.sp*Math.sin(1.418*a.tm)+a.spi*Math.cos(.76*a.tm);"},{baseVals:{enabled:1,sides:40,additive:1,num_inst:4,g:1,b:1,g2:0,border_a:0},init_eqs_str:"",frame_eqs_str:"a.x=.5+.225*Math.sin(.7*div(a.time,a.instance));a.y=.5+.3*Math.cos(.7*div(a.time,a.instance));a.x-=.4*a.x*Math.sin(a.time);a.y-=.4*a.y*Math.cos(a.time);a.rad*=a.mid_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);"},{baseVals:{enabled:1,sides:40,additive:1,g:1,b:1,g2:0,border_a:0},init_eqs_str:"",frame_eqs_str:"a.x=.5+.5*(.3*Math.sin(1.1*a.time)+.7*Math.sin(.5*a.time));a.x=.5+.225*Math.sin(a.time+2.09);a.y=.5+.3*Math.cos(a.time+2.09);a.rad*=a.bass_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);"},{baseVals:{enabled:1,sides:40,additive:1,num_inst:5,rad:.07419,g:1,b:1,g2:0,border_a:0},init_eqs_str:"",frame_eqs_str:"a.x=.5+.225*Math.sin(div(a.time,a.instance));a.y=.5+.3*Math.cos(div(a.time,a.instance));a.x+=.4*a.x*Math.sin(a.time);a.y+=.4*a.y*Math.cos(a.time);a.rad*=a.treb_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);"}],waves:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.index2=0;a.index=0;a.q22=0;a.q21=0;a.q1=0;a.dec_med=0;a.ps=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q28=0;a.q20=0;",frame_eqs_str:"a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.ps=.9*a.ps+.1*a.q22;a.q23=a.ps;a.q24=a.is_beat;\na.q26=a.bass_att+a.mid_att+a.treb_att;a.q27=a.index+1;a.q28=a.index2;a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;",pixel_eqs_str:"a.zoom=1.05;",warp:" shader_body { \n vec2 uv_1;\n vec2 tmpvar_2;\n tmpvar_2 = (uv - vec2(0.5, 0.5));\n vec4 tmpvar_3;\n tmpvar_3.w = 0.0;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_blur1, uv);\n tmpvar_3.xyz = ((tmpvar_4.xyz * scale1) + bias1);\n float tmpvar_5;\n tmpvar_5 = (dot (tmpvar_3, roam_sin) * 16.0);\n mat2 tmpvar_6;\n tmpvar_6[uint(0)].x = cos(tmpvar_5);\n tmpvar_6[uint(0)].y = -(sin(tmpvar_5));\n tmpvar_6[1u].x = sin(tmpvar_5);\n tmpvar_6[1u].y = cos(tmpvar_5);\n uv_1 = ((tmpvar_2 + (\n (0.2 * dot (((tmpvar_4.xyz * scale1) + bias1), vec3(0.32, 0.49, 0.29)))\n * \n (tmpvar_2 * tmpvar_6)\n )) - 0.5);\n vec2 tmpvar_7;\n tmpvar_7 = ((uv_1 * texsize.xy) * 0.02);\n vec2 tmpvar_8;\n tmpvar_8.x = (cos((tmpvar_7.y * q1)) * sin(-(tmpvar_7.y)));\n tmpvar_8.y = (sin(tmpvar_7.x) * cos((tmpvar_7.y * q2)));\n uv_1 = (uv_1 - ((tmpvar_8 * texsize.zw) * 12.0));\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ((texture (sampler_main, uv_1).xyz * 0.98) - 0.02);\n ret = tmpvar_9.xyz;\n }",comp:"vec3 xlat_mutableret1;\nvec2 xlat_mutablers;\nvec2 xlat_mutableuv1;\nfloat xlat_mutablez;\n shader_body { \n xlat_mutableuv1 = (uv - 0.5);\n xlat_mutablez = (0.2 / abs(xlat_mutableuv1.y));\n xlat_mutablers.x = (xlat_mutableuv1.x * xlat_mutablez);\n xlat_mutablers.y = ((xlat_mutablez / 2.0) + (time * 4.0));\n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_noise_hq, xlat_mutablers);\n xlat_mutableret1 = ((tmpvar_1.xyz * vec3(\n greaterThanEqual (tmpvar_1.xyz, vec3(0.0, 0.0, 0.0))\n )) - 0.6);\n float tmpvar_2;\n tmpvar_2 = clamp ((128.0 * xlat_mutableuv1.y), 0.0, 1.0);\n vec2 tmpvar_3;\n tmpvar_3 = fract(((\n (xlat_mutableuv1 * (1.0 - abs(xlat_mutableuv1.x)))\n - 0.5) - (\n (xlat_mutableret1 * 0.05)\n * tmpvar_2).xy));\n float x_4;\n x_4 = (tmpvar_3.y - 0.52);\n vec3 tmpvar_5;\n tmpvar_5 = (texture (sampler_main, tmpvar_3) + ((0.02 / \n (0.02 + sqrt((x_4 * x_4)))\n ) * slow_roam_sin)).xyz;\n xlat_mutableret1 = tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (32.0 * ((\n (uv * mat2(0.6, -0.8, 0.8, 0.6))\n + \n (tmpvar_5 * 0.1)\n .xy) + (time / 64.0)));\n vec2 tmpvar_7;\n tmpvar_7 = abs((fract(tmpvar_6) - 0.5));\n vec3 tmpvar_8;\n tmpvar_8 = clamp (((0.25 / \n sqrt(dot (tmpvar_7, tmpvar_7))\n ) * vec3((texture (sampler_pw_noise_lq, \n (tmpvar_6 / 256.0)\n ).y - 0.9))), 0.0, 1.0);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = (tmpvar_5 + ((\n (tmpvar_8.x * tmpvar_8.x)\n + \n ((rand_preset * (0.5 - uv.y)).xyz * vec3(0.0, 0.0, 1.0))\n ) * (1.0 - tmpvar_2)));\n ret = tmpvar_9.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:2,gammaadj:1.98,decay:.5,echo_zoom:1,echo_alpha:.5,echo_orient:3,wave_mode:3,wave_thick:1,wrap:0,darken:1,wave_a:100,wave_scale:.282,wave_smoothing:.9,wave_mystery:1,warpanimspeed:1.459,warpscale:2.007,zoom:.9999,warp:.01,sx:.9999,wave_r:.5,wave_g:.5,wave_b:.5,ob_size:.05,ob_g:.1,ob_b:1,ob_a:1,ib_size:0,ib_r:0,ib_g:0,ib_b:0,mv_a:0,b1ed:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,spectrum:1,thick:1,scaling:.2248},init_eqs_str:"a.ma=0;a.mx=0;a.my=0;",frame_eqs_str:"a.r=a.bass;a.g=a.treb;a.b=.5;",point_eqs_str:"a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30\nd);d=.06>a.dist?1:0}while(.00001b);",frame_eqs_str:"a.wave_a=0;a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001<\nMath.abs(bnot(a.slow))?a.beat*(6>randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*\na.s1+a.c3*a.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*\na.reg24+a.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;\na.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30<\na.len?1:0)}while(.00001d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+\n2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;",pixel_eqs_str:"a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;",warp:" shader_body { \n float dy_1;\n float dx_2;\n vec3 ret_3;\n vec2 tmpvar_4;\n tmpvar_4 = ((uv * texsize.xy) * texsize_noise_lq.zw);\n vec2 tmpvar_5;\n tmpvar_5 = (texsize.zw * 4.0);\n vec2 tmpvar_6;\n tmpvar_6.x = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).y * 0.5);\n tmpvar_6.y = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).y * 0.5);\n ret_3.y = texture (sampler_fw_main, clamp ((uv + (\n (tmpvar_6 * texsize.zw)\n * 4.0)), 0.0, 1.0)).y;\n ret_3.y = (ret_3.y + ((\n (ret_3 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n .y * 0.025) + -0.01));\n ret_3.y = (ret_3.y + ((texture (sampler_noise_lq, tmpvar_4).y - 0.5) * 0.02));\n dx_2 = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).z * 0.5);\n dy_1 = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).z * 0.5);\n vec2 tmpvar_7;\n tmpvar_7.x = dx_2;\n tmpvar_7.y = dy_1;\n ret_3.z = ((texture (sampler_main, (uv - \n ((tmpvar_7 * texsize.zw) * 4.0)\n )).z - (ret_3.y * 0.01)) + 0.004);\n ret_3.z = (ret_3.z + ((texture (sampler_noise_lq, tmpvar_4).y - 0.5) * 0.01));\n dx_2 = (((2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(1.0, 0.0)))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(-1.0, 0.0)))).xyz * scale1) + bias1)\n )).x * 0.5);\n dy_1 = (((2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(0.0, 1.0)))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(0.0, -1.0)))).xyz * scale1) + bias1)\n )).x * 0.5);\n vec2 tmpvar_8;\n tmpvar_8.x = dx_2;\n tmpvar_8.y = dy_1;\n vec2 tmpvar_9;\n tmpvar_9 = (tmpvar_8 * texsize.zw);\n vec2 domain_10;\n domain_10 = (uv - (tmpvar_9 * 2.5));\n vec4 tmpvar_11;\n tmpvar_11.w = 0.0;\n tmpvar_11.xyz = max (vec4(0.0, 0.0, 0.0, 0.0), texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(-1.0, 0.0))))).xyz;\n vec4 tmpvar_12;\n tmpvar_12.w = 0.0;\n tmpvar_12.xyz = max (tmpvar_11, texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(0.0, -1.0))))).xyz;\n vec4 tmpvar_13;\n tmpvar_13.w = 0.0;\n tmpvar_13.xyz = max (tmpvar_12, texture (sampler_fc_main, domain_10)).xyz;\n vec4 tmpvar_14;\n tmpvar_14.w = 0.0;\n tmpvar_14.xyz = max (tmpvar_13, texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(0.0, 1.0))))).xyz;\n ret_3.x = ((max (tmpvar_14, texture (sampler_fc_main, \n (domain_10 + (texsize.zw * vec2(1.0, 0.0)))\n )).x + (\n (texture (sampler_main, (uv + (tmpvar_9 * 4.0))).x - ((texture (sampler_blur1, (uv + \n (tmpvar_9 * 4.0)\n )).xyz * scale1) + bias1).x)\n * 0.206)) - 0.09);\n vec4 tmpvar_15;\n tmpvar_15.w = 1.0;\n tmpvar_15.xyz = ret_3;\n ret = tmpvar_15.xyz;\n }",comp:"float xlat_mutablelamp;\nvec2 xlat_mutablers0;\nvec2 xlat_mutablerss;\nvec2 xlat_mutableuv1;\n shader_body { \n vec3 tmpvar_1;\n tmpvar_1.x = q4;\n tmpvar_1.y = q5;\n tmpvar_1.z = q6;\n mat3 tmpvar_2;\n tmpvar_2[uint(0)].x = q20;\n tmpvar_2[uint(0)].y = q23;\n tmpvar_2[uint(0)].z = q26;\n tmpvar_2[1u].x = q21;\n tmpvar_2[1u].y = q24;\n tmpvar_2[1u].z = q27;\n tmpvar_2[2u].x = q22;\n tmpvar_2[2u].y = q25;\n tmpvar_2[2u].z = q28;\n vec2 tmpvar_3;\n tmpvar_3.x = q1;\n tmpvar_3.y = q2;\n vec2 uv_4;\n vec3 dots_5;\n vec3 ret_6;\n vec2 tmpvar_7;\n vec2 tmpvar_8;\n tmpvar_8 = (uv - 0.5);\n tmpvar_7 = (0.5 + (tmpvar_8 * vec2(1.1, 0.81)));\n vec2 tmpvar_9;\n tmpvar_9 = (uv - vec2(0.5, 0.5));\n uv_4 = (tmpvar_8 * aspect.xy);\n float tmpvar_10;\n float tmpvar_11;\n tmpvar_11 = (min (abs(\n (uv_4.y / uv_4.x)\n ), 1.0) / max (abs(\n (uv_4.y / uv_4.x)\n ), 1.0));\n float tmpvar_12;\n tmpvar_12 = (tmpvar_11 * tmpvar_11);\n tmpvar_12 = (((\n ((((\n ((((-0.01213232 * tmpvar_12) + 0.05368138) * tmpvar_12) - 0.1173503)\n * tmpvar_12) + 0.1938925) * tmpvar_12) - 0.3326756)\n * tmpvar_12) + 0.9999793) * tmpvar_11);\n tmpvar_12 = (tmpvar_12 + (float(\n (abs((uv_4.y / uv_4.x)) > 1.0)\n ) * (\n (tmpvar_12 * -2.0)\n + 1.570796)));\n tmpvar_10 = (tmpvar_12 * sign((uv_4.y / uv_4.x)));\n if ((abs(uv_4.x) > (1e-08 * abs(uv_4.y)))) {\n if ((uv_4.x < 0.0)) {\n if ((uv_4.y >= 0.0)) {\n tmpvar_10 += 3.141593;\n } else {\n tmpvar_10 = (tmpvar_10 - 3.141593);\n };\n };\n } else {\n tmpvar_10 = (sign(uv_4.y) * 1.570796);\n };\n xlat_mutablers0.x = ((tmpvar_10 / 3.1416) * 2.0);\n xlat_mutablers0.y = (0.02 / sqrt(dot (uv_4, uv_4)));\n vec2 tmpvar_13;\n tmpvar_13.x = xlat_mutablers0.x;\n tmpvar_13.y = (xlat_mutablers0.y + time);\n xlat_mutablerss = (tmpvar_13 * mat2(0.7, -0.7, 0.7, 0.7));\n vec4 tmpvar_14;\n tmpvar_14 = vec4(greaterThanEqual ((texture (sampler_pw_noise_lq, \n (xlat_mutablerss / 32.0)\n ) - 0.7), vec4(0.0, 0.0, 0.0, 0.0)));\n vec2 tmpvar_15;\n tmpvar_15 = abs((fract(\n (xlat_mutablerss * 8.0)\n ) - 0.5));\n vec2 tmpvar_16;\n tmpvar_16.x = (xlat_mutablers0.x * 2.0);\n tmpvar_16.y = (xlat_mutablers0.y + (time / 2.0));\n xlat_mutablerss = (tmpvar_16 * mat2(0.7, -0.7, 0.7, 0.7));\n vec4 tmpvar_17;\n tmpvar_17 = vec4(greaterThanEqual ((texture (sampler_pw_noise_lq, \n (xlat_mutablerss / 32.0)\n ) - 0.7), vec4(0.0, 0.0, 0.0, 0.0)));\n vec2 tmpvar_18;\n tmpvar_18 = abs((fract(\n (xlat_mutablerss * 8.0)\n ) - 0.5));\n xlat_mutablerss = tmpvar_18;\n dots_5 = (vec3((clamp (\n (0.04 / sqrt(dot (tmpvar_15, tmpvar_15)))\n , 0.0, 1.0) * tmpvar_14.x)) + (clamp (\n (0.04 / sqrt(dot (tmpvar_18, tmpvar_18)))\n , 0.0, 1.0) * tmpvar_17.x));\n dots_5 = (dots_5 * clamp ((0.04 / \n abs((0.01 / xlat_mutablers0.y))\n ), 0.0, 1.0));\n dots_5 = (dots_5 * (dots_5 * 2.0));\n vec2 tmpvar_19;\n tmpvar_19.x = -((tmpvar_9.y * -1024.0));\n tmpvar_19.y = (tmpvar_9.x * -1024.0);\n vec2 tmpvar_20;\n tmpvar_20.x = tmpvar_19.x;\n tmpvar_20.y = -(tmpvar_19.y);\n uv_4 = (vec2(-100.0, 100.0) * (tmpvar_20 / (\n (tmpvar_19.x * tmpvar_19.x)\n + \n (tmpvar_19.y * tmpvar_19.y)\n )).yx);\n uv_4 = (0.5 + ((\n (1.0 - abs(((\n fract((mix ((0.5 + \n ((tmpvar_7 - 0.5) * 2.0)\n ), (uv_4 + 0.5), vec2(0.5, 0.5)) * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.98));\n uv_4 = (((uv_4 - 0.5) * 0.9) + 0.5);\n xlat_mutableuv1 = ((uv_4 - tmpvar_3) * aspect.xy);\n float tmpvar_21;\n tmpvar_21 = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n vec3 tmpvar_22;\n tmpvar_22.xy = ((uv_4 - 0.5) * min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z)));\n tmpvar_22.z = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n float tmpvar_23;\n tmpvar_23 = clamp ((abs(\n ((1.0 - ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2).z) - clamp ((1.0 - (\n (texture (sampler_blur2, tmpvar_3).xyz * scale2)\n + bias2).z), 0.1, 0.4))\n ) + 0.2), 0.0, 1.0);\n vec3 tmpvar_24;\n tmpvar_24 = mix (texture (sampler_main, uv_4).xyz, ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1), vec3(tmpvar_23));\n float tmpvar_25;\n tmpvar_25 = clamp (((1.0 - \n exp(-(((texture (sampler_blur1, uv_4).xyz * scale1) + bias1).x))\n ) - 0.2), 0.0, 1.0);\n ret_6 = ((tmpvar_24.x * (0.2 + \n ((1.0 - tmpvar_23) * (1.0 - tmpvar_21))\n )) * (1.0 + (0.5 * \n sin((((tmpvar_22 / q7) * tmpvar_2) + tmpvar_1))\n )));\n vec3 tmpvar_26;\n tmpvar_26.xy = vec2(0.0, 1.0);\n tmpvar_26.z = (tmpvar_25 * 3.0);\n vec3 tmpvar_27;\n tmpvar_27 = mix (ret_6, tmpvar_26, vec3(tmpvar_25));\n xlat_mutablelamp = (((\n clamp ((1.0 - (4.0 * sqrt(\n dot (xlat_mutableuv1, xlat_mutableuv1)\n ))), 0.0, 1.0)\n * tmpvar_24.x) * clamp (\n (1.0 - (2.0 * mix (tmpvar_21, (1.0 - \n ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1)\n .z), 0.2)))\n , 0.0, 1.0)) * 1.8);\n ret_6 = (tmpvar_27 + ((1.0 - \n dot (tmpvar_27, vec3(0.32, 0.49, 0.29))\n ) * xlat_mutablelamp));\n ret_6 = (1.0 - exp((-2.0 * ret_6)));\n ret_6 = (ret_6 + (dots_5 * (1.0 + ret_6)));\n vec4 tmpvar_28;\n tmpvar_28.w = 1.0;\n tmpvar_28.xyz = ret_6;\n ret = tmpvar_28.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:3,wave_mode:4,additivewave:1,wave_dots:1,modwavealphabyvolume:1,wave_a:.331,wave_scale:.898,wave_smoothing:.108,wave_mystery:.1,modwavealphastart:.72,modwavealphaend:1.28,zoom:1.3345,wave_r:0,wave_g:.5,wave_b:.5,wave_y:.54,mv_x:24.8,mv_dy:.16,mv_l:1.5,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1,samples:352,usedots:1,additive:1,scaling:.03856,smoothing:.2,g:0},init_eqs_str:"a.t02=0;a.q1=0;a.ratio=0;a.ampl=0;a.x1=0;a.y1=0;",frame_eqs_str:"a.q1=a.bass_att;",point_eqs_str:"a.r=Math.abs(Math.sin(div(a.frame,38)));a.g=.5*Math.abs(Math.cos(div(a.frame,45)));a.b=.5*Math.abs(Math.sin(div(a.frame,133)));a.a=.3;a.t02+=div(a.q1,10);a.ratio=Math.sin(div(a.frame,49));a.ampl=.01+.4*sqr(Math.sin(div(a.frame,18))*Math.cos(div(a.frame,123)));a.x1=div(a.r-.5,15)+.5+a.ampl*Math.sin(6.28*a.sample);a.y1=div(a.b-.5,15)+.5+a.ampl*Math.cos(6.28*a.sample);a.x=a.x1+.2*(a.ampl+a.ratio)*Math.sin(6.28*a.sample*a.ratio*7.3);a.y=a.y1+.2*(a.ampl+a.ratio)*Math.cos(37.68*a.sample);\n"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"a.oldshift=0;a.shift=0;a.normalframez=0;a.crash=0;a.nex=0;a.rshift=0;a.q1=0;a.zoom1=0;",frame_eqs_str:"a.dx=0;a.oldshift=a.shift;a.normalframez+=1;a.shift=above(a.bass_att,1)*above(a.treb_att,.9);a.crash=Math.abs(a.oldshift-a.shift);a.nex=1*equal(a.rshift,0)+2*equal(a.rshift,1);a.rshift=.00001 0.9)) {\n ret_2.x = 0.0;\n };\n if ((ret_2.y > 0.9)) {\n ret_2.y = 0.0;\n };\n if ((ret_2.z > 0.9)) {\n ret_2.z = 0.0;\n };\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = ret_2;\n ret = tmpvar_7.xyz;\n }",comp:" shader_body { \n vec3 ret1_1;\n vec2 uv1_2;\n vec3 ret_3;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_main, uv);\n ret_3 = (tmpvar_4.xyz * (0.6 + (0.3 * \n sin(((uv.x * 10.0) + time))\n )));\n vec2 tmpvar_5;\n tmpvar_5.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_5.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_2 = ((0.5 * cos(\n (((uv - 0.5) * 1.5) + 1.6)\n )) - (3.0 * tmpvar_5));\n ret1_1 = ((0.3 * dot (tmpvar_4.xyz, vec3(0.32, 0.49, 0.29))) + ((\n clamp ((0.01 / sqrt(dot (uv1_2, uv1_2))), 0.0, 1.0)\n * \n mix (vec3(dot (((texture (sampler_blur2, uv).xyz * scale2) + bias2), vec3(0.32, 0.49, 0.29))), ret_3, pow (ret_3, vec3((0.05 + (mid_att * 0.03)))))\n ) * (\n (4.0 + bass)\n + \n (mid + treb_att)\n )));\n ret_3 = ret1_1;\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = ret1_1;\n ret = tmpvar_6.xyz;\n }"}},function(a,e){a.exports={baseVals:{rating:3,gammaadj:1,decay:.997,echo_zoom:.997,echo_orient:1,wave_thick:1,wave_brighten:0,darken:1,wave_a:.001,wave_scale:.01,wave_smoothing:.27,wave_mystery:-.38,modwavealphastart:.71,modwavealphaend:1.3,warpscale:1.331,zoom:.99951,warp:.01,ob_size:.5,ob_r:.01,ib_size:.26,ib_r:1,ib_g:1,ib_b:1,mv_x:64,mv_y:48,mv_l:.85,mv_r:.5,mv_g:.5,mv_b:.5,mv_a:0},shapes:[{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],waves:[{baseVals:{enabled:1},init_eqs_str:"",frame_eqs_str:"",point_eqs_str:"a.x=.5+.2*a.bass*Math.sin(20*a.sample*a.time*a.treb);a.y=.5+.2*a.bass*Math.cos(20*a.sample*a.time*a.treb);a.r=1+.5*Math.sin(.1*a.sample+10*a.time*a.bass);a.g=1+.5*Math.sin(2*a.sample+50*a.time*a.treb);a.b=1+.5*Math.sin(5*a.sample+20*a.time*a.mid);a.a=a.r;"},{baseVals:{enabled:0}},{baseVals:{enabled:0}},{baseVals:{enabled:0}}],init_eqs_str:"",frame_eqs_str:"a.warp=0;a.decay=.92;",pixel_eqs_str:"a.zoom+=.03*a.bass_att*a.bass_att*a.rad;a.rot+=a.rad*bitand(-2.5,5*Math.cos(a.time))*.01;",warp:" shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = texture (sampler_main, uv).xyz;\n ret = tmpvar_1.xyz;\n }",comp:" shader_body { \n vec2 uv1_1;\n vec3 ret_2;\n vec3 tmpvar_3;\n tmpvar_3 = texture (sampler_main, uv).xyz;\n vec2 tmpvar_4;\n tmpvar_4.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_4.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_1 = ((0.5 * cos(\n (((uv - 0.5) * 1.5) + 1.6)\n )) - (3.0 * tmpvar_4));\n ret_2 = (0.8 * ((0.3 * \n dot (tmpvar_3, vec3(0.32, 0.49, 0.29))\n ) + (\n (clamp ((0.01 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0) * tmpvar_3)\n * \n ((4.0 + bass) + (mid + treb_att))\n )));\n ret_2 = (ret_2 * 0.77);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }"}},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(a,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=_(t(6)),n=_(t(7));function _(a){return a&&a.__esModule?a:{default:a}}var s={};s["$$$ Royal - Mashup (197)"]=t(35),s["$$$ Royal - Mashup (220)"]=t(36),s["$$$ Royal - Mashup (431)"]=t(37),s["_Aderrasi - Wanderer in Curved Space - mash0000 - faclempt kibitzing meshuggana schmaltz (Geiss color mix)"]=t(38),s["_Geiss - Artifact 01"]=t(39),s["_Geiss - Desert Rose 2"]=t(40),s["_Geiss - untitled"]=t(41),s._Mig_049=t(42),s._Mig_085=t(43),s["_Rovastar + Geiss - Hurricane Nightmare (Posterize Mix)"]=t(44),s["Aderrasi + Geiss - Airhandler (Kali Mix) - Canvas Mix"]=t(45),s["Aderrasi - Potion of Spirits"]=t(20),s["Aderrasi - Songflower (Moss Posy)"]=t(21),s["Aderrasi - Storm of the Eye (Thunder) - mash0000 - quasi pseudo meta concentrics"]=t(46),s["An AdamFX n Martin Infusion 2 flexi - Why The Sky Looks Diffrent Today - AdamFx n Martin Infusion - Tack Tile Disfunction B"]=t(47),s["cope + martin - mother-of-pearl"]=t(48),s["Cope - The Neverending Explosion of Red Liquid Fire"]=t(49),s["Eo.S. + Phat - cubetrace - v2"]=t(22),s["Eo.S. + Zylot - skylight (Stained Glass Majesty mix)"]=t(23),s["Eo.S. - glowsticks v2 05 and proton lights (+Krashβ€²s beat code) _Phat_remix02b"]=t(24),s["fiShbRaiN + Flexi - witchcraft 2.0"]=t(50),s["flexi + amandio c - organic [random mashup]"]=t(51),s["flexi + amandio c - organic12-3d-2.milk"]=t(52),s["Flexi + amandio c - piercing 05 - Kopie (2) - Kopie"]=t(53),s["flexi + fishbrain - neon mindblob grafitti"]=t(54),s["flexi + geiss - pogo cubes vs. tokamak vs. game of life [stahls jelly 4.5 finish]"]=t(55),s["Flexi + Martin - astral projection"]=t(56),s["Flexi + Martin - cascading decay swing"]=t(57),s["Flexi + stahlregen - jelly showoff parade"]=t(58),s["Flexi - alien fish pond"]=t(59),s["Flexi - area 51"]=t(60),s["flexi - bouncing balls [double mindblob neon mix]"]=t(61),s["Flexi - infused with the spiral"]=t(62),s["Flexi - mindblob [shiny mix]"]=t(63),s["Flexi - mindblob mix"]=t(64),s["flexi - mom, why the sky looks different today"]=t(65),s["flexi - patternton, district of media, capitol of the united abstractions of fractopia"]=t(66),s["Flexi - predator-prey-spirals"]=t(67),s["Flexi - smashing fractals [acid etching mix]"]=t(68),s["flexi - swing out on the spiral"]=t(69),s["Flexi - truly soft piece of software - this is generic texturing (Jelly) "]=t(70),s["flexi - what is the matrix"]=t(71),s["Flexi, fishbrain, Geiss + Martin - tokamak witchery"]=t(72),s["Flexi, martin + geiss - dedicated to the sherwin maxawow"]=t(73),s["Fumbling_Foo & Flexi, Martin, Orb, Unchained - Star Nova v7b"]=t(74),s["Geiss + Flexi + Martin - disconnected"]=t(75),s["Geiss - Cauldron - painterly 2 (saturation remix)"]=t(76),s["Geiss - Reaction Diffusion 2"]=t(77),s["Geiss - Spiral Artifact"]=t(78),s["Geiss - Thumb Drum"]=t(79),s["Geiss, Flexi + Stahlregen - Thumbdrum Tokamak [crossfiring aftermath jelly mashup]"]=t(80),s["Goody - The Wild Vort"]=t(81),s["high-altitude basket unraveling - singh grooves nitrogen argon nz+"]=t(82),s["Idiot - Star Of Annon"]=t(25),s["Krash + Illusion - Spiral Movement"]=t(26),s["martin + flexi - diamond cutter [prismaticvortex.com] - camille - i wish i wish i wish i was constrained"]=t(83),s["Martin - acid wiring"]=t(84),s["martin - angel flight"]=t(85),s["martin - another kind of groove"]=t(86),s["martin - bombyx mori"]=t(87),s["martin - castle in the air"]=t(88),s["martin - chain breaker"]=t(89),s["Martin - charisma"]=t(90),s["martin - disco mix 4"]=t(91),s["martin - extreme heat"]=t(92),s["martin - frosty caves 2"]=t(93),s["martin - fruit machine"]=t(94),s["martin - ghost city"]=t(95),s["martin - glass corridor"]=t(96),s["martin - infinity (2010 update)"]=t(27),s["Martin - liquid arrows"]=t(97),s["martin - mandelbox explorer - high speed demo version"]=t(98),s["martin - mucus cervix"]=t(99),s["Martin - QBikal - Surface Turbulence IIb"]=t(100),s["martin - reflections on black tiles"]=t(101),s["martin - stormy sea (2010 update)"]=t(102),s["martin - The Bridge of Khazad-Dum"]=t(103),s["martin - witchcraft reloaded"]=t(104),s["martin [shadow harlequins shape code] - fata morgana"]=t(105),s["martin, flexi, fishbrain + sto - enterstate [random mashup]"]=t(106),s["Milk Artist At our Best - FED - SlowFast Ft AdamFX n Martin - HD CosmoFX"]=t(107),s["ORB - Waaa"]=t(108),s["Phat+fiShbRaiN+Eo.S_Mandala_Chasers_remix"]=t(28),s["Rovastar + Loadus + Geiss - FractalDrop (Triple Mix)"]=t(109),s["Rovastar - Oozing Resistance"]=t(29),s["sawtooth grin roam"]=t(110),s["shifter - dark tides bdrv mix 2"]=t(111),s["suksma - heretical crosscut playpen"]=t(112),s["suksma - Rovastar - Sunflower Passion (Enlightment Mix)_Phat_edit + flexi und martin shaders - circumflex in character classes in regular expression"]=t(113),s["suksma - uninitialized variabowl (hydroponic chronic)"]=t(114),s["suksma - vector exp 1 - couldnβ€²t not"]=t(115),s["TonyMilkdrop - Leonardo Da Vinci's Balloon [Flexi - merry-go-round + techstyle]"]=t(116),s["TonyMilkdrop - Magellan's Nebula [Flexi - you enter first + multiverse]"]=t(117),s["Unchained & Rovastar - Wormhole Pillars (Hall of Shadows mix)"]=t(30),s["Unchained - Rewop"]=t(31),s["Unchained - Unified Drag 2"]=t(32),s["yin - 191 - Temporal singularities"]=t(33),s["Zylot - Paint Spill (Music Reactive Paint Mix)"]=t(118),s["Zylot - Star Ornament"]=t(34),s["Zylot - True Visionary (Final Mix)"]=t(119);var v=function(){function a(){(0,r.default)(this,a)}return(0,n.default)(a,null,[{key:"getPresets",value:function(){return s}}]),a}();e.default=v,a.exports=v}])}); \ No newline at end of file +!(function (a, e) { + 'object' == typeof exports && 'object' == typeof module + ? (module.exports = e()) + : 'function' == typeof define && define.amd + ? define('butterchurnPresets', [], e) + : 'object' == typeof exports + ? (exports.butterchurnPresets = e()) + : (a.butterchurnPresets = e()); +})('undefined' != typeof self ? self : this, function () { + return (function (a) { + var e = {}; + function t(r) { + if (e[r]) return e[r].exports; + var n = (e[r] = { i: r, l: !1, exports: {} }); + return (a[r].call(n.exports, n, n.exports, t), (n.l = !0), n.exports); + } + return ( + (t.m = a), + (t.c = e), + (t.d = function (a, e, r) { + t.o(a, e) || Object.defineProperty(a, e, { configurable: !1, enumerable: !0, get: r }); + }), + (t.n = function (a) { + var e = + a && a.__esModule + ? function () { + return a.default; + } + : function () { + return a; + }; + return (t.d(e, 'a', e), e); + }), + (t.o = function (a, e) { + return Object.prototype.hasOwnProperty.call(a, e); + }), + (t.p = ''), + t((t.s = 165)) + ); + })([ + function (a, e, t) { + a.exports = !t(5)(function () { + return ( + 7 != + Object.defineProperty({}, 'a', { + get: function () { + return 7; + }, + }).a + ); + }); + }, + function (a, e) { + a.exports = function (a) { + return 'object' == typeof a ? null !== a : 'function' == typeof a; + }; + }, + function (a, e) { + var t = (a.exports = + 'undefined' != typeof window && window.Math == Math + ? window + : 'undefined' != typeof self && self.Math == Math + ? self + : Function('return this')()); + 'number' == typeof __g && (__g = t); + }, + function (a, e) { + var t = (a.exports = { version: '2.5.3' }); + 'number' == typeof __e && (__e = t); + }, + function (a, e, t) { + var r = t(15), + n = t(16), + _ = t(18), + s = Object.defineProperty; + e.f = t(0) + ? Object.defineProperty + : function (a, e, t) { + if ((r(a), (e = _(e, !0)), r(t), n)) + try { + return s(a, e, t); + } catch (a) {} + if ('get' in t || 'set' in t) throw TypeError('Accessors not supported!'); + return ('value' in t && (a[e] = t.value), a); + }; + }, + function (a, e) { + a.exports = function (a) { + try { + return !!a(); + } catch (a) { + return !0; + } + }; + }, + function (a, e, t) { + 'use strict'; + ((e.__esModule = !0), + (e.default = function (a, e) { + if (!(a instanceof e)) throw new TypeError('Cannot call a class as a function'); + })); + }, + function (a, e, t) { + 'use strict'; + e.__esModule = !0; + var r, + n = t(8), + _ = (r = n) && r.__esModule ? r : { default: r }; + e.default = (function () { + function a(a, e) { + for (var t = 0; t < e.length; t++) { + var r = e[t]; + ((r.enumerable = r.enumerable || !1), + (r.configurable = !0), + 'value' in r && (r.writable = !0), + (0, _.default)(a, r.key, r)); + } + } + return function (e, t, r) { + return (t && a(e.prototype, t), r && a(e, r), e); + }; + })(); + }, + function (a, e, t) { + a.exports = { default: t(9), __esModule: !0 }; + }, + function (a, e, t) { + t(10); + var r = t(3).Object; + a.exports = function (a, e, t) { + return r.defineProperty(a, e, t); + }; + }, + function (a, e, t) { + var r = t(11); + r(r.S + r.F * !t(0), 'Object', { defineProperty: t(4).f }); + }, + function (a, e, t) { + var r = t(2), + n = t(3), + _ = t(12), + s = t(14), + v = function (a, e, t) { + var m, + i, + p, + b = a & v.F, + l = a & v.G, + x = a & v.S, + o = a & v.P, + d = a & v.B, + u = a & v.W, + c = l ? n : n[e] || (n[e] = {}), + y = c.prototype, + h = l ? r : x ? r[e] : (r[e] || {}).prototype; + for (m in (l && (t = e), t)) + ((i = !b && h && void 0 !== h[m]) && m in c) || + ((p = i ? h[m] : t[m]), + (c[m] = + l && 'function' != typeof h[m] + ? t[m] + : d && i + ? _(p, r) + : u && h[m] == p + ? (function (a) { + var e = function (e, t, r) { + if (this instanceof a) { + switch (arguments.length) { + case 0: + return new a(); + case 1: + return new a(e); + case 2: + return new a(e, t); + } + return new a(e, t, r); + } + return a.apply(this, arguments); + }; + return ((e.prototype = a.prototype), e); + })(p) + : o && 'function' == typeof p + ? _(Function.call, p) + : p), + o && (((c.virtual || (c.virtual = {}))[m] = p), a & v.R && y && !y[m] && s(y, m, p))); + }; + ((v.F = 1), + (v.G = 2), + (v.S = 4), + (v.P = 8), + (v.B = 16), + (v.W = 32), + (v.U = 64), + (v.R = 128), + (a.exports = v)); + }, + function (a, e, t) { + var r = t(13); + a.exports = function (a, e, t) { + if ((r(a), void 0 === e)) return a; + switch (t) { + case 1: + return function (t) { + return a.call(e, t); + }; + case 2: + return function (t, r) { + return a.call(e, t, r); + }; + case 3: + return function (t, r, n) { + return a.call(e, t, r, n); + }; + } + return function () { + return a.apply(e, arguments); + }; + }; + }, + function (a, e) { + a.exports = function (a) { + if ('function' != typeof a) throw TypeError(a + ' is not a function!'); + return a; + }; + }, + function (a, e, t) { + var r = t(4), + n = t(19); + a.exports = t(0) + ? function (a, e, t) { + return r.f(a, e, n(1, t)); + } + : function (a, e, t) { + return ((a[e] = t), a); + }; + }, + function (a, e, t) { + var r = t(1); + a.exports = function (a) { + if (!r(a)) throw TypeError(a + ' is not an object!'); + return a; + }; + }, + function (a, e, t) { + a.exports = + !t(0) && + !t(5)(function () { + return ( + 7 != + Object.defineProperty(t(17)('div'), 'a', { + get: function () { + return 7; + }, + }).a + ); + }); + }, + function (a, e, t) { + var r = t(1), + n = t(2).document, + _ = r(n) && r(n.createElement); + a.exports = function (a) { + return _ ? n.createElement(a) : {}; + }; + }, + function (a, e, t) { + var r = t(1); + a.exports = function (a, e) { + if (!r(a)) return a; + var t, n; + if (e && 'function' == typeof (t = a.toString) && !r((n = t.call(a)))) return n; + if ('function' == typeof (t = a.valueOf) && !r((n = t.call(a)))) return n; + if (!e && 'function' == typeof (t = a.toString) && !r((n = t.call(a)))) return n; + throw TypeError("Can't convert object to primitive value"); + }; + }, + function (a, e) { + a.exports = function (a, e) { + return { enumerable: !(1 & a), configurable: !(2 & a), writable: !(4 & a), value: e }; + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.42, + decay: 1, + echo_zoom: 0.999823, + echo_alpha: 0.5, + echo_orient: 1, + wave_mode: 5, + wave_thick: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001185, + wave_scale: 0.325446, + wave_smoothing: 0.9, + modwavealphastart: 0.5, + modwavealphaend: 1, + warpanimspeed: 2.630064, + warpscale: 3.209168, + zoomexp: 1.000158, + dx: 1e-5, + dy: 1e-5, + warp: 0.01, + wave_r: 0.5, + wave_g: 0.5, + wave_b: 0.5, + ob_size: 0.005, + ob_a: 0.5, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 0.1, + mv_x: 6.4, + mv_y: 4.8, + mv_l: 5, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: 'a.thresh=0;a.dx_r=0;a.dy_r=0;a.tg1=0;a.tg2=0;a.tg3=0;a.six=0;', + frame_eqs_str: + 'a.wave_r=.5+.5*Math.sin(1.6*a.time);a.wave_g=.5+.5*Math.sin(4.1*a.time);a.wave_b=-1+(1-a.wave_r+1-a.wave_g);a.warp=2;a.ob_r+=a.wave_b*above(Math.sin(.1*a.time),0);a.ob_b+=a.wave_g*above(Math.sin(.1*a.time),0);a.ob_g+=a.wave_r*above(Math.sin(.1*a.time),0);a.ob_r+=a.wave_g*below(Math.sin(.1*a.time),0);a.ob_b+=a.wave_r*below(Math.sin(.1*a.time),0);a.ob_g+=a.wave_b*below(Math.sin(.1*a.time),0);', + pixel_eqs_str: + 'a.thresh=2*above(a.bass_att,a.thresh)+(1-above(a.bass_att,a.thresh))*(.96*(a.thresh-1.3)+1.3);a.dx_r=.05*equal(a.thresh,2)*Math.sin(5*a.time)+(1-equal(a.thresh,2))*a.dx_r;a.dy_r=.056*equal(a.thresh,2)*Math.sin(6*a.time)+(1-equal(a.thresh,2))*a.dy_r;a.tg1=Math.abs(Math.sin(a.time));a.tg2=22*above(a.tg1,.75)+12*below(a.tg1,.25)+18*above(a.tg1,.25)*below(a.tg1,.5)+12*above(a.tg1,.5)*below(a.tg1,.75);a.tg3=.00001 1.0)\n ) * (\n (tmpvar_8 * -2.0)\n + 1.570796)));\n tmpvar_6 = (tmpvar_8 * sign((uv_1.y / uv_1.x)));\n if ((abs(uv_1.x) > (1e-08 * abs(uv_1.y)))) {\n if ((uv_1.x < 0.0)) {\n if ((uv_1.y >= 0.0)) {\n tmpvar_6 += 3.141593;\n } else {\n tmpvar_6 = (tmpvar_6 - 3.141593);\n };\n };\n } else {\n tmpvar_6 = (sign(uv_1.y) * 1.570796);\n };\n xlat_mutablers0.x = ((tmpvar_6 / 3.1416) * 2.0);\n xlat_mutablers0.y = (0.03 / sqrt(dot (uv_1, uv_1)));\n ret1_3 = vec3(0.0, 0.0, 0.0);\n for (int n_2 = 0; n_2 <= 10; n_2++) {\n float tmpvar_9;\n tmpvar_9 = fract((-(q9) + (\n float(n_2)\n / 10.0)));\n xlat_mutableang2 = (((q1 * 3.14) * float(n_2)) / 10.0);\n float tmpvar_10;\n tmpvar_10 = cos(xlat_mutableang2);\n float tmpvar_11;\n tmpvar_11 = sin(xlat_mutableang2);\n mat2 tmpvar_12;\n tmpvar_12[uint(0)].x = tmpvar_10;\n tmpvar_12[uint(0)].y = -(tmpvar_11);\n tmpvar_12[1u].x = tmpvar_11;\n tmpvar_12[1u].y = tmpvar_10;\n xlat_mutableuv2 = (uv_1 * ((q13 * tmpvar_9) * tmpvar_12));\n ret1_3 = max (ret1_3, (texture (sampler_main, (xlat_mutableuv2 + 0.5)).xyz * (1.0 - tmpvar_9)));\n };\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = ((ret1_3 * 2.0) + ((\n (bass_att * xlat_mutablers0.y)\n * texture (sampler_main, \n ((uv_1 * q12) + vec2(0.5, 0.0))\n ).yzx) * clamp (\n (1.0 - (ret1_3 * 32.0))\n , 0.0, 1.0)));\n ret = tmpvar_13.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 0.965, + echo_zoom: 1.483827, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + wave_brighten: 0, + wrap: 0, + darken_center: 1, + darken: 1, + wave_a: 0.001, + wave_scale: 1.285751, + wave_smoothing: 0.63, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpanimspeed: 0.01, + warpscale: 1.470245, + zoomexp: 4.778023, + zoom: 0.998162, + warp: 0.01, + sx: 1.001828, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0.005, + ob_r: 1, + ob_g: 0.5, + ob_b: 0.5, + ob_a: 1, + ib_size: 0.5, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 4.800001, + mv_dx: 0.4, + mv_l: 1, + mv_r: 0, + mv_g: 0.5, + mv_a: 0.1, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 3, + additive: 1, + thickoutline: 1, + textured: 1, + x: 1, + y: 0.59, + rad: 0.559231, + ang: 3.39292, + tex_zoom: 100, + r: 0, + g: 1, + b: 1, + g2: 0, + border_r: 0, + border_g: 0, + border_b: 0, + border_a: 1, + }, + init_eqs_str: '', + frame_eqs_str: 'a.x=.1*Math.sin(div(a.time,10))+.5+.1*a.treb_att;', + }, + { baseVals: { enabled: 0 } }, + { + baseVals: { + enabled: 1, + sides: 6, + textured: 1, + x: 0.3, + y: 0.7, + rad: 1.089252, + ang: 0.816814, + tex_ang: 3.141592, + tex_zoom: 0.504215, + g: 1, + b: 1, + r2: 1, + b2: 1, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: '', + }, + { + baseVals: { + enabled: 1, + sides: 3, + textured: 1, + rad: 0.284278, + ang: 3.141593, + tex_ang: 4.900885, + tex_zoom: 2.987755, + g: 1, + b: 1, + r2: 0.95, + b2: 1, + a2: 1, + border_r: 0, + border_g: 0, + border_b: 0, + border_a: 1, + }, + init_eqs_str: 'a["var"]=0;', + frame_eqs_str: + 'a.ang=div(a.time,10);a.tex_zoom=3.4+.03*a.bass;a["var"]=above(a.bass_att,.7);a.a=a["var"];a.a2=a["var"];a.border_a=a["var"];', + }, + ], + waves: [ + { + baseVals: { enabled: 1, usedots: 1, thick: 1, additive: 1, r: 0, a: 0.06 }, + init_eqs_str: + 'a.px=0;a.xoffset2=0;a.py=0;a.xoffset1=0;a.pheight=0;a.pphase=0;a.yspout=0;a.pphase2=0;a.xspout=0;a.lrorient=0;a.yheight=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.xspout=.5;a.yspout=-.01;a.pphase=9999*a.sample*a.sample*.0001;a.pphase2=.1+.01*mod(3349*a.sample*a.sample,100);a.pheight=.002*mod(9893*a.sample,100);a.yheight=.01*mod(1231*a.sample*a.sample,100);a.r=.01*mod(5454*a.sample,100)*Math.abs(Math.sin(.25*a.time));a.g=.01*mod(9954*a.sample,100);a.xoffset1=Math.cos(a.time*a.pphase2+a.pphase)*a.pheight;a.xoffset2=-1*Math.cos(a.time*a.pphase2+a.pphase)*a.pheight;a.lrorient=.00001 1.0)\n ) * (\n (tmpvar_8 * -2.0)\n + 1.570796)));\n tmpvar_6 = (tmpvar_8 * sign((uv_1.y / uv_1.x)));\n if ((abs(uv_1.x) > (1e-08 * abs(uv_1.y)))) {\n if ((uv_1.x < 0.0)) {\n if ((uv_1.y >= 0.0)) {\n tmpvar_6 += 3.141593;\n } else {\n tmpvar_6 = (tmpvar_6 - 3.141593);\n };\n };\n } else {\n tmpvar_6 = (sign(uv_1.y) * 1.570796);\n };\n xlat_mutablers0.x = (((tmpvar_6 / 3.1416) * 6.0) * q28);\n xlat_mutablers0.y = inversesqrt(dot (uv_1, uv_1));\n vec2 tmpvar_9;\n tmpvar_9.x = (xlat_mutablers0.x + (q9 * 8.0));\n tmpvar_9.y = (xlat_mutablers0.y + ((q9 * q28) * 4.0));\n xlat_mutablerss = (tmpvar_9 / 12.0);\n vec2 tmpvar_10;\n tmpvar_10.x = q5;\n tmpvar_10.y = q6;\n ofs_2 = (0.1 * tmpvar_10.yx);\n float tmpvar_11;\n float tmpvar_12;\n tmpvar_12 = -(q9);\n tmpvar_11 = fract(tmpvar_12);\n mat2 tmpvar_13;\n tmpvar_13[uint(0)].x = 1.0;\n tmpvar_13[uint(0)].y = -0.0;\n tmpvar_13[1u].x = 0.0;\n tmpvar_13[1u].y = 1.0;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_11)\n * tmpvar_13)) * aspect.yx);\n vec2 tmpvar_14;\n tmpvar_14 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_14).xyz + ((texture (sampler_blur1, tmpvar_14).xyz * scale1) + bias1));\n ret1_3 = max (vec3(0.0, 0.0, 0.0), ((xlat_mutableneu * \n (1.0 - (tmpvar_11 * tmpvar_11))\n ) * 2.0));\n float tmpvar_15;\n tmpvar_15 = fract((tmpvar_12 + 0.3333333));\n mat2 tmpvar_16;\n tmpvar_16[uint(0)].x = -0.4990803;\n tmpvar_16[uint(0)].y = -0.8665558;\n tmpvar_16[1u].x = 0.8665558;\n tmpvar_16[1u].y = -0.4990803;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_15)\n * tmpvar_16)) * aspect.yx);\n vec2 tmpvar_17;\n tmpvar_17 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_17).xyz + ((texture (sampler_blur1, tmpvar_17).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_15 * tmpvar_15))\n ) * 2.0));\n float tmpvar_18;\n tmpvar_18 = fract((tmpvar_12 + 0.6666667));\n mat2 tmpvar_19;\n tmpvar_19[uint(0)].x = -0.5018377;\n tmpvar_19[uint(0)].y = 0.8649619;\n tmpvar_19[1u].x = -0.8649619;\n tmpvar_19[1u].y = -0.5018377;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_18)\n * tmpvar_19)) * aspect.yx);\n vec2 tmpvar_20;\n tmpvar_20 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_20).xyz + ((texture (sampler_blur1, tmpvar_20).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_18 * tmpvar_18))\n ) * 2.0));\n float tmpvar_21;\n tmpvar_21 = fract((tmpvar_12 + 1.0));\n mat2 tmpvar_22;\n tmpvar_22[uint(0)].x = 0.9999949;\n tmpvar_22[uint(0)].y = 0.003185092;\n tmpvar_22[1u].x = -0.003185092;\n tmpvar_22[1u].y = 0.9999949;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_21)\n * tmpvar_22)) * aspect.yx);\n vec2 tmpvar_23;\n tmpvar_23 = fract(((xlat_mutableuv2 + 0.5) + ofs_2));\n xlat_mutableneu = (texture (sampler_main, tmpvar_23).xyz + ((texture (sampler_blur1, tmpvar_23).xyz * scale1) + bias1));\n ret1_3 = max (ret1_3, ((xlat_mutableneu * \n (1.0 - (tmpvar_21 * tmpvar_21))\n ) * 2.0));\n vec2 tmpvar_24;\n tmpvar_24.x = (ret1_3.x + ret1_3.z);\n tmpvar_24.y = (ret1_3.x - ret1_3.y);\n vec4 tmpvar_25;\n tmpvar_25.w = 1.0;\n tmpvar_25.xyz = ((ret1_3 + (\n ((bass_att * 0.004) / sqrt(dot (uv_1, uv_1)))\n * roam_sin).xyz) + ((2.0 * \n (bass_att * ((texture (sampler_blur1, fract(\n (xlat_mutablerss + (tmpvar_24 / 2.0))\n )).xyz * scale1) + bias1).zxy)\n ) * clamp (\n (1.0 - (ret1_3 * 4.0))\n , 0.0, 1.0)));\n ret = tmpvar_25.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.14, + decay: 1, + echo_zoom: 1, + wave_mode: 6, + wave_thick: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 1.17, + wave_scale: 0.797, + wave_smoothing: 0, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpscale: 1.331, + zoomexp: 0.9995, + zoom: 0.9998, + rot: 0.02, + dy: -0.008, + warp: 0.01, + sx: 1.0098, + wave_r: 0.5, + wave_g: 0.5, + wave_b: 0.5, + wave_x: 0.9, + ob_size: 0.005, + ob_a: 0.8, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 44.8, + mv_y: 38.4, + mv_l: 5, + mv_g: 0.91, + mv_b: 0.71, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.q12=0;a.q18=0;a.q6=0;a.bass_thresh=0;a.wg=0;a.q11=0;a.q10=0;a.wb=0;a.q17=0;a.vol=0;a.q2=0;a.q3=0;a.wr=0;a.q7=0;a.q8=0;', + frame_eqs_str: + 'a.wave_r+=.3*Math.sin(50*a.vol);a.wave_b+=.3*Math.sin(20*a.vol);a.wave_g+=.5*Math.sin(35*a.vol);a.q8=a.wave_r;a.q7=a.wave_b;a.q6=a.wave_g;a.wr=.5+.4*(.6*Math.sin(1.1*a.time)+.4*Math.sin(.8*a.time));a.wb=.5+.4*(.6*Math.sin(1.6*a.time)+.4*Math.sin(.5*a.time));a.wg=.5+.4*(.6*Math.sin(1.34*a.time)+.4*Math.sin(.4*a.time));a.monitor=a.wg;a.q10=a.wr;a.q11=a.wb;a.q12=a.wg;a.q18=.007*Math.sin(.1*a.time);a.q17=-.007*Math.sin(.254*a.time);a.q2=a.bass_thresh;a.vol=.25*(a.bass+a.mid+a.treb);\na.vol*=a.vol;a.q3=a.vol;a.warp=0;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec3 noise3_1;\n vec3 tmpvar_2;\n tmpvar_2 = (texture (sampler_main, uv).xyz + ((texture (sampler_blur1, uv).xyz * scale1) + bias1));\n vec2 tmpvar_3;\n tmpvar_3 = (0.5 + ((\n (uv - vec2(0.0, 1.0))\n - 0.5) * (1.0 + \n (tmpvar_2.y * 0.03)\n )));\n vec2 tmpvar_4;\n tmpvar_4.x = (tmpvar_3.x + pow (tmpvar_2.x, 0.0));\n tmpvar_4.y = (tmpvar_3.y + pow (tmpvar_2.x, 0.005));\n noise3_1 = (texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * texsize_noise_lq.zw) + rand_frame.xy)).xyz * fract(q15));\n vec3 tmpvar_5;\n tmpvar_5 = (noise3_1 * (vec3(1.0, 1.0, 1.0) - vec3(fract(\n (q3 * 0.5)\n ))));\n noise3_1 = tmpvar_5;\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_main, fract(tmpvar_4));\n vec3 tmpvar_7;\n tmpvar_7.x = q10;\n tmpvar_7.y = q11;\n tmpvar_7.z = q12;\n vec3 tmpvar_8;\n tmpvar_8 = mix (tmpvar_5, tmpvar_7, tmpvar_6.xxx);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = (tmpvar_6.xyz + clamp ((\n (tmpvar_6.yzx * tmpvar_8.zxy)\n - \n (tmpvar_6.zxy * tmpvar_8.yzx)\n ), 0.0, 1.0));\n ret = tmpvar_9.xyz;\n }', + comp: ' shader_body { \n vec2 uv1_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n vec2 tmpvar_4;\n tmpvar_4.x = (texture (sampler_main, (uv - tmpvar_2)).xyz - texture (sampler_main, (uv + tmpvar_2)).xyz).x;\n tmpvar_4.y = (texture (sampler_main, (uv - tmpvar_3)).xyz - texture (sampler_main, (uv + tmpvar_3)).xyz).x;\n uv1_1 = ((0.3 * cos(\n ((uv - 0.5) * 2.0)\n )) - tmpvar_4);\n float tmpvar_5;\n tmpvar_5 = clamp ((0.04 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0);\n uv1_1 = ((0.3 * cos(\n (uv1_1 * 12.0)\n )) - (9.0 * tmpvar_4));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = (tmpvar_5 + ((texture (sampler_main, uv).xyz * 12.0) * vec3(clamp (\n (0.04 / sqrt(dot (uv1_1, uv1_1)))\n , 0.0, 1.0))));\n ret = tmpvar_6.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.14, + decay: 1, + echo_zoom: 1, + wave_mode: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.179, + wave_smoothing: 0, + wave_mystery: 0.3, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpscale: 1.331, + zoomexp: 0.8195, + zoom: 1.0697, + dy: 0.006, + warp: 0.01, + sx: 0.9996, + wave_g: 0, + wave_b: 0, + ob_a: 0.8, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 0, + mv_y: 0, + mv_l: 1, + mv_g: 0.91, + mv_b: 0.71, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.q12=0;a.q18=0;a.q6=0;a.q5=0;a.bass_thresh=0;a.wg=0;a.q11=0;a.q10=0;a.wb=0;a.q17=0;a.vol=0;a.q2=0;a.q3=0;a.wr=0;a.q7=0;a.mtime=0;a.q8=0;', + frame_eqs_str: + 'a.bass_thresh=2*above(a.bass_att,a.bass_thresh)+(1-above(a.bass_att,a.bass_thresh))*(.91*(a.bass_thresh-1.3)+1.3);a.wave_r=.5+.5*(.6*Math.sin(1.3*a.time)+.4*Math.sin(.98*a.time));a.wave_b=.5+.5*(.6*Math.sin(1.1*a.time)+.4*Math.sin(.78*a.time));a.wave_g=.5+.5*(.6*Math.sin(1.2*a.time)+.4*Math.sin(.6*a.time));a.q8=a.wave_r;a.q7=a.wave_b;a.q6=a.wave_g;a.wr=.5+.4*(.6*Math.sin(.2*a.time)+.4*Math.sin(.8*a.time));a.wb=.5+.4*(.6*Math.sin(.377*a.time)+.4*Math.sin(.5*a.time));a.wg=.5+\n.4*(.6*Math.sin(.7*a.time)+.4*Math.sin(.4*a.time));a.q10=a.wr;a.q11=a.wb;a.q12=a.wg;a.q10=.8;a.q11=.2;a.q12=.1;a.q18=.01*Math.sin(.1*a.mtime);a.q17=-.01*Math.sin(.254*a.mtime);a.q2=a.bass_thresh;a.vol=.25*(a.bass+a.mid+a.treb);a.vol*=a.vol;a.q3=a.vol;a.q5=.5*a.vol;a.mtime+=.01*a.vol;a.q2=.25*a.mtime;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec3 noise2_1;\n vec3 ret_2;\n vec3 tmpvar_3;\n tmpvar_3 = (((texture (sampler_blur1, uv).xyz * scale1) + bias1) + texture (sampler_main, uv).xyz);\n vec2 tmpvar_4;\n tmpvar_4 = (0.5 + ((uv - 0.5) * (1.0 + \n (tmpvar_3.y * 0.05)\n )));\n vec2 tmpvar_5;\n tmpvar_5.x = (tmpvar_4.x + pow (tmpvar_3.x, q17));\n tmpvar_5.y = (tmpvar_4.y + pow (tmpvar_3.x, q18));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_fc_main, fract(tmpvar_5));\n vec3 tmpvar_7;\n tmpvar_7.x = q10;\n tmpvar_7.y = q11;\n tmpvar_7.z = q12;\n noise2_1 = (texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * texsize_noise_lq.zw) + rand_frame.xy)).xyz + ((tmpvar_7 * vec3(rad)) * vol));\n vec3 a_8;\n a_8 = (1.0 - tmpvar_6.xyz);\n ret_2 = (tmpvar_6.xyz + (0.3 * clamp (\n ((a_8.yzx * noise2_1.zxy) - (a_8.zxy * noise2_1.yzx))\n , 0.0, 1.0)));\n ret_2 = (ret_2 * 0.97);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ret_2;\n ret = tmpvar_9.xyz;\n }', + comp: ' shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz * vec3(0.9, 0.3, 0.5));\n ret_1 = (ret_1 * 1.34);\n ret_1 = (ret_1 * ret_1);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.28, + decay: 0.8, + echo_zoom: 1, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + brighten: 1, + wave_a: 0.001, + wave_scale: 1.286, + wave_smoothing: 0.63, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + zoomexp: 3.04777, + zoom: 1.0173, + warp: 0.01605, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0, + ob_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, thick: 1, additive: 1, g: 0, b: 0 }, + init_eqs_str: 'a.ma=0;a.mx=0;a.my=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=\ndiv(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);a.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*\na.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):\na.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);', + frame_eqs_str: + 'a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*\na.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;\na.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;\na.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?\n-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+\nMath.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;a.bb=.99*a.bb+.02*a.bass;a.mm=.99*a.mm+.02*a.mid;a.tt=.99*a.tt+.02*a.treb;a.mx=Math.max(Math.max(a.bb,a.mm),a.tt);a.mn=Math.min(Math.min(a.bb,a.mm),a.tt);a.h1=div(a.bb-a.mn,a.mx-a.mn);a.h2=div(a.mm-a.mn,a.mx-a.mn);a.h3=div(a.tt-a.mn,a.mx-a.mn);a.v=div(.1333,a.fps);a.bm+=(a.h1-a.h2)*a.v;a.mt+=(a.h2-a.h3)*a.v;a.bt+=(a.h1-a.h3)*a.v;a.w=2*a.bm;a.q3=\nMath.sin(a.w);a.q9=Math.cos(a.w);a.q17=a.bm;a.q18=a.mt;a.q19=a.bt;', + pixel_eqs_str: + 'a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;', + warp: 'float sustain;\nfloat xlat_mutabledist;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (1.0123 - q14);\n vec2 uv_3;\n vec3 ret_4;\n vec2 tmpvar_5;\n tmpvar_5 = (uv - 0.5);\n xlat_mutableuv1 = ((tmpvar_5 * aspect.xy) * q16);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pc_main, uv);\n uv_3 = ((tmpvar_5 * (1.0 - \n (q10 / (1.0 - ((tmpvar_6.z + \n (0.003921569 * tmpvar_6.y)\n ) + (q10 * 0.7))))\n )) + 0.5);\n vec4 tmpvar_7;\n tmpvar_7 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n xlat_mutabledist = tmpvar_7.x;\n if ((tmpvar_7.y > 0.2)) {\n vec3 tmpvar_8;\n tmpvar_8 = (tmpvar_7.xyz - vec3(0.4, 0.5, 0.5));\n vec2 uvi_9;\n uvi_9 = ((tmpvar_8.zy * 0.003) + uv_3);\n vec2 pix_10;\n vec4 nb2_11;\n vec4 nb_12;\n vec2 x_13;\n x_13 = (uvi_9 - 0.5);\n pix_10 = (texsize.zw * (1.0 + (\n sqrt(dot (x_13, x_13))\n * 8.0)));\n float tmpvar_14;\n tmpvar_14 = (q10 * 0.7);\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pc_main, (uvi_9 - pix_10));\n nb_12.x = (1.0 - ((tmpvar_15.z + \n (0.003921569 * tmpvar_15.y)\n ) + tmpvar_14));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, -1.0))));\n nb_12.y = (1.0 - ((tmpvar_16.z + \n (0.003921569 * tmpvar_16.y)\n ) + tmpvar_14));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pc_main, (uvi_9 + pix_10));\n nb_12.z = (1.0 - ((tmpvar_17.z + \n (0.003921569 * tmpvar_17.y)\n ) + tmpvar_14));\n vec4 tmpvar_18;\n tmpvar_18 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 1.0))));\n nb_12.w = (1.0 - ((tmpvar_18.z + \n (0.003921569 * tmpvar_18.y)\n ) + tmpvar_14));\n vec4 tmpvar_19;\n tmpvar_19 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, -1.0))));\n nb2_11.x = (1.0 - ((tmpvar_19.z + \n (0.003921569 * tmpvar_19.y)\n ) + tmpvar_14));\n vec4 tmpvar_20;\n tmpvar_20 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, 0.0))));\n nb2_11.y = (1.0 - ((tmpvar_20.z + \n (0.003921569 * tmpvar_20.y)\n ) + tmpvar_14));\n vec4 tmpvar_21;\n tmpvar_21 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, 1.0))));\n nb2_11.z = (1.0 - ((tmpvar_21.z + \n (0.003921569 * tmpvar_21.y)\n ) + tmpvar_14));\n vec4 tmpvar_22;\n tmpvar_22 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 0.0))));\n nb2_11.w = (1.0 - ((tmpvar_22.z + \n (0.003921569 * tmpvar_22.y)\n ) + tmpvar_14));\n vec4 tmpvar_23;\n tmpvar_23 = min (nb_12, nb2_11);\n nb_12.zw = tmpvar_23.zw;\n nb_12.xy = min (tmpvar_23.xy, tmpvar_23.zw);\n xlat_mutabledist = (min (nb_12.x, nb_12.y) + ((0.008 * tmpvar_8.x) * abs(tmpvar_8.y)));\n };\n vec4 tmpvar_24;\n tmpvar_24 = texture (sampler_pc_main, uv_3);\n float tmpvar_25;\n tmpvar_25 = min (xlat_mutabledist, (1.0 - (\n (tmpvar_24.z + (0.003921569 * tmpvar_24.y))\n + \n (q10 * 0.7)\n )));\n xlat_mutabledist = tmpvar_25;\n float tmpvar_26;\n tmpvar_26 = (tmpvar_25 + pow (tmpvar_25, 3.0));\n vec3 tmpvar_27;\n tmpvar_27.xy = (xlat_mutableuv1 * tmpvar_26);\n tmpvar_27.z = tmpvar_26;\n xlat_mutableuv2 = (((tmpvar_27 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n float li_28;\n vec3 zz0_29;\n vec3 zz_30;\n zz0_29 = (xlat_mutableuv2 + q8);\n li_28 = 0.0;\n zz_30 = ((2.0 * clamp (xlat_mutableuv2, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - xlat_mutableuv2);\n float tmpvar_31;\n tmpvar_31 = dot (zz_30, zz_30);\n if ((tmpvar_31 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_31 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_31);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_32;\n tmpvar_32 = dot (zz_30, zz_30);\n if ((tmpvar_32 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_32 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_32);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_33;\n tmpvar_33 = dot (zz_30, zz_30);\n if ((tmpvar_33 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_33 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_33);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_34;\n tmpvar_34 = dot (zz_30, zz_30);\n if ((tmpvar_34 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_34 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_34);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_35;\n tmpvar_35 = dot (zz_30, zz_30);\n if ((tmpvar_35 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_35 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_35);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_36;\n tmpvar_36 = dot (zz_30, zz_30);\n if ((tmpvar_36 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_36 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_36);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_37;\n tmpvar_37 = dot (zz_30, zz_30);\n if ((tmpvar_37 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_37 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_37);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_38;\n tmpvar_38 = dot (zz_30, zz_30);\n if ((tmpvar_38 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_38 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_38);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n vec4 tmpvar_39;\n tmpvar_39.xyz = zz_30;\n tmpvar_39.w = li_28;\n float tmpvar_40;\n tmpvar_40 = sqrt(dot (zz_30, zz_30));\n xlat_mutablestruc = (sqrt(dot (tmpvar_39.xyw, tmpvar_39.xyw)) / 24.0);\n vec4 tmpvar_41;\n tmpvar_41 = texture (sampler_pc_main, uv_3);\n float tmpvar_42;\n float tmpvar_43;\n tmpvar_43 = (q10 * 0.7);\n tmpvar_42 = ((log(\n (1.0 + (tmpvar_40 / 24.0))\n ) * 0.02) * (1.0 - (1.0 - \n ((tmpvar_41.z + (0.003921569 * tmpvar_41.y)) + tmpvar_43)\n )));\n float tmpvar_44;\n vec4 tmpvar_45;\n tmpvar_45 = texture (sampler_pc_main, uv_3);\n tmpvar_44 = (1.0 - ((tmpvar_45.z + \n (0.003921569 * tmpvar_45.y)\n ) + tmpvar_43));\n if ((((tmpvar_25 <= tmpvar_44) && (tmpvar_40 < 24.0)) && (tmpvar_25 > 0.005))) {\n ret_4.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(\n (q14 * 4.0)\n )).x));\n float x_46;\n x_46 = ((1.0 - tmpvar_25) * 255.0);\n float ip_47;\n ip_47 = float(int(x_46));\n vec2 tmpvar_48;\n tmpvar_48.x = (x_46 - ip_47);\n tmpvar_48.y = (ip_47 / 255.0);\n ret_4.yz = tmpvar_48;\n } else {\n vec3 tmpvar_49;\n tmpvar_49.y = 0.0;\n tmpvar_49.x = sustain;\n tmpvar_49.z = (1.0 - tmpvar_42);\n vec3 tmpvar_50;\n tmpvar_50.xy = vec2(0.003921569, 0.0);\n tmpvar_50.z = (q14 / 6.0);\n ret_4 = ((texture (sampler_fc_main, uv_3).xyz * tmpvar_49) - tmpvar_50);\n };\n vec4 tmpvar_51;\n tmpvar_51.w = 1.0;\n tmpvar_51.xyz = ret_4;\n ret = tmpvar_51.xyz;\n }', + comp: 'vec2 xlat_mutabled;\nvec3 xlat_mutabledx;\nvec3 xlat_mutabledy;\n shader_body { \n vec3 ret_1;\n xlat_mutabled = (texsize.zw * 1.5);\n xlat_mutabledx = (texture (sampler_main, (uv_orig + (vec2(1.0, 0.0) * xlat_mutabled))).xyz - texture (sampler_main, (uv_orig - (vec2(1.0, 0.0) * xlat_mutabled))).xyz);\n xlat_mutabledy = (texture (sampler_main, (uv_orig + (vec2(0.0, 1.0) * xlat_mutabled))).xyz - texture (sampler_main, (uv_orig - (vec2(0.0, 1.0) * xlat_mutabled))).xyz);\n vec2 tmpvar_2;\n tmpvar_2.x = xlat_mutabledx.y;\n tmpvar_2.y = xlat_mutabledy.y;\n vec2 x_3;\n x_3 = (tmpvar_2 * 8.0);\n ret_1 = (((texture (sampler_main, uv).x * \n (1.0 - sqrt(dot (x_3, x_3)))\n ) * pow (hue_shader, vec3(6.0, 6.0, 6.0))) * 1.4);\n vec2 tmpvar_4;\n tmpvar_4.x = xlat_mutabledx.z;\n tmpvar_4.y = xlat_mutabledy.z;\n vec2 x_5;\n x_5 = (tmpvar_4 * 4.0);\n vec3 tmpvar_6;\n tmpvar_6 = mix (ret_1, vec3(1.0, 1.0, 1.0), vec3(sqrt(dot (x_5, x_5))));\n ret_1 = tmpvar_6;\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = tmpvar_6;\n ret = tmpvar_7.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.9, + echo_zoom: 1.169, + echo_orient: 1, + wave_mode: 5, + additivewave: 1, + wave_a: 0, + wave_scale: 0.9, + wave_smoothing: 0.63, + wave_mystery: 1, + modwavealphastart: 2, + modwavealphaend: 2, + warpscale: 2.853, + rot: 0.006, + warp: 0, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0.005, + mv_x: 0, + mv_y: 48, + mv_dx: -0.941, + mv_dy: 0.426, + mv_l: 5, + mv_r: 0.316, + mv_g: 0.078, + mv_b: 0.942, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + textured: 1, + rad: 0.78903, + ang: 0.62832, + tex_zoom: 1.02009, + r: 0, + g: 1, + b: 1, + r2: 0.7, + b2: 1, + border_a: 0, + }, + init_eqs_str: 'a.vx=0;a.vy=0;', + frame_eqs_str: '', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.d=0;a.y3=0;a.y1=0;a.xx=0;a.res=0;a.q12=0;a.x1=0;a.vx3=0;a.q13=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.c_x=0;a.c_y=0;a.q9=0;a.d1=0;a.v=0;a.si1=0;a.vx4=0;a.diff=0;a.x3=0;a.q23=0;a.q24=0;a.d2=0;a.q11=0;a.q10=0;a.xx2=0;a.q4=0;a.yy1=0;a.vy4=0;a.dir=0;a.x4=0;a.r=0;a.x2=0;a.beat=0;a.vol=0;a.vy2=0;a.y2=0;a.size=0;a.q2=0;a.q14=0;a.si2=0;a.vx2=0;a.q3=0;a.yy=0;a.y4=0;a.q7=0;a.vy3=0;a.strength=0;a.xx1=0;a.velocity=0;a.q8=0;a.c_x=.5;a.c_y=.5;', + frame_eqs_str: + 'a.sx=1+.01*mod(8*a.bass,8)*equal(mod(a.time,Math.floor(24-2*a.bass)),0);a.sy=1+.01*mod(8*a.mid,8)*equal(mod(a.time,12+Math.floor(24-2*a.bass)),0);a.q1=a.aspectx;a.q2=a.aspecty;a.rot=0;a.zoom=1;a.warp=0;a.vol=8*a.bass+4*a.mid+2*a.treb;a.vol*=above(a.vol,17);a.monitor=a.vol;a.beat=above(a.vol,a.res);a.diff=(1-a.beat)*a.diff+a.beat*(a.vol-a.res);a.res=a.beat*(a.vol+2*a.diff)+(1-a.beat)*(a.res-div(60*(.04*a.diff+.12),a.fps));a.res=Math.max(0,a.res);a.monitor=a.res;a.r=.00001 3.1)) {\n ret_2 = (ret_2 - 0.4);\n };\n bool tmpvar_4;\n if ((ret_2.x < 0.1)) {\n tmpvar_4 = (abs((n_1 - 3.0)) < 0.5);\n } else {\n tmpvar_4 = bool(0);\n };\n if (tmpvar_4) {\n ret_2 = (ret_2 + 0.4);\n };\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }', + comp: ' shader_body { \n vec3 ret2_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3 = (texsize.zw * 8.0);\n vec2 tmpvar_4;\n tmpvar_4.x = (((texture (sampler_blur1, \n (uv + (vec2(1.0, 0.0) * tmpvar_3))\n ).xyz * scale1) + bias1) - ((texture (sampler_blur1, \n (uv - (vec2(1.0, 0.0) * tmpvar_3))\n ).xyz * scale1) + bias1)).y;\n tmpvar_4.y = (((texture (sampler_blur1, \n (uv + (vec2(0.0, 1.0) * tmpvar_3))\n ).xyz * scale1) + bias1) - ((texture (sampler_blur1, \n (uv - (vec2(0.0, 1.0) * tmpvar_3))\n ).xyz * scale1) + bias1)).y;\n vec2 tmpvar_5;\n tmpvar_5 = (uv + (tmpvar_4 * 0.55));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_blur3, uv);\n ret_2 = (vec3((0.25 * dot (\n clamp ((2.0 * ((tmpvar_6.xyz * scale3) + bias3)), 0.0, 1.0)\n , vec3(0.32, 0.49, 0.29)))) - (0.8 * dot (\n clamp (((20.0 * (\n (0.6 * ((texture (sampler_blur2, uv).xyz * scale2) + bias2))\n - 0.01)) - 2.0), 0.0, 1.0)\n , vec3(0.32, 0.49, 0.29))));\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_blur1, uv);\n ret_2 = (ret_2 + dot (clamp (\n ((30.0 * ((texture (sampler_main, uv).xyz + \n (((tmpvar_7.xyz * scale1) + bias1) * 0.15)\n ) - 0.01)) - 2.0)\n , 0.0, 1.0), vec3(0.32, 0.49, 0.29)));\n ret_2 = (ret_2 + 1.0);\n vec3 tmpvar_8;\n tmpvar_8 = mix (ret_2, (ret_2 * (\n ((texture (sampler_blur3, tmpvar_5).xyz * scale3) + bias3)\n - \n ((texture (sampler_blur1, tmpvar_5).xyz * scale1) + bias1)\n )), pow (hue_shader, ret_2));\n ret2_1 = (vec3((-0.5 * dot (\n ((texture (sampler_blur3, tmpvar_5).xyz * scale3) + bias3)\n , vec3(0.32, 0.49, 0.29)))) + (0.8 * (\n (texture (sampler_blur1, tmpvar_5).xyz * scale1)\n + bias1)));\n ret2_1 = (ret2_1 - (0.9 * texture (sampler_main, tmpvar_5).xyz));\n ret2_1 = (ret2_1 - 1.5);\n vec3 tmpvar_9;\n tmpvar_9 = mix (ret2_1, (ret2_1 * (\n ((tmpvar_6.xyz * scale3) + bias3)\n - \n ((tmpvar_7.xyz * scale1) + bias1)\n )), pow (hue_shader.zxy, tmpvar_8));\n ret2_1 = tmpvar_9;\n vec3 tmpvar_10;\n tmpvar_10 = abs((tmpvar_8 - tmpvar_9));\n ret_2 = (tmpvar_10 * tmpvar_10);\n ret_2 = (ret_2 * 1.15);\n vec4 tmpvar_11;\n tmpvar_11.w = 1.0;\n tmpvar_11.xyz = ret_2;\n ret = tmpvar_11.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1, + decay: 0.9, + echo_zoom: 1, + wave_brighten: 0, + wrap: 0, + wave_a: 0.001, + wave_scale: 5.715, + wave_smoothing: 0.9, + modwavealphastart: 1, + modwavealphaend: 1, + warpanimspeed: 0.162, + warpscale: 5.582, + zoomexp: 0.32104, + zoom: 0.9901, + warp: 0.11563, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_b: 0, + mv_a: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + thickoutline: 1, + textured: 1, + rad: 0.05343, + tex_zoom: 12.77228, + g: 1, + b: 1, + a: 0, + r2: 1, + b2: 1, + a2: 1, + border_g: 0, + border_a: 0, + }, + init_eqs_str: 'a.vx=0;a.vy=0;', + frame_eqs_str: '', + }, + { + baseVals: { + enabled: 1, + sides: 100, + textured: 1, + y: 0.75, + rad: 0.46753, + g: 1, + b: 1, + r2: 1, + b2: 1, + border_a: 0, + }, + init_eqs_str: 'a.w=0;a.q1=0;', + frame_eqs_str: + 'a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);', + }, + { + baseVals: { + enabled: 1, + sides: 100, + textured: 1, + y: 0.75, + rad: 0.46753, + g: 1, + b: 1, + r2: 1, + b2: 1, + border_a: 0, + }, + init_eqs_str: 'a.w=0;a.q1=0;', + frame_eqs_str: + 'a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1)+div(2*Math.asin(1),3);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);', + }, + { + baseVals: { + enabled: 1, + sides: 100, + textured: 1, + y: 0.75, + rad: 0.46753, + g: 1, + b: 1, + r2: 1, + b2: 1, + border_a: 0, + }, + init_eqs_str: 'a.w=0;a.q1=0;', + frame_eqs_str: + 'a.w=4*-Math.atan2(.5,a.q1)+4*Math.asin(1)-div(2*Math.asin(1),3);a.ang=a.w;a.x=.5+.19*Math.sin(a.w);a.y=.5+.26*Math.cos(a.w);', + }, + ], + waves: [ + { + baseVals: { enabled: 1, usedots: 1, thick: 1, additive: 1, scaling: 2.44415, smoothing: 0 }, + init_eqs_str: + 'a.d=0;a.n=0;a.y1=0;a.xx=0;a.z=0;a.w=0;a.t5=0;a.t1=0;a.x1=0;a.cl3=0;a.j3=0;a.cl2=0;a.zoom=0;a.j=0;a.cl1=0;a.t8=0;a.v=0;a.t3=0;a.t6=0;a.pi3=0;a.t7=0;a.c2=0;a.j2=0;a.s3=0;a.t=0;a.k=0;a.zz=0;a.c3=0;a.t2=0;a.bb=0;a.s1=0;a.s2=0;a.t4=0;a.yy=0;a.c=0;a.c1=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;', + frame_eqs_str: + 'a.t1=0;a.v=.01;a.j+=.01*a.bass;a.j2+=.01*a.mid_att;a.j3+=.01*a.treb_att;a.t2=a.j;a.t3=a.j2;a.t4=a.j3;a.k=.99*a.k+div(10*a.mid,a.fps);a.t5=-a.k;a.cl1=a.cl1-.0005-.003*a.bass;a.cl1=.00001 0.0))))\n .xy * 0.025))));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = (((tmpvar_5.xyz * tmpvar_5.xyz) * 1.4) - 0.04);\n ret = tmpvar_6.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.56, + decay: 1, + echo_zoom: 0.362, + echo_orient: 1, + wave_thick: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 1.599, + wave_smoothing: 0, + wave_mystery: -0.5, + modwavealphastart: 2, + modwavealphaend: 2, + warpscale: 0.107, + zoomexp: 0.1584, + fshader: 1, + warp: 0.01, + wave_r: 0.51, + wave_g: 0.5, + ob_size: 0, + ob_a: 1, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0.5, + mv_r: 0, + mv_g: 0, + mv_b: 0, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.d=0;a.y3=0;a.y1=0;a.xx=0;a.s=0;a.t1=0;a.x1=0;a.vx3=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.v=0;a.vx4=0;a.mm=0;a.tt=0;a.grav=0;a.x3=0;a.xx2=0;a.q4=0;a.a=0;a.yy1=0;a.vy4=0;a.dir=0;a.bounce=0;a.x4=0;a.r=0;a.x2=0;a.mx=0;a.mn=0;a.vy2=0;a.y2=0;a.bb=0;a.q2=0;a.m1=0;a.spring=0;a.vx2=0;a.q3=0;a.resist=0;a.yy=0;a.y4=0;a.vy3=0;a.xx1=0;a.b1=0;a.q8=0;', + frame_eqs_str: + 'a.ib_r=.3*Math.sin(5*a.time)+.7;a.ib_g=.3*Math.sin(4*a.time)+.3;a.ib_b=.5*Math.sin(4*div(a.time,3))+.5;a.xx1=.9*a.xx1+.01*a.bass;a.xx2=.9*a.xx2+.01*a.treb;a.yy1=.94*a.yy1+.0075*(a.treb+a.bass);a.x1=.5+2*(a.xx1-a.xx2);a.y1=.4+a.yy1;a.x1=Math.max(0,Math.min(1,a.x1));a.y1=Math.max(0,Math.min(1,a.y1));a.spring=10;a.grav=.5;a.resist=1;a.bounce=.75;a.dt=.0002*div(60,a.fps);a.vx2=a.vx2*(1-a.resist*a.dt)+a.dt*(a.x1+a.x3-2*a.x2)*a.spring;a.vy2=a.vy2*(1-a.resist*a.dt)+a.dt*((a.y1+a.y3-\n2*a.y2)*a.spring-a.grav);a.vx3=a.vx3*(1-a.resist*a.dt)+a.dt*(a.x2+a.x4-2*a.x3)*a.spring;a.vy3=a.vy3*(1-a.resist*a.dt)+a.dt*((a.y2+a.y4-2*a.y3)*a.spring-a.grav);a.vx4=a.vx4*(1-a.resist*a.dt)+a.dt*(a.x3-a.x4)*a.spring;a.vy4=a.vy4*(1-a.resist*a.dt)+a.dt*((a.y3-a.y4)*a.spring-a.grav);a.x2+=a.vx2;a.y2+=a.vy2;a.x3+=a.vx3;a.y3+=a.vy3;a.x4+=a.vx4;a.y4+=a.vy4;a.vx2=.00001b;b++)a.gmegabuf[Math.floor(a.i)]=0,a.i+=1;a.count=50;a.attributes=32;a.nliststart=24;a.minradius=.004;a.maxradius=.04;a.v=0;for(b=a.index=0;b 1.0)\n ) * (\n (tmpvar_15 * -2.0)\n + 1.570796)));\n tmpvar_13 = (tmpvar_15 * sign((tmpvar_11.x / tmpvar_11.y)));\n if ((abs(tmpvar_11.y) > (1e-08 * abs(tmpvar_11.x)))) {\n if ((tmpvar_11.y < 0.0)) {\n if ((tmpvar_11.x >= 0.0)) {\n tmpvar_13 += 3.141593;\n } else {\n tmpvar_13 = (tmpvar_13 - 3.141593);\n };\n };\n } else {\n tmpvar_13 = (sign(tmpvar_11.x) * 1.570796);\n };\n vec2 tmpvar_16;\n tmpvar_16.x = (tmpvar_13 * 0.1591549);\n tmpvar_16.y = tmpvar_12;\n vec2 tmpvar_17;\n tmpvar_17.x = ((tmpvar_16.x * 2.0) + q11);\n tmpvar_17.y = ((0.3 * log(tmpvar_12)) + q12);\n vec2 tmpvar_18;\n tmpvar_18 = (0.5 + (0.5 - abs(\n ((fract((tmpvar_17 * 0.5)) * 2.0) - 1.0)\n )));\n vec2 tmpvar_19;\n tmpvar_19 = (texsize.zw * 3.0);\n vec3 tmpvar_20;\n tmpvar_20 = ((2.0 * (\n (texture (sampler_blur1, (tmpvar_18 + (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (tmpvar_18 - (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec3 tmpvar_21;\n tmpvar_21 = ((2.0 * (\n (texture (sampler_blur1, (tmpvar_18 + (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (tmpvar_18 - (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec2 tmpvar_22;\n tmpvar_22.x = tmpvar_20.x;\n tmpvar_22.y = tmpvar_21.x;\n mirror_uv_3 = (tmpvar_18 + ((tmpvar_22 * texsize.zw) * 4.0));\n ret_4 = ((mix (ret_4, vec3(1.0, 1.0, 1.0), \n ((((texture (sampler_blur1, mirror_uv_3).xyz * scale1) + bias1).x * (1.0 - (\n (texture (sampler_blur2, mirror_uv_3).xyz * scale2)\n + bias2).x)) * (pow (hue_shader, vec3(4.0, 4.0, 4.0)) * 1.4))\n ) * texture (sampler_main, mirror_uv_3).xxx) + ((\n (1.0 - texture (sampler_main, mirror_uv_3).x)\n * \n ((texture (sampler_blur1, mirror_uv_3).xyz * scale1) + bias1)\n .x) * vec3(3.0, 3.0, 3.0)));\n vec2 tmpvar_23;\n tmpvar_23.x = tmpvar_20.x;\n tmpvar_23.y = tmpvar_21.x;\n mirror_uv_3 = (mirror_uv_3 - ((tmpvar_23 * texsize.zw) * 24.0));\n dx_2 = ((2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 + (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 - (vec2(1.0, 0.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n dy_1 = ((2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 + (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)) - (2.0 * (\n (texture (sampler_blur1, (mirror_uv_3 - (vec2(0.0, 1.0) * tmpvar_19))).xyz * scale1)\n + bias1)));\n vec2 tmpvar_24;\n tmpvar_24.x = -(dx_2.y);\n tmpvar_24.y = dy_1.y;\n vec2 tmpvar_25;\n tmpvar_25 = (tmpvar_24 * 0.25);\n vec3 tmpvar_26;\n tmpvar_26 = mix (ret_4, vec3(1.0, 1.0, 1.0), (mix (vec3(1.0, 0.7, 0.2), vec3(0.15, 0.0, 0.5), vec3(\n ((((\n ((mirror_uv_3.x * 0.8) - mirror_uv_3.y)\n + 0.75) + tmpvar_25.x) + tmpvar_25.y) - 0.1)\n )) * texture (sampler_main, mirror_uv_3).y));\n vec2 tmpvar_27;\n vec2 tmpvar_28;\n tmpvar_28 = ((0.5 + (\n (uv - 0.5)\n * aspect.wz)) - vec2(0.5, 0.5));\n vec2 tmpvar_29;\n tmpvar_29.x = ((q4 * tmpvar_28.x) - (q3 * tmpvar_28.y));\n tmpvar_29.y = ((q3 * tmpvar_28.x) + (q4 * tmpvar_28.y));\n tmpvar_27 = (vec2(0.5, 0.5) + tmpvar_29);\n mirror_uv_3 = tmpvar_27.yx;\n vec2 tmpvar_30;\n tmpvar_30 = (vec2(1.0, 0.0) * texsize.zw);\n dx_2 = ((2.0 * texture (sampler_main, (tmpvar_27.yx + tmpvar_30)).xyz) - (2.0 * texture (sampler_main, (tmpvar_27.yx - tmpvar_30)).xyz));\n vec2 tmpvar_31;\n tmpvar_31 = (vec2(0.0, 1.0) * texsize.zw);\n dy_1 = ((2.0 * texture (sampler_main, (tmpvar_27.yx + tmpvar_31)).xyz) - (2.0 * texture (sampler_main, (tmpvar_27.yx - tmpvar_31)).xyz));\n vec2 tmpvar_32;\n tmpvar_32.x = dx_2.z;\n tmpvar_32.y = dy_1.z;\n vec3 tmpvar_33;\n tmpvar_33 = mix (tmpvar_26, vec3(0.9, 0.9, 1.0), vec3((1.0 - texture (sampler_main, (tmpvar_27.yx - tmpvar_32)).z)));\n ret_4 = tmpvar_33;\n vec4 tmpvar_34;\n tmpvar_34.w = 1.0;\n tmpvar_34.xyz = tmpvar_33;\n ret = tmpvar_34.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 0.995, + echo_zoom: 1.007, + echo_orient: 3, + additivewave: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + wave_a: 1.413, + wave_scale: 0.418, + wave_smoothing: 0, + wave_mystery: -0.66, + modwavealphastart: 2, + modwavealphaend: 2, + warpanimspeed: 0.626, + warpscale: 8.642, + zoomexp: 7.10084, + zoom: 0.99951, + warp: 0.09014, + wave_r: 0, + wave_g: 0, + wave_x: 0.24, + wave_y: 0.44, + ob_size: 0, + ob_a: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_a: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 48, + additive: 1, + rad: 0.0277, + ang: 6.03186, + tex_ang: 6.03186, + tex_zoom: 0.6839, + r: 0, + g: 1, + a2: 1, + border_r: 0, + border_g: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.q3=0;a.q4=0;a.q5=0;a.q2=0;a.q1=0;', + frame_eqs_str: 'a.x=a.q3;a.y=a.q4;a.rad=a.q5;a.x=.5+div(a.x-.5,a.q2);a.y=.5+div(a.y-.5,a.q1);', + }, + { + baseVals: { + enabled: 1, + sides: 48, + additive: 1, + rad: 0.0277, + ang: 6.03186, + tex_ang: 6.03186, + tex_zoom: 0.6839, + r: 0, + b: 1, + g2: 0, + b2: 1, + a2: 1, + border_r: 0, + border_g: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.q6=0;a.q7=0;a.q8=0;a.q2=0;a.q1=0;', + frame_eqs_str: 'a.x=a.q6;a.y=a.q7;a.rad=a.q8;a.x=.5+div(a.x-.5,a.q2);a.y=.5+div(a.y-.5,a.q1);', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, thick: 1, additive: 1, scaling: 2.0231, smoothing: 0, g: 0, b: 0 }, + init_eqs_str: + 'a.d=0;a.tt2=0;a.res=0;a.tt1=0;a.diff=0;a.tt3=0;a.beat=0;a.vol=0;a.m=0;a.monitor=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;', + frame_eqs_str: + 'a.vol=8*a.bass+5*a.mid+3*a.treb;a.m=.97*a.m+.08*a.vol;a.monitor=a.vol;a.beat=above(a.vol,a.res)*above(a.vol,a.m)*above(a.vol,16);a.diff=(1-a.beat)*a.diff+a.beat*(a.vol-a.res);a.res=a.beat*(a.vol+.04*a.m)+(1-a.beat)*(a.res-div(60*(.1+.02*a.diff),a.fps));a.res=Math.max(0,a.res);a.a=a.beat;', + point_eqs_str: + 'a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.5+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.y3=0;a.y1=0;a.xx=0;a.q12=0;a.w2=0;a.ref_ang=0;a.q18=0;a.x1=0;a.vx3=0;a.q13=0;a.q15=0;a.q6=0;a.q1=0;a.q5=0;a.q9=0;a.d1=0;a.si1=0;a.vx1=0;a.vx4=0;a.x3=0;a.d2=0;a.q11=0;a.q10=0;a.q4=0;a.vy4=0;a.dir=0;a.bounce=0;a.q16=0;a.x4=0;a.w1=0;a.r=0;a.x2=0;a.q17=0;a.vy2=0;a.y2=0;a.vy1=0;a.q2=0;a.m1=0;a.q14=0;a.si2=0;a.v1=0;a.vx2=0;a.q3=0;a.yy=0;a.y4=0;a.q7=0;a.vy3=0;a.v2=0;a.b1=0;a.q8=0;a.x1=.5;a.x2=.51;a.y2=.9;a.y1=.7;a.x3=.8;a.y3=.5;a.x4=.2;a.y4=.5;a.ax1=0;a.ay1=0;a.ax2=0;a.ay2=0;a.ax3=\n0;a.ay3=0;a.vx1=0;a.vx2=0;', + frame_eqs_str: + 'a.zoom=1.002;a.warp=.2;a.wave_a=0;a.r=.04+.008*Math.max(a.bass_att,a.treb_att);a.bounce=below(a.y1,a.r);a.y1+=a.vy1;a.vy1=.00001 1.0)\n ) * (\n (tmpvar_7 * -2.0)\n + 1.570796)));\n tmpvar_5 = (tmpvar_7 * sign((tmpvar_4.x / tmpvar_4.y)));\n if ((abs(tmpvar_4.y) > (1e-08 * abs(tmpvar_4.x)))) {\n if ((tmpvar_4.y < 0.0)) {\n if ((tmpvar_4.x >= 0.0)) {\n tmpvar_5 += 3.141593;\n } else {\n tmpvar_5 = (tmpvar_5 - 3.141593);\n };\n };\n } else {\n tmpvar_5 = (sign(tmpvar_4.x) * 1.570796);\n };\n vec2 tmpvar_8;\n tmpvar_8.x = ((tmpvar_5 * q11) - tmpvar_3);\n tmpvar_8.y = (((q13 * \n log(sqrt(dot (tmpvar_4, tmpvar_4)))\n ) + (tmpvar_5 * q11)) + tmpvar_3);\n uv_1 = (0.5 + (0.5 - abs(\n ((fract((tmpvar_8 * 0.5)) * 2.0) - 1.0)\n )));\n vec4 tmpvar_9;\n tmpvar_9 = texture (sampler_main, uv_1);\n ret_2 = (vec3(dot (tmpvar_9.xyz, vec3(0.32, 0.49, 0.29))) * mix (vec3(1.0, 1.0, 1.0), vec3(0.2, 0.5, 1.0), tmpvar_9.xxx));\n ret_2 = (ret_2 * 2.0);\n vec4 tmpvar_10;\n tmpvar_10.w = 1.0;\n tmpvar_10.xyz = ret_2;\n ret = tmpvar_10.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 1, + echo_zoom: 1, + echo_alpha: 0.5, + wave_thick: 1, + wave_brighten: 0, + wrap: 0, + wave_a: 0.004, + wave_scale: 0.242, + wave_smoothing: 0, + wave_mystery: -0.44, + modwavealphastart: 1, + modwavealphaend: 1, + warpanimspeed: 0.88, + warpscale: 9.181, + zoomexp: 0.65309, + zoom: 0.87866, + warp: 0.04914, + wave_y: 0.04, + ob_size: 0.05, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_b: 0, + mv_a: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + thickoutline: 1, + y: 0.04, + rad: 0.01, + tex_ang: 0.12566, + tex_zoom: 1.51878, + r: 0, + a: 0, + g2: 0, + b2: 0.01, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: '', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, thick: 1, additive: 1, scaling: 2.0231, smoothing: 0, r: 0, b: 0 }, + init_eqs_str: 'a.tt3=0;a.tt2=0;a.tt1=0;a.d=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;', + frame_eqs_str: 'a.r=1;a.g=0;a.b=1;', + point_eqs_str: + 'a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.6+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.c_inv_i=0;a.translation_x=0;a.q12=0;a.a_i=0;a.a_r=0;a.q18=0;a.q13=0;a.scale=0;a.q15=0;a.c_inv_r=0;a.angle=0;a.q11=0;a.bcad_r=0;a.b_r=0;a.q16=0;a.bcad_i=0;a.q17=0;a.q14=0;a.translation_y=0;a.translation_v=0;a.b_i=0;a.translation_u=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;', + frame_eqs_str: + 'a.zoom=1;a.scale=1;a.angle=.1*a.time;a.translation_x=0;a.translation_y=.12;a.a_r=Math.cos(a.angle)*a.scale;a.a_i=Math.sin(a.angle)*a.scale;a.b_r=a.translation_x;a.b_i=a.translation_y;a.scale=1.6;a.angle=0;a.translation_u=0;a.translation_v=0;a.q15=Math.cos(a.angle)*a.scale;a.q16=Math.sin(a.angle)*a.scale;a.q17=a.translation_u;a.q18=a.translation_v;a.c_inv_r=div(a.q15,a.q15*a.q15+a.q16*a.q16);a.c_inv_i=div(a.q16,a.q15*a.q15+a.q16*a.q16);a.q11=a.a_r*a.c_inv_r-a.a_i*a.c_inv_i;a.q12=\na.a_r*a.c_inv_i-a.a_i*a.c_inv_r;a.bcad_r=a.b_r*a.q15-a.b_i*a.q16-(a.a_r*a.q17-a.a_i*a.q18);a.bcad_i=a.b_r*a.q16-a.b_i*a.q15-(a.a_r*a.q18-a.a_i*a.q17);a.q13=a.bcad_r*a.c_inv_r-a.bcad_i*a.c_inv_i;a.q14=a.bcad_r*a.c_inv_i-a.bcad_i*a.c_inv_r;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n float conway_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = (((\n ((texture (sampler_blur2, (uv + vec2(0.02, 0.0))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.02, 0.0))).xyz * scale2) + bias2)\n ).y * 1280.0) * texsize.z);\n tmpvar_3.y = (((\n ((texture (sampler_blur2, (uv + vec2(0.0, 0.02))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.0, 0.02))).xyz * scale2) + bias2)\n ).y * 1024.0) * texsize.w);\n ret_2.y = texture (sampler_pc_main, (uv - (tmpvar_3 * 0.004))).y;\n ret_2.y = (ret_2.y + ((\n ((ret_2.y - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).y) - 0.1)\n * 0.1) + 0.02));\n vec2 tmpvar_4;\n tmpvar_4 = (vec2(0.0, 1.0) * texsize.zw);\n ret_2.z = (texture (sampler_fc_main, (uv - tmpvar_4)).z - 0.004);\n conway_1 = (texture (sampler_pw_main, (uv_orig - texsize.zw)).x + texture (sampler_pw_main, (uv_orig + (vec2(0.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + tmpvar_4)).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + texsize.zw)).x);\n conway_1 = (conway_1 - fract(conway_1));\n float tmpvar_5;\n tmpvar_5 = clamp (texture (sampler_pc_main, uv_orig).x, 0.0, 1.0);\n ret_2.x = (clamp ((1.0 - \n abs((conway_1 - 3.0))\n ), 0.0, 1.0) * (1.0 - tmpvar_5));\n ret_2.x = (ret_2.x + (clamp (\n max ((1.0 - abs((conway_1 - 2.0))), (1.0 - abs((conway_1 - 3.0))))\n , 0.0, 1.0) * tmpvar_5));\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = ret_2;\n ret = tmpvar_6.xyz;\n }', + comp: ' shader_body { \n vec2 moebius_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = q11;\n tmpvar_3.y = q12;\n vec2 tmpvar_4;\n tmpvar_4.x = q17;\n tmpvar_4.y = q18;\n vec2 tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (uv - 0.5);\n tmpvar_5 = (tmpvar_6 * aspect.xy);\n vec2 tmpvar_7;\n tmpvar_7.x = ((tmpvar_5.x * q15) - (tmpvar_5.y * q16));\n tmpvar_7.y = ((tmpvar_5.x * q16) - (tmpvar_5.y * q15));\n vec2 tmpvar_8;\n tmpvar_8 = (tmpvar_7 + tmpvar_4);\n vec2 tmpvar_9;\n tmpvar_9.x = ((q13 * tmpvar_8.x) + (q14 * tmpvar_8.y));\n tmpvar_9.y = ((q14 * tmpvar_8.x) - (q13 * tmpvar_8.y));\n moebius_1 = (((tmpvar_9 / \n ((tmpvar_8.x * tmpvar_8.x) + (tmpvar_8.y * tmpvar_8.y))\n ) + tmpvar_3) * 0.5);\n float tmpvar_10;\n tmpvar_10 = sqrt(dot (moebius_1, moebius_1));\n moebius_1 = (0.5 + ((\n (1.0 - abs(((\n fract((moebius_1 * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.95));\n vec2 tmpvar_11;\n tmpvar_11 = (0.5 + (tmpvar_6 * 0.2));\n ret_2 = (texture (sampler_main, tmpvar_11).z * vec3(0.4, 0.0, 0.7));\n ret_2 = (mix (ret_2, vec3(0.0, 1.0, 1.0), vec3(clamp (texture (sampler_fc_main, moebius_1).y, 0.0, 1.0))) * (1.4 - pow (\n (tmpvar_10 * 0.8)\n , 0.3)));\n vec3 tmpvar_12;\n tmpvar_12 = mix (mix (mix (ret_2, vec3(4.0, 1.0, 0.0), vec3(\n ((clamp ((texture (sampler_fc_main, tmpvar_11).y - texture (sampler_pc_main, tmpvar_11).y), 0.0, 1.0) * 4.0) * (tmpvar_10 * tmpvar_10))\n )), vec3(-4.0, -4.0, -4.0), texture (sampler_main, tmpvar_11).xxx), vec3(2.0, 2.0, 2.0), vec3((texture (sampler_pc_main, tmpvar_11).x * 0.75)));\n ret_2 = tmpvar_12;\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = tmpvar_12;\n ret = tmpvar_13.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 1, + gammaadj: 1.28, + decay: 0.8, + echo_zoom: 1, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + brighten: 1, + wave_a: 0.001, + wave_scale: 1.286, + wave_smoothing: 0.63, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpanimspeed: 0.01, + warpscale: 100, + zoomexp: 0.92178, + zoom: 0.9901, + warp: 0.01, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0.005, + ob_g: 1, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.d=0;a.y3=0;a.y1=0;a.xx=0;a.s=0;a.x1=0;a.vx3=0;a.q6=0;a.dt=0;a.q1=0;a.q5=0;a.v=0;a.vx4=0;a.grav=0;a.x3=0;a.q11=0;a.q10=0;a.xx2=0;a.q4=0;a.a=0;a.yy1=0;a.vy4=0;a.dir=0;a.bounce=0;a.x4=0;a.r=0;a.x2=0;a.vy2=0;a.y2=0;a.q2=0;a.spring=0;a.vx2=0;a.q3=0;a.resist=0;a.yy=0;a.y4=0;a.vy3=0;a.xx1=0;a.v2=0;a.q8=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;', + frame_eqs_str: + 'a.xx1=.9*a.xx1+.01*a.bass;a.xx2=.9*a.xx2+.01*a.treb;a.yy1=.94*a.yy1+.0075*(a.treb+a.bass);a.x1=.5+2*(a.xx1-a.xx2);a.y1=.4+a.yy1;a.x1=Math.max(0,Math.min(1,a.x1));a.y1=Math.max(0,Math.min(1,a.y1));a.spring=10;a.grav=.5;a.resist=1;a.bounce=.75;a.dt=.0001*div(60,a.fps);a.vx2=a.vx2*(1-a.resist*a.dt)+a.dt*(a.x1+a.x3-2*a.x2)*a.spring;a.vy2=a.vy2*(1-a.resist*a.dt)+a.dt*((a.y1+a.y3-2*a.y2)*a.spring-a.grav);a.vx3=a.vx3*(1-a.resist*a.dt)+a.dt*(a.x2+a.x4-2*a.x3)*a.spring;a.vy3=a.vy3*(1-\na.resist*a.dt)+a.dt*((a.y2+a.y4-2*a.y3)*a.spring-a.grav);a.vx4=a.vx4*(1-a.resist*a.dt)+a.dt*(a.x3-a.x4)*a.spring;a.vy4=a.vy4*(1-a.resist*a.dt)+a.dt*((a.y3-a.y4)*a.spring-a.grav);a.x2+=a.vx2;a.y2+=a.vy2;a.x3+=a.vx3;a.y3+=a.vy3;a.x4+=a.vx4;a.y4+=a.vy4;a.vx2=.00001 1.0)\n ) * (\n (tmpvar_4 * -2.0)\n + 1.570796)));\n tmpvar_2 = (tmpvar_4 * sign((tmpvar_1.x / tmpvar_1.y)));\n if ((abs(tmpvar_1.y) > (1e-08 * abs(tmpvar_1.x)))) {\n if ((tmpvar_1.y < 0.0)) {\n if ((tmpvar_1.x >= 0.0)) {\n tmpvar_2 += 3.141593;\n } else {\n tmpvar_2 = (tmpvar_2 - 3.141593);\n };\n };\n } else {\n tmpvar_2 = (sign(tmpvar_1.x) * 1.570796);\n };\n vec2 tmpvar_5;\n tmpvar_5.x = (tmpvar_2 * q11);\n tmpvar_5.y = (((0.5 * \n log(sqrt(dot (tmpvar_1, tmpvar_1)))\n ) - (tmpvar_2 * q11)) + q12);\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = pow (texture (sampler_main, (0.5 + (\n (0.5 - abs(((\n fract((tmpvar_5 * 0.5))\n * 2.0) - 1.0)))\n * vec2(0.96, 1.0)))).xyz, vec3(0.618034, 0.618034, 0.618034));\n ret = tmpvar_6.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1, + decay: 1, + echo_zoom: 1, + echo_alpha: 0.5, + wave_thick: 1, + wave_brighten: 0, + wave_a: 0.004, + wave_scale: 0.01, + wave_smoothing: 0, + wave_mystery: -0.44, + modwavealphastart: 1, + modwavealphaend: 1, + warpanimspeed: 0.01, + warpscale: 100, + zoomexp: 0.24298, + zoom: 0.9901, + warp: 0.01, + wave_y: 0.04, + ob_size: 0, + ob_g: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_b: 0, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + thickoutline: 1, + rad: 0.01, + tex_ang: 0.12566, + tex_zoom: 1.51878, + r: 0.05, + a: 0.1, + g2: 0, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: '', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: 'a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;', + frame_eqs_str: 'a.zoom=1;a.warp=0;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec2 my_uv_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3 = (0.02 * aspect.zw);\n vec3 tmpvar_4;\n tmpvar_4 = (((texture (sampler_blur2, \n ((uv + (vec2(1.0, 0.0) * tmpvar_3)) - floor((uv + (vec2(1.0, 0.0) * tmpvar_3))))\n ).xyz * scale2) + bias2) - ((texture (sampler_blur2, \n ((uv - (vec2(1.0, 0.0) * tmpvar_3)) - floor((uv - (vec2(1.0, 0.0) * tmpvar_3))))\n ).xyz * scale2) + bias2));\n vec3 tmpvar_5;\n tmpvar_5 = (((texture (sampler_blur2, \n ((uv + (vec2(0.0, 1.0) * tmpvar_3)) - floor((uv + (vec2(0.0, 1.0) * tmpvar_3))))\n ).xyz * scale2) + bias2) - ((texture (sampler_blur2, \n ((uv - (vec2(0.0, 1.0) * tmpvar_3)) - floor((uv - (vec2(0.0, 1.0) * tmpvar_3))))\n ).xyz * scale2) + bias2));\n vec3 tmpvar_6;\n tmpvar_6 = ((texture (sampler_blur1, uv).xyz * scale1) + bias1);\n vec2 tmpvar_7;\n tmpvar_7.x = tmpvar_4.y;\n tmpvar_7.y = tmpvar_5.y;\n vec2 tmpvar_8;\n tmpvar_8.x = tmpvar_5.x;\n tmpvar_8.y = -(tmpvar_4.x);\n vec2 tmpvar_9;\n tmpvar_9 = ((uv - (tmpvar_7 * vec2(0.01, 0.01))) - (tmpvar_8 * -0.02));\n ret_2.y = texture (sampler_fc_main, (tmpvar_9 - floor(tmpvar_9))).y;\n ret_2.y = (ret_2.y + ((\n (ret_2.y - tmpvar_6.y)\n * 0.02) + 0.005));\n vec2 tmpvar_10;\n tmpvar_10.x = tmpvar_4.x;\n tmpvar_10.y = tmpvar_5.x;\n vec2 tmpvar_11;\n tmpvar_11.x = tmpvar_5.z;\n tmpvar_11.y = -(tmpvar_4.z);\n my_uv_1 = ((uv - (tmpvar_10 * vec2(0.01, 0.01))) - (tmpvar_11 * -0.02));\n ret_2.x = texture (sampler_fc_main, (my_uv_1 - floor(my_uv_1))).x;\n ret_2.x = (ret_2.x + ((\n (ret_2.x - tmpvar_6.x)\n * 0.02) + 0.005));\n vec2 tmpvar_12;\n tmpvar_12.x = tmpvar_4.z;\n tmpvar_12.y = tmpvar_5.z;\n vec2 tmpvar_13;\n tmpvar_13.x = tmpvar_5.y;\n tmpvar_13.y = -(tmpvar_4.y);\n my_uv_1 = ((uv - (tmpvar_12 * vec2(0.01, 0.01))) - (tmpvar_13 * -0.02));\n ret_2.z = texture (sampler_fc_main, (my_uv_1 - floor(my_uv_1))).z;\n ret_2.z = (ret_2.z + ((\n (ret_2.z - tmpvar_6.z)\n * 0.02) + 0.005));\n vec4 tmpvar_14;\n tmpvar_14.w = 1.0;\n tmpvar_14.xyz = ret_2;\n ret = tmpvar_14.xyz;\n }', + comp: ' shader_body { \n vec2 uv2_1;\n vec3 ret_2;\n uv2_1 = (uv + (vec2(1.0, 0.0) * texsize.zw));\n float tmpvar_3;\n tmpvar_3 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(-1.0, 0.0) * texsize.zw));\n float tmpvar_4;\n tmpvar_4 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, 1.0) * texsize.zw));\n float tmpvar_5;\n tmpvar_5 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, -1.0) * texsize.zw));\n vec3 tmpvar_6;\n tmpvar_6.z = 0.14;\n tmpvar_6.x = (tmpvar_3 - tmpvar_4);\n tmpvar_6.y = (tmpvar_5 - ((\n (texture (sampler_main, uv2_1).xyz + (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4))\n + \n (((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2) * 0.15)\n ) + (\n ((texture (sampler_blur3, uv2_1).xyz * scale3) + bias3)\n * 0.1)).x);\n ret_2 = (0.5 + (0.5 * normalize(tmpvar_6)));\n vec2 x_7;\n x_7 = (ret_2.xy - 0.5);\n ret_2 = (ret_2 * clamp ((\n sqrt(dot (x_7, x_7))\n * 5.0), 0.0, 1.0));\n ret_2 = ret_2.xxy;\n ret_2 = (ret_2 + 1.15);\n ret_2 = (ret_2 * mix (ret_2, (ret_2 * \n (((texture (sampler_blur3, uv).xyz * scale3) + bias3) - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n ), pow (hue_shader.zxy, ret_2)));\n ret_2 = (ret_2 * ret_2);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = ret_2;\n ret = tmpvar_8.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 1, + echo_zoom: 1, + echo_alpha: 0.5, + wave_thick: 1, + wave_brighten: 0, + wrap: 0, + wave_a: 0.004, + wave_scale: 0.242, + wave_smoothing: 0, + wave_mystery: -0.44, + modwavealphastart: 1, + modwavealphaend: 1, + warpanimspeed: 0.397, + warpscale: 15.099, + zoomexp: 0.65309, + zoom: 0.87866, + warp: 0.04027, + wave_y: 0.04, + ob_size: 0, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_b: 0, + mv_a: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + thickoutline: 1, + y: 0.04, + rad: 0.01, + tex_ang: 0.12566, + tex_zoom: 1.51878, + r: 0, + a: 0, + g2: 0, + b2: 0.01, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: '', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, thick: 1, additive: 1, scaling: 2.0231, smoothing: 0, r: 0, b: 0 }, + init_eqs_str: 'a.tt3=0;a.tt2=0;a.tt1=0;a.d=0;a.t2=0;a.t3=0;a.t4=0;a.cl=0;', + frame_eqs_str: 'a.r=1;a.g=0;a.b=1;', + point_eqs_str: + 'a.tt3=.6*a.tt3+1*a.value1;a.tt2=.7*a.tt2+.2*a.tt3;a.tt1=.8*a.tt1+.1*a.tt2;a.d=.9*a.d+.2*a.tt1;a.y=.6+a.d*a.sample*(1-a.sample)*2;a.x=-.05+1.1*a.sample;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.c_inv_i=0;a.translation_x=0;a.q12=0;a.a_i=0;a.a_r=0;a.q18=0;a.q13=0;a.scale=0;a.q15=0;a.c_inv_r=0;a.angle=0;a.q11=0;a.bcad_r=0;a.b_r=0;a.q16=0;a.bcad_i=0;a.q17=0;a.q14=0;a.translation_y=0;a.translation_v=0;a.b_i=0;a.translation_u=0;a.x1=.9;a.y1=.5;a.x2=.5;a.y2=.5;a.x3=.5;a.y3=.5;a.x4=.5;a.y4=.5;', + frame_eqs_str: + 'a.zoom=.998;a.scale=1;a.angle=.02*a.time;a.translation_x=0;a.translation_y=.12;a.a_r=Math.cos(a.angle)*a.scale;a.a_i=Math.sin(a.angle)*a.scale;a.b_r=a.translation_x;a.b_i=a.translation_y;a.scale=1;a.angle=0*Math.sin(.1337*a.time);a.translation_u=0;a.translation_v=-.2;a.q15=Math.cos(a.angle)*a.scale;a.q16=Math.sin(a.angle)*a.scale;a.q17=a.translation_u;a.q18=a.translation_v;a.c_inv_r=div(a.q15,a.q15*a.q15+a.q16*a.q16);a.c_inv_i=div(a.q16,a.q15*a.q15+a.q16*a.q16);a.q11=a.a_r*\na.c_inv_r-a.a_i*a.c_inv_i;a.q12=a.a_r*a.c_inv_i-a.a_i*a.c_inv_r;a.bcad_r=a.b_r*a.q15-a.b_i*a.q16-(a.a_r*a.q17-a.a_i*a.q18);a.bcad_i=a.b_r*a.q16-a.b_i*a.q15-(a.a_r*a.q18-a.a_i*a.q17);a.q13=a.bcad_r*a.c_inv_r-a.bcad_i*a.c_inv_i;a.q14=a.bcad_r*a.c_inv_i-a.bcad_i*a.c_inv_r;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n float conway_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = (((\n ((texture (sampler_blur2, (uv + vec2(0.02, 0.0))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.02, 0.0))).xyz * scale2) + bias2)\n ).y * 1280.0) * texsize.z);\n tmpvar_3.y = (((\n ((texture (sampler_blur2, (uv + vec2(0.0, 0.02))).xyz * scale2) + bias2)\n - \n ((texture (sampler_blur2, (uv - vec2(0.0, 0.02))).xyz * scale2) + bias2)\n ).y * 1024.0) * texsize.w);\n ret_2.y = texture (sampler_pc_main, (uv - (tmpvar_3 * 0.004))).y;\n ret_2.y = (ret_2.y + ((\n ((ret_2.y - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).y) - 0.1)\n * 0.1) + 0.02));\n ret_2.z = (texture (sampler_fc_main, (0.5 + (\n (uv - 0.5)\n * 0.992))).z - 0.004);\n conway_1 = (texture (sampler_pw_main, (uv_orig - texsize.zw)).x + texture (sampler_pw_main, (uv_orig + (vec2(0.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, -1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(1.0, 0.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(-1.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + (vec2(0.0, 1.0) * texsize.zw))).x);\n conway_1 = (conway_1 + texture (sampler_pw_main, (uv_orig + texsize.zw)).x);\n conway_1 = (conway_1 - fract(conway_1));\n float tmpvar_4;\n tmpvar_4 = clamp (texture (sampler_pc_main, uv_orig).x, 0.0, 1.0);\n ret_2.x = (clamp ((1.0 - \n abs((conway_1 - 3.0))\n ), 0.0, 1.0) * (1.0 - tmpvar_4));\n ret_2.x = (ret_2.x + (clamp (\n max ((1.0 - abs((conway_1 - 2.0))), (1.0 - abs((conway_1 - 3.0))))\n , 0.0, 1.0) * tmpvar_4));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }', + comp: ' shader_body { \n vec2 moebius_1;\n vec3 ret_2;\n vec2 tmpvar_3;\n tmpvar_3.x = q11;\n tmpvar_3.y = q12;\n vec2 tmpvar_4;\n tmpvar_4.x = q17;\n tmpvar_4.y = q18;\n vec2 tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (uv - 0.5);\n tmpvar_5 = (tmpvar_6 * aspect.xy);\n vec2 tmpvar_7;\n tmpvar_7.x = ((tmpvar_5.x * q15) - (tmpvar_5.y * q16));\n tmpvar_7.y = ((tmpvar_5.x * q16) - (tmpvar_5.y * q15));\n vec2 tmpvar_8;\n tmpvar_8 = (tmpvar_7 + tmpvar_4);\n vec2 tmpvar_9;\n tmpvar_9.x = ((q13 * tmpvar_8.x) + (q14 * tmpvar_8.y));\n tmpvar_9.y = ((q14 * tmpvar_8.x) - (q13 * tmpvar_8.y));\n moebius_1 = (((tmpvar_9 / \n ((tmpvar_8.x * tmpvar_8.x) + (tmpvar_8.y * tmpvar_8.y))\n ) + tmpvar_3) * 0.5);\n float tmpvar_10;\n tmpvar_10 = sqrt(dot (moebius_1, moebius_1));\n moebius_1 = (0.5 + ((\n (1.0 - abs(((\n fract((moebius_1 * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.99));\n vec3 tmpvar_11;\n tmpvar_11 = mix (mix (mix (\n mix (mix ((mix (ret_2, vec3(0.2, 0.6, 1.0), vec3(\n (texture (sampler_pc_main, moebius_1).y * 2.0)\n )) * (vec3(1.0, 1.0, 1.0) - vec3(\n ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.5))\n ).xyz * scale1) + bias1).y * 2.0) * tmpvar_10)\n ))), vec3(1.0, 1.0, 1.0), texture (sampler_pc_main, moebius_1).xxx), vec3(4.0, 1.0, 0.0), vec3(clamp (((texture (sampler_pc_main, \n (0.5 + (tmpvar_6 * 0.2))\n ).y * 2.0) * (\n (tmpvar_10 * tmpvar_10)\n * tmpvar_10)), 0.0, 1.0)))\n , vec3(0.1, 0.0, 0.0), vec3(\n clamp ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.2))\n ).xyz * scale1) + bias1).x * 12.0), 0.0, 1.0)\n )), (vec3(0.5, 0.8, 1.0) * texture (sampler_pc_main, uv).z), vec3((\n clamp ((((texture (sampler_blur1, \n (0.5 + (tmpvar_6 * 0.2))\n ).xyz * scale1) + bias1).x * 4.0), 0.0, 1.0)\n * 1.4))), vec3(1.0, 1.0, 1.0), texture (sampler_pc_main, (0.5 + (tmpvar_6 * 0.2))).xxx);\n ret_2 = tmpvar_11;\n vec4 tmpvar_12;\n tmpvar_12.w = 1.0;\n tmpvar_12.xyz = tmpvar_11;\n ret = tmpvar_12.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.56, + decay: 1, + echo_zoom: 0.362, + echo_orient: 1, + wave_mode: 7, + additivewave: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 1.286, + wave_smoothing: 0.63, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpscale: 1.331, + fshader: 1, + zoom: 1.004, + warp: 0.19788, + sx: 0.99967, + sy: 0.9999, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0, + ob_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, thick: 1, r: 0, g: 0.3, b: 0.75 }, + init_eqs_str: 'a.ma=0;a.mx=0;a.my=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.tstart=\na.time;a.bd_recsz=8;a.bd_oct=4;a.bd_spo=30;a.bd_finc=pow(2,div(1,a.bd_spo));a.bd_nres=a.bd_oct*a.bd_spo;a.bd_minbpm=20;a.bd_maxbpm=pow(2,a.bd_oct)*a.bd_minbpm;a.bd_dat0=1E5;a.bd_tab0=a.bd_dat0+a.bd_nres*a.bd_recsz*3;a.reg00=a.bd_minbpm;a.reg01=a.bd_maxbpm;a.reg02=a.bd_recsz;a.reg03=a.bd_nres;a.reg05=a.bd_finc;a.reg06=a.bd_dat0;a.reg07=a.bd_mp0;a.time_st=0;a.timediff=1;', + frame_eqs_str: + 'a.dt=Math.min(div(1,a.fps),.1);a.dec_m=1-4*a.dt;a.dec_s=1-a.dt;a.dec_xs=1-div(a.dt,6);a.t0=a.time-a.tstart;a.bd_b=a.bass;a.bd_bass_=a.bd_bass_*a.dec_m+(1-a.dec_m)*a.bd_b;a.bd_bass=a.bd_b-a.bd_bass_;a.bd_m=a.mid;a.bd_mid_=a.bd_mid_*a.dec_m+(1-a.dec_m)*a.bd_m;a.bd_mid=a.bd_m-a.bd_mid_;a.bd_t=a.treb;a.bd_treb_=a.bd_treb_*a.dec_m+(1-a.dec_m)*a.bd_t;a.bd_treb=a.bd_t-a.bd_treb_;a.n=0;a.bpm=a.bd_minbpm;for(var b=0;bb;b++){a.bd_exc=a.bd_bass*(.00001>Math.abs(a.bd_src-0)?1:0)+a.bd_mid*(.00001>Math.abs(a.bd_src-1)?1:0)+a.bd_treb*(.00001>Math.abs(a.bd_src-2)?1:0);for(var c=a.oct=0;ca.bd_pk?1:0)?a.bd_pk=a.bd_ampl:0;a.bd_slot+=1}a.bd_slot=0;a.bd_qual=pow(div(a.bd_pk,a.bd_mean)*a.bd_spo-1,1);a.gmegabuf[Math.floor(2*(a.bd_src*a.bd_oct+a.oct))]=a.bd_qual;for(d=0;da.bd_pk?1:0)?(a.bd_pk=a.gmegabuf[Math.floor(a.m)],a.maxind=a.bd_slot):0,a.bd_slot+=1;\na.quali=div(a.bd_pk,a.bd_mean)*a.bd_spo-1;for(b=a.n=0;150>b;b++)a.gmegabuf[Math.floor(50+a.n)]*=0,a.n+=1;a.bd_src=0;a.tsin=0;for(b=a.tcos=0;3>b;b++){for(c=a.oct=0;cb;b++){a.oct=1;for(c=0;ca.maxa?1:0)?(a.maxa=a.ampl,a.maxs=a.bd_src,a.maxo=a.oct):0,a.oct+=1;a.bd_src+=1}a.q28=pow(4*a.bd_qual,1.5);a.q31=a.q28;.00001Math.abs(a.prog-0)?1:0,2>Math.abs(a.testi-a.test0)?1:0))?a.test0=a.testi:0;a.n=a.bd_dat0+a.test0*a.bd_recsz;a.creep=a.gmegabuf[Math.floor(a.n+1)];a.beat=(0a.creepo?1:0);a.beatct=.000011.2*sqrt(a.bass_att)?1:0)?(a.rot=.00001 1.333)))).xyz;\n ret_1 = tmpvar_12;\n vec4 tmpvar_13;\n tmpvar_13.w = 1.0;\n tmpvar_13.xyz = tmpvar_12;\n ret = tmpvar_13.xyz;\n }', + comp: ' shader_body { \n vec3 ret_1;\n ret_1 = mix (texture (sampler_main, uv).xyz, texture (sampler_main, ((0.5 - uv) + 0.5)).xyz, vec3(0.5, 0.5, 0.5));\n ret_1 = (1.0 - ((ret_1 * \n (1.0 - ret_1)\n ) * 4.0));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 0.925, + echo_zoom: 1.007, + echo_orient: 3, + wave_brighten: 0, + brighten: 1, + darken: 1, + solarize: 1, + wave_a: 0.001, + wave_scale: 0.01, + wave_smoothing: 0, + modwavealphastart: 1, + modwavealphaend: 1, + warpanimspeed: 1.459, + warpscale: 2.007, + fshader: 1, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0.015, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 5, + mv_a: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 100, + textured: 1, + rad: 0.789, + ang: 0.6283, + tex_zoom: 1.17257, + r: 0, + g: 1, + border_a: 0, + }, + init_eqs_str: 'a.an=0;a.vx=0;a.vy=0;', + frame_eqs_str: 'a.rad=.65+.1*a.bass;a.an=.99*a.an+.1*(a.bass-a.treb);a.ang=.1*a.an+.6;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + samples: 495, + sep: 4, + spectrum: 1, + thick: 1, + additive: 1, + scaling: 100, + smoothing: 1, + r: 0, + g: 0.04, + b: 0, + a: 0.99, + }, + init_eqs_str: + 'a.my_z=0;a.d=0;a.n=0;a.y3=0;a.z2=0;a.y1=0;a.w=0;a.t5=0;a.w2=0;a.t1=0;a.x1=0;a.q6=0;a.zoom=0;a.p=0;a.q1=0;a.q5=0;a.t8=0;a.z3=0;a.w3=0;a.t3=0;a.my_x=0;a.x3=0;a.t6=0;a.my_y=0;a.pi=0;a.q4=0;a.t7=0;a.rd=0;a.w1=0;a.x2=0;a.t2=0;a.l=0;a.y2=0;a.q2=0;a.z1=0;a.q3=0;a.t4=0;a.t2=0;a.t3=0;a.t4=0;a.ab=1;', + frame_eqs_str: 'a.t1=a.q1;a.t2=a.q2;a.t3=a.q3;a.t4=a.q4;a.t5=a.q5;a.t6=a.q6;a.t8=.07;a.t7=1;', + point_eqs_str: + 'a.t7=-a.t7;a.pi=Math.asin(1);a.n=180;a.rd=.075;a.my_x=.5*Math.sin(a.sample*a.pi*4+(a.t7+1)*a.t8)+Math.cos(a.sample*a.pi*a.n)*a.rd*Math.sin(a.sample*a.pi*4+(a.t7+1)*a.t8);a.my_y=.5*Math.cos(a.sample*a.pi*4+(a.t7+1)*a.t8)+Math.cos(a.sample*a.pi*a.n)*a.rd*Math.cos(a.sample*a.pi*4+(a.t7+1)*a.t8);a.my_z=Math.sin(a.sample*a.pi*a.n)*a.rd;a.d=1.4;a.zoom=.65;a.w1=a.q2;a.w2=a.q3;a.w3=a.q4;a.x1=Math.cos(a.w1)*a.my_x+Math.sin(a.w1)*a.my_y;a.y1=-Math.sin(a.w1)*a.my_x+Math.cos(a.w1)*a.my_y;\na.z1=a.my_z;a.x2=Math.cos(a.w2)*a.x1+Math.sin(a.w2)*a.z1;a.z2=-Math.sin(a.w2)*a.x1+Math.cos(a.w2)*a.z1;a.y2=a.y1;a.y3=Math.cos(a.w3)*a.y2+Math.sin(a.w3)*a.z2;a.z3=-Math.sin(a.w3)*a.y2+Math.cos(a.w3)*a.z2;a.x3=a.x2;a.l=sqrt(a.x3*a.x3+a.y3*a.y3);a.w=Math.atan2(a.x3,a.y3);a.p=Math.tan(Math.asin(1)+Math.atan2(a.d+a.z3,a.l));a.d=sqrt(a.x3*a.x3+a.y3*a.y3+(a.z3+a.d)*(a.z3+a.d));a.my_x=a.zoom*Math.sin(a.w)*a.p;a.my_y=a.zoom*Math.cos(a.w)*a.p;a.x=.5+a.my_x;a.y=.5+a.my_y;a.b=-a.z3+.5;a.b=.5*Math.min(1,Math.max(0,\na.b));a.r=1-2*a.b;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q29=0;a.q1=0;a.dec_med=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q28=0;a.q30=0;a.q20=0;a.p4=0;a.step=0;a.step=0;', + frame_eqs_str: + 'a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,-2+a.avg+a.peak)*above(a.time,a.t0+.1);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,16);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+\na.mid_att+a.treb_att;a.q27=a.index+1;a.q28=a.index2;a.q29=2*(mod(a.index,2)-.5);a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,8);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.step+=a.q24;a.p3=a.p3*a.dec_slow+(1-a.dec_slow)*a.step;a.q30=a.step;a.p4=a.dec_slow*a.p4+(1-a.dec_slow)*a.q27;a.q31=a.p4;a.q12=a.time-a.t0;a.monitor=a.q12;a.zoom=1;a.rot=-0;a.dx=0;', + pixel_eqs_str: 'a.zoom=1.3;', + warp: ' shader_body { \n vec2 uv_1;\n vec2 uv6_2;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv - 0.5) * aspect.xy);\n float tmpvar_4;\n tmpvar_4 = (((q29 * 2.0) * sqrt(\n dot (tmpvar_3, tmpvar_3)\n )) + (rand_frame * 64.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_4) / cos(tmpvar_4)) * normalize(tmpvar_3))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 20.0));\n uv6_2 = (0.4 * sin((tmpvar_3 * 22.0)));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (((q24 * \n (((texture (sampler_main, uv_1).xyz - (\n ((texture (sampler_blur1, fract(uv_1)).xyz * scale1) + bias1)\n * 0.04)) + (0.15 * (vec3(\n (0.1 / sqrt(dot (uv6_2, uv6_2)))\n ) * roam_cos.xyz))) - 0.02)\n ) * 0.98) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_5.xyz;\n }', + comp: 'uniform sampler2D sampler_rand00;\n shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ((texture (sampler_rand00, (0.4 + \n (0.6 * tmpvar_1.xy)\n )) * tmpvar_1.z) * 3.0).xyz;\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 2, + gammaadj: 2.7, + wave_mode: 1, + modwavealphabyvolume: 1, + wave_a: 2.707, + wave_scale: 1.025, + wave_smoothing: 0.1, + modwavealphastart: 0.77, + modwavealphaend: 1.01, + warpscale: 1.331, + zoom: 1.014, + warp: 0.21786, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: '', + frame_eqs_str: + 'a.wave_r+=.35*(.6*Math.sin(3.98*a.time)+.4*Math.sin(11.047*a.time));a.wave_g+=.35*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.35*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.cx+=.11*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.cy+=.11*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.dx+=.005*(.6*Math.sin(.173*a.time)+.4*Math.sin(.223*a.time));a.decay-=.01*equal(mod(a.frame,20),0);', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (texture (sampler_main, (uv + (\n (texture (sampler_main, (mix (uv, uv_orig, vec2(-1.0, -1.0)) + texsize.zw)).xy - 0.37)\n * 0.01))).xyz - 0.004);\n ret = tmpvar_1.xyz;\n }', + comp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = mix (vec3(dot (tmpvar_1.xyz, vec3(0.3333, 0.3333, 0.3333))), tmpvar_1.xyz, vec3(3.0, 3.0, 3.0));\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.9, + echo_zoom: 1.16936, + wave_mode: 7, + modwavealphabyvolume: 1, + wave_a: 0, + wave_scale: 1.015009, + wave_smoothing: 0.522, + modwavealphastart: 0.83, + modwavealphaend: 1.31, + warpscale: 3.138, + zoom: 1.009006, + warp: 536e-6, + wave_r: 0.5, + wave_g: 0.5, + wave_b: 0.5, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: 'a.dx_residual=0;a.dy_residual=0;a.bass_thresh=0;', + frame_eqs_str: + 'a.wave_r=.85+.25*Math.sin(.437*a.time+1);a.wave_g=.85+.25*Math.sin(.544*a.time+2);a.wave_b=.85+.25*Math.sin(.751*a.time+3);a.rot+=.01*(.6*Math.sin(.381*a.time)+.4*Math.sin(.579*a.time));a.cx+=.21*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.cy+=.21*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.dx+=.003*(.6*Math.sin(.234*a.time)+.4*Math.sin(.277*a.time));a.dy+=.003*(.6*Math.sin(.284*a.time)+.4*Math.sin(.247*a.time));a.decay-=.01*equal(mod(a.frame,6),0);a.dx+=\na.dx_residual;a.dy+=a.dy_residual;a.bass_thresh=2*above(a.bass_att,a.bass_thresh)+(1-above(a.bass_att,a.bass_thresh))*(.96*(a.bass_thresh-1.3)+1.3);a.dx_residual=.016*equal(a.bass_thresh,2.13)*Math.sin(7*a.time)+(1-equal(a.bass_thresh,2.13))*a.dx_residual;a.dy_residual=.012*equal(a.bass_thresh,2.13)*Math.sin(9*a.time)+(1-equal(a.bass_thresh,2.13))*a.dy_residual;a.wave_x-=7*a.dx_residual;a.wave_y-=7*a.dy_residual;a.wave_mystery=.03*a.time;a.zoom+=.005*(.6*Math.sin(.1934*a.time+3)+.4*Math.sin(.307*\na.time+9));a.zoom+=.4*Math.max(0,a.bass_att-1.1);', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec3 ret_1;\n ret_1 = texture (sampler_main, uv).xyz;\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n ret_1 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }', + comp: ' shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz + ((\n (texture (sampler_blur1, uv).xyz * scale1)\n + bias1) * 0.4));\n vec3 tmpvar_2;\n tmpvar_2 = pow (ret_1, vec3(0.5, 0.8, 1.7));\n ret_1 = tmpvar_2;\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = tmpvar_2;\n ret = tmpvar_3.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1, + decay: 1, + wave_mode: 6, + additivewave: 1, + wave_dots: 1, + wave_thick: 1, + wave_brighten: 0, + wave_a: 100, + wave_scale: 3.63, + wave_smoothing: 0.9, + wave_mystery: -0.3, + modwavealphastart: 1.15, + modwavealphaend: 1.55, + warpscale: 1.331, + zoom: 0.96971, + warp: 0, + wave_r: 0.6, + wave_g: 0.6, + wave_b: 0.6, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_r: 0.35, + mv_g: 0.35, + mv_b: 0.35, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.decay_rate=0;a.q6=0;a.rot_sum=0;a.q1=0;a.q5=0;a.prev_beat=0;a.is_beat=0;a.min_att=0;a.beat=0;a.decay_to=0;a.rot_sim=0;a.q2=0;a.q3=0;a.beat_level=0;a.rot_sum=0;a.q2=.07+.00004*randint(1E3)+.00003*randint(1E3);a.q3=1.035+.06*(randint(1E3)+randint(1E3)+randint(1E3))*.000333;', + frame_eqs_str: + 'a.wave_r+=.5*(.6*Math.sin(1.98*a.time)+.4*Math.sin(3.047*a.time));a.wave_g+=.5*(.6*Math.sin(2.835*a.time)+.4*Math.sin(2.081*a.time));a.wave_b+=.5*(.6*Math.sin(3.814*a.time)+.4*Math.sin(1.011*a.time));a.cx=.5;a.cy=.5;a.rot=a.q2;a.zoom=a.zoom-1+a.q3;a.rot_sum+=a.rot;a.q1=-a.rot_sum;a.q5=Math.cos(a.rot_sum);a.q6=Math.sin(a.rot_sim);a.monitor=a.q2;a.min_att=2.5;a.decay_to=.8;a.decay_rate=pow(.999,a.fps);a.beat=div(a.bass,Math.max(a.min_att,a.bass_att));a.beat=Math.max(a.beat,div(a.mid,\nMath.max(a.min_att,a.mid_att)));a.beat=Math.max(a.beat,div(a.treb,Math.max(a.min_att,a.treb_att)));a.beat=Math.max(a.beat,(a.prev_beat-a.decay_to)*a.decay_rate+a.decay_to);a.beat_level=24*(a.beat-a.prev_beat-.02);a.is_beat=above(a.beat_level,.5);a.prev_beat=a.beat;a.wave_a=a.beat_level;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (texture (sampler_pw_main, uv).xyz - 0.004);\n ret = tmpvar_1.xyz;\n }', + comp: ' shader_body { \n vec2 uv_1;\n vec2 uv2_2;\n uv_1 = (uv - 0.5);\n uv_1 = (uv_1 * (min (aspect.x, aspect.y) * 0.8));\n uv_1 = (uv_1 * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = sin(q1);\n float tmpvar_4;\n tmpvar_4 = cos(q1);\n uv2_2.x = ((uv_1.x * tmpvar_4) - (uv_1.y * tmpvar_3));\n uv2_2.y = ((uv_1.x * tmpvar_3) + (uv_1.y * tmpvar_4));\n uv2_2 = (uv2_2 * aspect.zw);\n uv2_2 = (uv2_2 + 0.5);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (abs((\n (texture (sampler_main, uv2_2).xyz * 2.65)\n + \n (((texture (sampler_blur1, uv2_2).xyz * scale1) + bias1) * -2.0)\n )) * 1.5);\n ret = tmpvar_5.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.9, + echo_zoom: 1.16936, + wave_mode: 5, + additivewave: 1, + wave_a: 0, + wave_scale: 0.899719, + wave_smoothing: 0.63, + wave_mystery: 1, + modwavealphastart: 2, + modwavealphaend: 2, + warpscale: 2.593743, + zoom: 1.00496, + warp: 0.278033, + sx: 0.999666, + sy: 0.9999, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + mv_x: 0, + mv_y: 48, + mv_dx: -0.941273, + mv_dy: 0.426319, + mv_l: 5, + mv_r: 0.315997, + mv_g: 0.078173, + mv_b: 0.941976, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.du=0;a.q1=0;a.rg=0;a.q9=0;a.mult=0;a.ang2=0;a.dv=0;a.q4=0;a.q2=0;a.dist=0;a.q3=0;a.rg=0;', + frame_eqs_str: + 'a.wave_r+=.35*(.6*Math.sin(.98*a.time)+.4*Math.sin(1.047*a.time));a.wave_g+=.35*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.35*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.q1=2*a.cx-1+.52*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.q2=2*a.cy-1+.52*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));a.q3=2*a.cx-1+.52*(.6*Math.sin(.174*-a.time)+.4*Math.sin(.364*a.time));a.q4=2*a.cy-1+.52*(.6*Math.sin(.234*a.time)+.4*Math.sin(.271*-a.time));\na.decay-=.01*equal(mod(a.frame,5),0);a.rg=Math.max(.95*a.rg,.3+.5*Math.min(2,1.3*Math.max(0,a.mid_att-1)));a.q9=a.rg;', + pixel_eqs_str: + 'a.du=2*a.x-1-a.q1;a.dv=2*a.y-1-a.q2;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv);a.mult=div(.008,a.dist+.4);a.dx=a.mult*Math.sin(a.ang2-1.5);a.dy=a.mult*Math.cos(a.ang2-1.5);a.du=2*a.x-1-a.q3;a.dv=2*a.y-1-a.q4;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv);a.mult=div(.008,a.dist+.4);a.dx+=a.mult*Math.sin(a.ang2+1.5);a.dy+=a.mult*Math.cos(a.ang2+1.5);', + warp: ' shader_body { \n vec3 ret_1;\n vec2 tmpvar_2;\n tmpvar_2 = mix (uv_orig, uv, vec2(q9));\n ret_1 = texture (sampler_main, tmpvar_2).xyz;\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur1, tmpvar_2).xyz * scale1) + bias1)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n ret_1 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = ret_1;\n ret = tmpvar_3.xyz;\n }', + comp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = (0.3 + (0.4 * vec3(dot (texture (sampler_main, uv).xyz, vec3(0.32, 0.49, 0.29)))));\n ret = tmpvar_1.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.9, + echo_zoom: 1.169, + echo_orient: 1, + wave_mode: 5, + additivewave: 1, + wave_a: 0, + wave_scale: 0.9, + wave_smoothing: 0.63, + wave_mystery: 1, + modwavealphastart: 2, + modwavealphaend: 2, + warpscale: 1.331, + zoom: 1.004, + warp: 0.19788, + sx: 0.99967, + sy: 0.9999, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + mv_x: 0, + mv_y: 48, + mv_dx: -0.941, + mv_dy: 0.426, + mv_l: 5, + mv_r: 0.316, + mv_g: 0.078, + mv_b: 0.942, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: 'a.du=0;a.q1=0;a.dv=0;a.q2=0;a.dist=0;a.ang2=0;a.mult=0;', + frame_eqs_str: + 'a.wave_r+=.2*(.6*Math.sin(.98*a.time)+.4*Math.sin(1.047*a.time));a.wave_g+=.2*(.6*Math.sin(.835*a.time)+.4*Math.sin(1.081*a.time));a.wave_b+=.2*(.6*Math.sin(.814*a.time)+.4*Math.sin(1.011*a.time));a.q1=2*a.cx-1+.6*(.6*Math.sin(.374*a.time)+.4*Math.sin(.294*a.time));a.q2=2*a.cy-1+.6*(.6*Math.sin(.393*a.time)+.4*Math.sin(.223*a.time));', + pixel_eqs_str: + 'a.du=2*a.x-1-a.q1;a.dv=2*a.y-1-a.q2;a.dist=sqrt(a.du*a.du+a.dv*a.dv);a.ang2=Math.atan2(a.du,a.dv)+.15*a.time;a.mult=.65*Math.sin(.05*a.dist);a.dx=a.mult*Math.sin(2*a.ang2-1.5);a.dy=a.mult*Math.cos(2*a.ang2-1.5);', + warp: ' shader_body { \n vec3 ret_1;\n vec4 tmpvar_2;\n tmpvar_2 = texture (sampler_main, uv);\n ret_1 = (tmpvar_2.xyz + ((tmpvar_2.xyz - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n ) * 0.3));\n ret_1 = (ret_1 * 0.9);\n ret_1 = (ret_1 + ((\n ((texture (sampler_noise_lq, ((\n (uv_orig * texsize.xy)\n * \n (texsize_noise_lq.zw * 0.4)\n ) + rand_frame.xy)).xyz - 0.5) / 256.0)\n * 122.0) * clamp (\n (treb_att - 1.0)\n , 0.0, 1.0)));\n vec3 tmpvar_3;\n tmpvar_3 = mix (ret_1, vec3(dot (ret_1, vec3(0.32, 0.49, 0.29))), vec3(0.2, 0.2, 0.2));\n ret_1 = tmpvar_3;\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = tmpvar_3;\n ret = tmpvar_4.xyz;\n }', + comp: ' shader_body { \n vec2 uv2_1;\n vec3 ret_2;\n uv2_1 = (uv + (vec2(1.0, 0.0) * texsize.zw));\n float tmpvar_3;\n tmpvar_3 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(-1.0, 0.0) * texsize.zw));\n float tmpvar_4;\n tmpvar_4 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, 1.0) * texsize.zw));\n float tmpvar_5;\n tmpvar_5 = (((texture (sampler_main, uv2_1).xyz + \n (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4)\n ) + (\n ((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2)\n * 0.15)) + ((\n (texture (sampler_blur3, uv2_1).xyz * scale3)\n + bias3) * 0.1)).x;\n uv2_1 = (uv + (vec2(0.0, -1.0) * texsize.zw));\n vec3 tmpvar_6;\n tmpvar_6.z = 0.14;\n tmpvar_6.x = (tmpvar_3 - tmpvar_4);\n tmpvar_6.y = (tmpvar_5 - ((\n (texture (sampler_main, uv2_1).xyz + (((texture (sampler_blur1, uv2_1).xyz * scale1) + bias1) * 0.4))\n + \n (((texture (sampler_blur2, uv2_1).xyz * scale2) + bias2) * 0.15)\n ) + (\n ((texture (sampler_blur3, uv2_1).xyz * scale3) + bias3)\n * 0.1)).x);\n ret_2 = (0.5 + (0.5 * normalize(tmpvar_6)));\n vec2 x_7;\n x_7 = (ret_2.xy - 0.5);\n ret_2 = (ret_2 * clamp ((\n sqrt(dot (x_7, x_7))\n * 5.0), 0.0, 1.0));\n ret_2 = ret_2.xxy;\n ret_2 = (ret_2 + 1.15);\n ret_2 = (ret_2 * mix (ret_2, (ret_2 * \n (((texture (sampler_blur3, uv).xyz * scale3) + bias3) - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n ), pow (hue_shader.yxz, ret_2)));\n ret_2 = (ret_2 * ret_2);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = ret_2;\n ret = tmpvar_8.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 2.4, + decay: 1, + echo_zoom: 0.997, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 2, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.28, + wave_smoothing: 0.9, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpanimspeed: 2.599, + warpscale: 0.01, + zoomexp: 0.99817, + zoom: 0.86978, + warp: 0.01, + sy: 1.0017, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0, + ob_r: 1, + ob_g: 1, + ob_b: 1, + ib_size: 0.04, + ib_r: 0, + ib_g: 0, + ib_b: 0, + ib_a: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0.5, + mv_r: 0.35, + mv_g: 0.35, + mv_b: 0.35, + mv_a: 0.2, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 20, + additive: 1, + textured: 1, + rad: 1.99867, + tex_zoom: 0.49486, + g: 1, + b: 1, + a: 0.75, + r2: 1, + b2: 1, + a2: 1, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: '', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.ang2=0;a.redsine=0;a.greensine=0;a.bluesine=0;a.redif=0;a.greenif=0;a.blueif=0;a.decay=.1;', + frame_eqs_str: + 'a.sx=1;a.sy=1;a.redsine=.5+.15*a.bass*Math.sin(3*a.time);a.greensine=.5+.15*a.mid*Math.sin(2*a.time);a.bluesine=.5+.15*a.treb*Math.sin(a.time);a.redif=.9*(.00001 (q21 * q13)) && (tmpvar_2.x <= (q24 * q11)))) {\n ret_1.y = (tmpvar_2.y - (tmpvar_3.x * 0.5));\n };\n if (((ret_1.y > (q22 * q11)) && (ret_1.y <= (q25 * q12)))) {\n ret_1.z = (tmpvar_2.z - (tmpvar_3.y * 0.5));\n };\n if (((ret_1.z > (q23 * q12)) && (ret_1.z <= (q26 * q13)))) {\n ret_1.x = (tmpvar_2.x - (tmpvar_3.z * 0.5));\n };\n ret_1 = (ret_1 + ((ret_1 - \n ((texture (sampler_blur1, uv).xyz * scale1) + bias1)\n ) * 0.2));\n ret_1 = (ret_1 - 0.02);\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = ret_1;\n ret = tmpvar_4.xyz;\n }', + comp: ' shader_body { \n vec2 uv_1;\n vec3 ret_2;\n uv_1 = (0.05 + (0.9 * uv));\n vec4 tmpvar_3;\n tmpvar_3 = texture (sampler_main, uv_1);\n ret_2 = tmpvar_3.xyz;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_noisevol_hq, (((vec3(0.05, 0.05, 0.0) * uv_1.xyy) * (\n (q28 * texsize.xyy)\n * texsize_noisevol_hq.zww)) + ((time * vec3(0.0, 0.0, 1.0)) * q31)));\n if (((tmpvar_3.x > (q26 * q13)) && (tmpvar_3.x <= (q23 * q11)))) {\n ret_2.z = (tmpvar_3.z - (tmpvar_4.x * 0.5));\n };\n if (((tmpvar_3.y > (q25 * q11)) && (tmpvar_3.y <= (q22 * q12)))) {\n ret_2.x = (tmpvar_3.x - (tmpvar_4.y * 0.5));\n };\n if (((ret_2.z > (q24 * q12)) && (ret_2.z <= (q21 * q13)))) {\n ret_2.y = (tmpvar_3.y - (tmpvar_4.z * 0.5));\n };\n ret_2 = (abs((\n ((texture (sampler_blur1, uv_1).xyz * scale1) + bias1)\n - ret_2)) * 6.0);\n ret_2 = (ret_2 * 1.333);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 1.157, + wave_smoothing: 0.63, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpscale: 1.331, + zoom: 0.9995, + warp: 0.009, + wave_r: 0.65, + wave_g: 0.65, + wave_b: 0.65, + ob_size: 0.5, + ob_r: 0.01, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_a: 0, + b1x: 0.7, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 14, + num_inst: 512, + rad: 0.1026, + tex_ang: 0.62832, + r2: 1, + g2: 0, + a2: 1, + border_a: 0, + }, + init_eqs_str: 'a.ma=0;a.mx=0;a.my=0;a.r_border=0;a.g_border=0;a.b_border=0;', + frame_eqs_str: + 'a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001 1.0)\n ) * (\n (tmpvar_9 * -2.0)\n + 1.570796)));\n tmpvar_7 = (tmpvar_9 * sign((uv5_4.y / uv5_4.x)));\n if ((abs(uv5_4.x) > (1e-08 * abs(uv5_4.y)))) {\n if ((uv5_4.x < 0.0)) {\n if ((uv5_4.y >= 0.0)) {\n tmpvar_7 += 3.141593;\n } else {\n tmpvar_7 = (tmpvar_7 - 3.141593);\n };\n };\n } else {\n tmpvar_7 = (sign(uv5_4.y) * 1.570796);\n };\n xlat_mutablers0.x = (((tmpvar_7 / 3.1416) * 6.0) * q28);\n float tmpvar_10;\n tmpvar_10 = (1.5 / sqrt(dot (uv_1, uv_1)));\n xlat_mutablers0.y = tmpvar_10;\n vec2 tmpvar_11;\n tmpvar_11.x = (xlat_mutablers0.x + (q9 * 4.0));\n tmpvar_11.y = (tmpvar_10 + ((q9 * q28) * 4.0));\n xlat_mutablerss = (tmpvar_11 / 12.0);\n vec2 tmpvar_12;\n tmpvar_12.x = q5;\n tmpvar_12.y = q6;\n ofs_2 = (0.1 * tmpvar_12.yx);\n float tmpvar_13;\n float tmpvar_14;\n tmpvar_14 = -(q9);\n tmpvar_13 = fract(tmpvar_14);\n mat2 tmpvar_15;\n tmpvar_15[uint(0)].x = 1.0;\n tmpvar_15[uint(0)].y = -0.0;\n tmpvar_15[1u].x = 0.0;\n tmpvar_15[1u].y = 1.0;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_13)\n * tmpvar_15)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * (1.0 - \n (tmpvar_13 * tmpvar_13)\n )));\n float tmpvar_16;\n tmpvar_16 = fract((tmpvar_14 + 0.3333333));\n mat2 tmpvar_17;\n tmpvar_17[uint(0)].x = -0.4990803;\n tmpvar_17[uint(0)].y = -0.8665558;\n tmpvar_17[1u].x = 0.8665558;\n tmpvar_17[1u].y = -0.4990803;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_16)\n * tmpvar_17)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_16 * tmpvar_16)\n )));\n float tmpvar_18;\n tmpvar_18 = fract((tmpvar_14 + 0.6666667));\n mat2 tmpvar_19;\n tmpvar_19[uint(0)].x = -0.5018377;\n tmpvar_19[uint(0)].y = 0.8649619;\n tmpvar_19[1u].x = -0.8649619;\n tmpvar_19[1u].y = -0.5018377;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_18)\n * tmpvar_19)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_18 * tmpvar_18)\n )));\n float tmpvar_20;\n tmpvar_20 = fract((tmpvar_14 + 1.0));\n mat2 tmpvar_21;\n tmpvar_21[uint(0)].x = 0.9999949;\n tmpvar_21[uint(0)].y = 0.003185092;\n tmpvar_21[1u].x = -0.003185092;\n tmpvar_21[1u].y = 0.9999949;\n xlat_mutableuv2 = ((uv_1 * (\n (q13 * tmpvar_20)\n * tmpvar_21)) * aspect.yx);\n xlat_mutableneu = (3.0 * texture (sampler_main, fract((\n (xlat_mutableuv2 + 0.5)\n + ofs_2)))).xyz;\n ret1_3 = max (ret1_3, (xlat_mutableneu * (1.0 - \n (tmpvar_20 * tmpvar_20)\n )));\n vec2 tmpvar_22;\n tmpvar_22.x = (ret1_3.x + ret1_3.z);\n tmpvar_22.y = (ret1_3.x - ret1_3.y);\n xlat_mutableret2 = (((\n (texture (sampler_blur1, fract((xlat_mutablerss + (tmpvar_22 / 2.0)))).xyz * scale1)\n + bias1) / tmpvar_10) * 12.0);\n vec4 tmpvar_23;\n tmpvar_23.w = 1.0;\n tmpvar_23.xyz = ((ret1_3 + (\n ((bass_att * 0.004) / sqrt(dot (uv_1, uv_1)))\n * roam_sin).xyz) + (sqrt(xlat_mutableret2.zxy) * clamp (\n (1.0 - (ret1_3 * 4.0))\n , 0.0, 1.0)));\n ret = tmpvar_23.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 2, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.958, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0, + ob_g: 0.1, + ob_b: 1, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + mv_x: 25.6, + mv_y: 9.6, + mv_l: 0, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.n=0;a.reg26=0;a.uvx0=0;a.reg34=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.q12=0;a.v3=0;a.q22=0;a.q21=0;a.diry=0;a.q13=0;a.q6=0;a.posx=0;a.fps_=0;a.reg25=0;a.uvx=0;a.q1=0;a.travel=0;a.posz=0;a.q5=0;a.movz=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.slow=0;a.reg36=0;a.reg22=0;a.uvy=0;a.rotz=0;a.dist_=0;a.q23=0;a.q24=0;a.reg24=0;a.cran0=0;a.vx=0;a.ran2=0;a.q11=0;a.q10=0;a.reg14=0;a.posy=0;a.vy=0;a.vz=0;a.reg31=0;a.dirx=0;a.dec_m=0;a.q4=0;a.start=0;a.reg12=\n0;a.reg13=0;a.c2=0;a.reg37=0;a.s3=0;a.yslope=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.reg35=0;a.reg11=0;a.tx=0;a.avg=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.beat=0;a.q17=0;a.vol=0;a.reg32=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.reg30=0;a.q27=0;a.slen=0;a.q14=0;a.dist=0;a.reg17=0;a.v1=0;a.speed=0;a.s1=0;a.t0=0;a.s2=0;a.ran1=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.ty=0;a.c1=0;a.v2=0;a.q20=0;a.q8=0;a.avg=.01;a.q7=.2;a.q8=div(randint(200),100)-1;a.q16=1.2;a.q18=randint(.8)+.1;a.q17=2.6;a.start=1;a.travel=\n0;a.rotz=0;a.look=0;a.slow=0;a.t0=a.time+3;a.lampx=.5;a.lampy=.5;a.cran0=randint(1);for(var b=a.n=0;1E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(10)-5;a.posy=randint(10)-5;a.posz=randint(10)-5;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)*a.q17+a.uvx0,a.uvy=(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)*a.q17+a.uvy0,a.uvz=(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)*a.q17+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);', + frame_eqs_str: + 'a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.03*30,a.fps_);a.dec_m=1-div(3,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001a.dist_?1:0);a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*\na.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+\na.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=\na.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001\na.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)*a.q17+a.uvx0,a.uvy=(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)*a.q17+a.uvy0,a.uvz=(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)*a.q17+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+\n2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.warp=0;a.zoom=1;a.dx=div(-a.v2,a.q16);a.dy=div(a.v3,a.q16);a.rot=a.v1;a.vx-=div(a.v2,a.q16);a.vy+=div(a.v3,a.q16);a.vz+=a.v1;a.q11=a.vx;a.q12=a.vy;a.movz+=a.ds;a.q13=a.movz;a.monitor=a.q13;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: 'float sustain;\nfloat ffac;\nfloat xlat_mutabledist;\nfloat xlat_mutablelimit;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (0.98 - q14);\n ffac = q17;\n vec2 uv_3;\n uv_3 = (((uv - 0.5) * (1.0 - \n (q10 / (1.0 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1).z))\n )) + 0.5);\n xlat_mutableuv1 = (((uv_orig - 0.5) * aspect.xy) * q16);\n vec4 tmpvar_4;\n tmpvar_4 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n vec3 tmpvar_5;\n tmpvar_5 = tmpvar_4.xyz;\n if ((tmpvar_4.y > (0.4 * rad))) {\n vec3 tmpvar_6;\n tmpvar_6 = (tmpvar_4.xyz - vec3(0.5, 0.5, 0.5));\n vec4 nb2_7;\n vec4 nb_8;\n vec2 tmpvar_9;\n tmpvar_9 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 - texsize.zw)).yz)\n + vec2(0.5, 0.5))));\n nb_8.x = (1.0 - (tmpvar_9.y + (0.015625 * \n (tmpvar_9.x - 0.5)\n )));\n vec2 tmpvar_10;\n tmpvar_10 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(1.0, -1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb_8.y = (1.0 - (tmpvar_10.y + (0.015625 * \n (tmpvar_10.x - 0.5)\n )));\n vec2 tmpvar_11;\n tmpvar_11 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + texsize.zw)).yz)\n + vec2(0.5, 0.5))));\n nb_8.z = (1.0 - (tmpvar_11.y + (0.015625 * \n (tmpvar_11.x - 0.5)\n )));\n vec2 tmpvar_12;\n tmpvar_12 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(-1.0, 1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb_8.w = (1.0 - (tmpvar_12.y + (0.015625 * \n (tmpvar_12.x - 0.5)\n )));\n vec2 tmpvar_13;\n tmpvar_13 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(0.0, -1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.x = (1.0 - (tmpvar_13.y + (0.015625 * \n (tmpvar_13.x - 0.5)\n )));\n vec2 tmpvar_14;\n tmpvar_14 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(1.0, 0.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.y = (1.0 - (tmpvar_14.y + (0.015625 * \n (tmpvar_14.x - 0.5)\n )));\n vec2 tmpvar_15;\n tmpvar_15 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(0.0, 1.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.z = (1.0 - (tmpvar_15.y + (0.015625 * \n (tmpvar_15.x - 0.5)\n )));\n vec2 tmpvar_16;\n tmpvar_16 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, (uv_3 + (texsize.zw * vec2(-1.0, 0.0)))).yz)\n + vec2(0.5, 0.5))));\n nb2_7.w = (1.0 - (tmpvar_16.y + (0.015625 * \n (tmpvar_16.x - 0.5)\n )));\n vec4 tmpvar_17;\n tmpvar_17 = min (nb_8, nb2_7);\n nb_8.zw = tmpvar_17.zw;\n nb_8.xy = min (tmpvar_17.xy, tmpvar_17.zw);\n xlat_mutabledist = (min (nb_8.x, nb_8.y) + ((0.006 * tmpvar_6.x) * abs(tmpvar_6.y)));\n } else {\n xlat_mutabledist = tmpvar_5.x;\n };\n vec2 tmpvar_18;\n tmpvar_18 = (0.0078125 * floor((\n (128.0 * texture (sampler_pc_main, uv_3).yz)\n + vec2(0.5, 0.5))));\n xlat_mutabledist = (min (xlat_mutabledist, (1.0 - \n (tmpvar_18.y + (0.015625 * (tmpvar_18.x - 0.5)))\n )) - (q10 * 0.8));\n xlat_mutablelimit = (15.0 + (10.0 * xlat_mutabledist));\n vec3 tmpvar_19;\n tmpvar_19.xy = (xlat_mutableuv1 * xlat_mutabledist);\n tmpvar_19.z = xlat_mutabledist;\n xlat_mutableuv2 = (((tmpvar_19 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n int iterations_21;\n vec3 zz0_22;\n vec3 zz_23;\n zz_23 = xlat_mutableuv2;\n zz0_22 = (xlat_mutableuv2 + q8);\n iterations_21 = int((8.0 - float(\n (xlat_mutabledist > 0.8)\n )));\n for (int n_20 = 0; n_20 <= iterations_21; n_20++) {\n zz_23 = ((2.0 * clamp (zz_23, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_23);\n zz_23 = (zz_23 * (clamp (\n max ((0.25 / dot (zz_23, zz_23)), 0.25)\n , 0.0, 1.0) * 4.0));\n zz_23 = ((ffac * zz_23) + zz0_22);\n };\n xlat_mutablestruc = (sqrt(dot (zz_23.xz, zz_23.xz)) / xlat_mutablelimit);\n vec2 tmpvar_24;\n tmpvar_24 = (0.0078125 * floor((\n (128.0 * vec2((1.0 - xlat_mutabledist)))\n + vec2(0.5, 0.5))));\n vec2 tmpvar_25;\n tmpvar_25.x = ((64.0 * (\n (1.0 - xlat_mutabledist)\n - tmpvar_24.x)) + 0.5);\n tmpvar_25.y = tmpvar_24.x;\n vec3 tmpvar_26;\n float tmpvar_27;\n tmpvar_27 = (q14 * 2.0);\n tmpvar_26.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(tmpvar_27)).x));\n tmpvar_26.yz = tmpvar_25;\n vec3 tmpvar_28;\n tmpvar_28.y = 1.0;\n tmpvar_28.x = sustain;\n tmpvar_28.z = 1.0;\n vec3 tmpvar_29;\n tmpvar_29.y = 0.0;\n tmpvar_29.x = 0.003921569;\n tmpvar_29.z = (0.01568628 * (0.2 + rad));\n vec4 tmpvar_30;\n tmpvar_30.w = 1.0;\n tmpvar_30.xyz = mix (tmpvar_26, ((\n mix (texture (sampler_main, uv_3).xyz, ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1), vec3(tmpvar_27))\n * tmpvar_28) - tmpvar_29), vec3(clamp ((\n sqrt(dot (zz_23, zz_23))\n - xlat_mutablelimit), 0.0, 1.0)));\n ret = tmpvar_30.xyz;\n }', + comp: 'float xlat_mutableinten;\nfloat xlat_mutabletmp;\nvec2 xlat_mutableuv1;\nvec2 xlat_mutableuv2;\nfloat xlat_mutablez;\n shader_body { \n float t_rel_2;\n vec3 ret1_3;\n float struc_4;\n xlat_mutableuv1 = ((uv * aspect.xy) - vec2(0.5, 0.5));\n vec4 tmpvar_5;\n tmpvar_5 = texture (sampler_main, uv);\n float tmpvar_6;\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_blur1, uv);\n tmpvar_6 = mix (min ((1.0 - tmpvar_5.z), (1.0 - \n ((texture (sampler_blur2, uv).xyz * scale2) + bias2)\n .z)), (1.0 - (\n (tmpvar_7.xyz * scale1)\n + bias1).z), 0.5);\n struc_4 = ((mix (tmpvar_5.xyz, \n ((tmpvar_7.xyz * scale1) + bias1)\n , vec3(tmpvar_6)).x * (1.0 - tmpvar_6)) * tmpvar_6);\n vec2 tmpvar_8;\n tmpvar_8.x = q11;\n tmpvar_8.y = q12;\n xlat_mutableuv2 = ((xlat_mutableuv1 * 0.2) - (tmpvar_8 * 0.2));\n vec2 uvi_9;\n uvi_9 = (xlat_mutableuv2 * 4.0);\n float zv_10;\n zv_10 = (0.008 * time);\n xlat_mutabletmp = clamp (dot ((texture (sampler_noise_hq, \n (xlat_mutableuv2 + (0.03 * ((\n (dot (texture (sampler_noise_hq, uvi_9), vec4(0.32, 0.49, 0.29, 0.0)) + (dot (texture (sampler_noise_hq, (\n (uvi_9 * 2.0)\n + zv_10)), vec4(0.32, 0.49, 0.29, 0.0)) / 2.0))\n + \n (dot (texture (sampler_noise_hq, ((uvi_9 * 4.0) + (2.0 * zv_10))), vec4(0.32, 0.49, 0.29, 0.0)) / 4.0)\n ) + (\n dot (texture (sampler_noise_hq, ((uvi_9 * 8.0) + (4.0 * zv_10))), vec4(0.32, 0.49, 0.29, 0.0))\n / 8.0))))\n ) - 0.4), vec4(0.32, 0.49, 0.29, 0.0)), 0.0, 1.0);\n float tmpvar_11;\n tmpvar_11 = clamp ((pow (xlat_mutabletmp, 1.2) * sign(xlat_mutabletmp)), 0.0, 1.0);\n xlat_mutabletmp = tmpvar_11;\n vec3 tmpvar_12;\n tmpvar_12.xy = vec2(0.1, 0.1);\n tmpvar_12.z = (1.2 - uv.y);\n ret1_3 = ((tmpvar_12 + 0.07) + ((\n clamp (((tmpvar_6 * 2.0) - 1.5), 0.0, 1.0)\n * tmpvar_11) * 4.0));\n t_rel_2 = (q13 * 6.0);\n for (int n_1 = 1; n_1 <= 3; n_1++) {\n xlat_mutablez = (1.0 - fract((\n (float(n_1) / 3.0)\n - \n (fract(-(t_rel_2)) / 3.0)\n )));\n xlat_mutableinten = (((1.0 - xlat_mutablez) * xlat_mutablez) * 2.0);\n vec2 tmpvar_13;\n tmpvar_13.x = q11;\n tmpvar_13.y = q12;\n xlat_mutableuv2 = (((xlat_mutablez * xlat_mutableuv1) / 4.0) - (tmpvar_13 / 6.0));\n vec2 uvi_14;\n uvi_14 = (xlat_mutableuv2 * 4.0);\n float zv_15;\n zv_15 = (0.008 * time);\n xlat_mutabletmp = clamp (dot ((\n (texture (sampler_noise_hq, (xlat_mutableuv2 + (0.03 * (\n ((dot (texture (sampler_noise_hq, uvi_14), vec4(0.32, 0.49, 0.29, 0.0)) + (dot (texture (sampler_noise_hq, \n ((uvi_14 * 2.0) + zv_15)\n ), vec4(0.32, 0.49, 0.29, 0.0)) / 2.0)) + (dot (texture (sampler_noise_hq, (\n (uvi_14 * 4.0)\n + \n (2.0 * zv_15)\n )), vec4(0.32, 0.49, 0.29, 0.0)) / 4.0))\n + \n (dot (texture (sampler_noise_hq, ((uvi_14 * 8.0) + (4.0 * zv_15))), vec4(0.32, 0.49, 0.29, 0.0)) / 8.0)\n )))) - (xlat_mutablez * 0.5))\n - 0.3), vec4(0.32, 0.49, 0.29, 0.0)), 0.0, 1.0);\n xlat_mutabletmp = (((\n clamp ((xlat_mutabletmp * sign(xlat_mutabletmp)), 0.0, 1.0)\n * xlat_mutableinten) * q1) * 2.0);\n ret1_3 = (((ret1_3 + \n ((vec3(4.0, 3.0, 0.8) * q1) * struc_4)\n ) * clamp (\n (1.0 - xlat_mutabletmp)\n , 0.0, 1.0)) + xlat_mutabletmp);\n };\n vec4 tmpvar_16;\n tmpvar_16.w = 1.0;\n tmpvar_16.xyz = (1.0 - exp((-1.6 * ret1_3)));\n ret = tmpvar_16.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + additivewave: 1, + wave_dots: 1, + wave_thick: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.527, + wave_smoothing: 0, + wave_mystery: 0.6, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_g: 0.49, + ob_a: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b2x: 0.6, + b3x: 0.4, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { + baseVals: { + enabled: 1, + sides: 5, + additive: 1, + num_inst: 256, + x: 0.26, + y: 0.2, + rad: 0.39317, + tex_zoom: 0.9355, + g2: 0, + a2: 0.2, + border_g: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: + 'a.n=0;a.w=0;a.high=0;a.q12=0;a.arg=0;a.q13=0;a.y0=0;a.flen=0;a.x0=0;a.k1=0;a.q11=0;a.z0=0;a.exc=0;a.p2=0;a.p1=0;a.a0=0;a.q2=0;a.slen=0;a.q14=0;a.q3=0;a.q32=0;a.rad0=0;', + frame_eqs_str: + 'a.n=a.instance;a.flen=a.reg00;a.slen=div(a.reg00,2);a.z0=10;a.y0=div(a.gmegabuf[Math.floor(2E3+a.n+a.flen)],a.z0);a.x0=div(a.gmegabuf[Math.floor(2E3+a.n)],a.z0);a.a0=a.gmegabuf[Math.floor(a.n+1E4)];a.k1=div(a.instance,a.num_inst)-.5;a.x=.5+a.x0+Math.sin(8*a.k1*Math.sin(.07*a.q12))*Math.sin(.13*a.q11)*a.q3*.7;a.y=.5+a.q32*(a.y0+Math.sin(8*a.k1*Math.sin(.1*a.q14))*Math.sin(.2*a.q13)*a.q3*.7);a.arg=div(a.q2,8);a.high=Math.exp(-500*pow(a.arg+.5-div(a.instance,a.num_inst),2));a.high+=\nMath.exp(-500*pow(-a.arg+.5-div(a.instance,a.num_inst),2));a.exc=sqrt(pow(a.x-.5,2)+pow(a.y-.5,2));a.rad0=above(a.z0,0)*Math.min(.1,div(a.a0,60))+.005;a.rad0=a.rad0*(1+2*a.exc)*(1+a.high);a.p1=.5+div(Math.sin(a.q12),2);a.p2=.5+div(Math.sin(1.4*a.q13),2);a.exc=pow(a.x-a.p1,2)+pow(a.y-a.p2,2);a.rad=Math.min(a.rad0*(1+div(.004*a.q3,Math.abs(a.exc))),1);a.a=Math.min(8*a.a0+.4,1);a.k1=5*div(a.instance,a.num_inst)+a.high;a.w=1-Math.exp(div(-a.treb_att,2)-.5);a.g=a.w+(1-a.w)*Math.sin(a.k1);a.r=a.w+(1-a.w)*\nMath.sin(a.k1-div(6.28,3));a.b=a.w+(1-a.w)*Math.sin(a.k1-div(12.56,3));a.a2=div(a.a,4);a.g2=0*a.g;a.b2=0*a.b;a.r2=0*a.r;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + sep: 120, + spectrum: 1, + additive: 1, + scaling: 7.52386, + smoothing: 0, + r: 0, + a: 0.7, + }, + init_eqs_str: 'a.flen=0;a.n=0;a.vol=0;a.chg=0;a.dec=0;a.q1=0;a.q2=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.flen=a.reg00;a.n=Math.floor(a.sample*a.flen);a.vol=(a.value1+a.value2)*(1+div(.1,a.sample+.03));a.chg=Math.min(Math.max(a.vol-a.gmegabuf[Math.floor(a.n)],-1),1);a.dec=.00001a.q2?1:0))]*(1-a.dec);a.gmegabuf[Math.floor(a.n+1E4)]=.2*a.gmegabuf[Math.floor(a.n+1E4)]+div(.8*a.vol,3);a.a=0;a.x=a.sample;a.y=.2+.23*a.gmegabuf[Math.floor(a.n+0)];', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.n=0;a.sw2=0;a.in1=0;a.q12=0;a.q13=0;a.sw3=0;a.dif=0;a.q1=0;a.lev3=0;a.flen=0;a.lev4=0;a.in2=0;a.lev1=0;a.k1=0;a.q11=0;a.ofs=0;a.dec_m=0;a.i=0;a.k=0;a.m2=0;a.vol=0;a.q2=0;a.slen=0;a.m1=0;a.q14=0;a.sw1=0;a.lev2=0;a.q3=0;a.reg00=0;a.vol_=0;a.dec=0;a.q32=0;a.sw4=0;for(var b=a.n=0;5E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.sw1=randint(8);a.sw2=randint(8);a.sw3=randint(8);a.sw4=randint(8);', + frame_eqs_str: + 'a.flen=512;a.reg00=a.flen;a.slen=div(a.flen,2);a.dec_m=pow(.94,div(30,a.fps));a.n=0;for(var b=a.vol=0;ba.in1*a.in1+a.in2*a.in2?1:0)?.8:.94,a.dec=pow(a.dec,div(30,a.fps)),a.gmegabuf[Math.floor(2E3+a.n)]=a.gmegabuf[Math.floor(2E3+a.n)]*a.dec+(1-a.dec)*a.in1,a.gmegabuf[Math.floor(2E3+a.flen+a.n)]=a.gmegabuf[Math.floor(2E3+a.flen+a.n)]*a.dec+(1-a.dec)*a.in2,a.n+=1;a.q1=div(a.bass+a.treb+a.mid,3);a.q2=div(a.bass_att+a.treb_att+a.mid_att,3);a.q3=a.vol_;a.q11=a.sw1;a.q12=a.sw2;a.q13=\na.sw3;a.q14=a.sw4;a.rot=0;a.zoom=.98;a.warp=.3;a.rot=0;a.q32=a.aspecty;a.monitor=a.dif;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = ((texture (sampler_main, uv).xyz * clamp (\n (q1 - 0.8)\n , 0.0, 1.0)) * 0.92);\n ret = tmpvar_1.xyz;\n }', + comp: ' shader_body { \n vec3 ret_1;\n ret_1 = (texture (sampler_main, uv).xyz + ((texture (sampler_blur2, uv).xyz * scale2) + bias2));\n ret_1 = (ret_1 + ((0.8 * \n (hue_shader - 0.8)\n ) * (1.0 - uv.y)));\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ret_1;\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 4, + additivewave: 1, + wave_dots: 1, + modwavealphabyvolume: 1, + darken: 1, + wave_a: 0.33064, + wave_scale: 0.897961, + wave_smoothing: 0.108, + wave_mystery: 0.1, + modwavealphastart: 0.72, + modwavealphaend: 1.28, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0.5, + wave_b: 0.5, + wave_y: 0.54, + ob_r: 1, + ob_g: 1, + ob_b: 1, + ib_size: 0.26, + mv_x: 24.799994, + mv_dy: 0.16, + mv_l: 1.5, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + samples: 352, + usedots: 1, + additive: 1, + scaling: 0.038558, + smoothing: 0.2, + g: 0, + }, + init_eqs_str: 'a.t02=0;a.q1=0;a.ratio=0;a.ampl=0;a.x1=0;a.y1=0;', + frame_eqs_str: 'a.q1=a.bass_att;', + point_eqs_str: + 'a.r=Math.abs(Math.sin(div(a.frame,38)));a.g=.5*Math.abs(Math.cos(div(a.frame,45)));a.b=.5*Math.abs(Math.sin(div(a.frame,133)));a.a=.3;a.t02+=div(a.q1,10);a.ratio=Math.sin(div(a.frame,49));a.ampl=.01+.4*sqr(Math.sin(div(a.frame,18))*Math.cos(div(a.frame,123)));a.x1=div(a.r-.5,15)+.5+a.ampl*Math.sin(6.28*a.sample);a.y1=div(a.b-.5,15)+.5+a.ampl*Math.cos(6.28*a.sample);a.x=a.x1+.2*(a.ampl+a.ratio)*Math.sin(6.28*a.sample*a.ratio*7.3);a.y=a.y1+.2*(a.ampl+a.ratio)*Math.cos(37.68*a.sample);\n', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.q25=0;a.index=0;a.q18=0;a.q22=0;a.q21=0;a.q29=0;a.q6=0;a.movex=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.mov=0;a.avg=0;a.beat=0;a.p1=0;a.dx1=0;a.peak=0;a.q2=0;a.q27=0;a.clear=0;a.p3=0;a.q3=0;a.t0=0;a.rot1=0;a.q32=0;a.q28=0;a.q20=0;a.clear=.5;', + frame_eqs_str: + 'a.dec_med=pow(.96,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,4);a.index2=mod(a.index2+a.is_beat*bnot(a.index),8);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.q20=a.avg;a.q21=\na.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.p3=a.dec_med*a.p3+(1-a.dec_med)*a.p2;a.rott=div(3.1416*a.p3,4);a.rot1+=a.q26;a.q25=.01*a.rot1;a.q27=8-a.index;a.q28=a.index3;a.dx1=a.dec_med*a.dx1+(1-a.dec_med)*bnot(a.index2);a.q29=a.dx1;a.monitor=a.q29;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.q5=1.5*Math.cos(div(a.time,9));a.q6=.5*Math.sin(div(a.time,\n7));a.clear=a.clear*a.dec_med+1-a.dec_med;a.q32=a.clear;a.mov=bnot(a.q24)*a.movex+(div(randint(100),100)-50)*a.q2;a.movex+=div(.2,a.fps)*a.q2;a.q18=a.movex;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec2 uv6_1;\n vec2 tmpvar_2;\n tmpvar_2 = ((uv - 0.5) * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = (rand_frame * 64.0).x;\n uv6_1 = (0.5 * cos((\n ((tmpvar_2 * mat2(0.7, -0.7, 0.7, 0.7)) * 17.0)\n + \n (rand_frame * 6.0)\n .xy)));\n float x_4;\n x_4 = (uv6_1.x + uv6_1.y);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ((0.147 * (\n (texture (sampler_main, (uv + clamp ((\n (sin(tmpvar_3) / cos(tmpvar_3))\n * \n normalize(tmpvar_2)\n ), vec2(-8.0, -8.0), vec2(8.0, 8.0)))).xyz + (0.15 * (vec3((0.01 / \n sqrt((x_4 * x_4))\n )) * roam_cos.xyz)))\n - 0.02)) + ((0.85 * \n (texture (sampler_main, uv_orig).xyz - 0.002)\n ) * q32));\n ret = tmpvar_5.xyz;\n }', + comp: 'vec2 xlat_mutabledz;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\nvec2 xlat_mutableuv4;\n shader_body { \n vec2 uv_1;\n float inten_2;\n float dist_3;\n vec3 ret_4;\n uv_1 = (uv - 0.5);\n float tmpvar_5;\n tmpvar_5 = (time / 2.0);\n dist_3 = (1.0 - fract(tmpvar_5));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_6;\n tmpvar_6.y = 0.4;\n tmpvar_6.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_6);\n vec2 tmpvar_7;\n tmpvar_7.y = 0.0;\n tmpvar_7.x = texsize.z;\n vec2 tmpvar_8;\n tmpvar_8.y = 0.0;\n tmpvar_8.x = texsize.z;\n xlat_mutabledz.x = (inten_2 * dot ((texture (sampler_main, \n (xlat_mutableuv3 + tmpvar_7)\n ).xyz - texture (sampler_main, \n (xlat_mutableuv3 - tmpvar_8)\n ).xyz), vec3(0.32, 0.49, 0.29)));\n vec2 tmpvar_9;\n tmpvar_9.x = 0.0;\n tmpvar_9.y = texsize.w;\n vec2 tmpvar_10;\n tmpvar_10.x = 0.0;\n tmpvar_10.y = texsize.w;\n xlat_mutabledz.y = (inten_2 * dot ((texture (sampler_main, \n (xlat_mutableuv3 + tmpvar_9)\n ).xyz - texture (sampler_main, \n (xlat_mutableuv3 - tmpvar_10)\n ).xyz), vec3(0.32, 0.49, 0.29)));\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((0.3333333 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_11;\n tmpvar_11.y = 0.4;\n tmpvar_11.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_11);\n vec2 tmpvar_12;\n tmpvar_12.y = 0.0;\n tmpvar_12.x = texsize.z;\n vec2 tmpvar_13;\n tmpvar_13.y = 0.0;\n tmpvar_13.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_12)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_13)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_14;\n tmpvar_14.x = 0.0;\n tmpvar_14.y = texsize.w;\n vec2 tmpvar_15;\n tmpvar_15.x = 0.0;\n tmpvar_15.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_14)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_15)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((0.6666667 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_16;\n tmpvar_16.y = 0.4;\n tmpvar_16.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_16);\n vec2 tmpvar_17;\n tmpvar_17.y = 0.0;\n tmpvar_17.x = texsize.z;\n vec2 tmpvar_18;\n tmpvar_18.y = 0.0;\n tmpvar_18.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_17)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_18)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_19;\n tmpvar_19.x = 0.0;\n tmpvar_19.y = texsize.w;\n vec2 tmpvar_20;\n tmpvar_20.x = 0.0;\n tmpvar_20.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_19)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_20)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n dist_3 = (1.0 - fract((1.0 + tmpvar_5)));\n inten_2 = ((sqrt(dist_3) * (1.0 - dist_3)) * 2.0);\n vec2 tmpvar_21;\n tmpvar_21.y = 0.4;\n tmpvar_21.x = q18;\n xlat_mutableuv3 = (((2.0 * uv_1) * dist_3) + tmpvar_21);\n vec2 tmpvar_22;\n tmpvar_22.y = 0.0;\n tmpvar_22.x = texsize.z;\n vec2 tmpvar_23;\n tmpvar_23.y = 0.0;\n tmpvar_23.x = texsize.z;\n xlat_mutabledz.x = (xlat_mutabledz.x + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_22)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_23)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n vec2 tmpvar_24;\n tmpvar_24.x = 0.0;\n tmpvar_24.y = texsize.w;\n vec2 tmpvar_25;\n tmpvar_25.x = 0.0;\n tmpvar_25.y = texsize.w;\n xlat_mutabledz.y = (xlat_mutabledz.y + (inten_2 * dot (\n (texture (sampler_main, (xlat_mutableuv3 + tmpvar_24)).xyz - texture (sampler_main, (xlat_mutableuv3 - tmpvar_25)).xyz)\n , vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (texture (sampler_main, xlat_mutableuv3).xyz * inten_2));\n uv_1 = (uv_1 + xlat_mutabledz);\n vec2 tmpvar_26;\n tmpvar_26.x = q5;\n tmpvar_26.y = q6;\n xlat_mutableuv4 = (uv_1 - (0.4 * tmpvar_26));\n float tmpvar_27;\n tmpvar_27 = (0.1 * clamp ((1.0/(\n (abs(uv_1.y) + 0.1)\n )), 0.0, 12.0));\n vec2 tmpvar_28;\n tmpvar_28.x = (uv_1.x * tmpvar_27);\n tmpvar_28.y = tmpvar_27;\n vec3 tmpvar_29;\n tmpvar_29.xy = vec2(0.0, 0.0);\n tmpvar_29.z = clamp ((1.0 - (3.0 * uv_1.y)), 0.0, 1.0);\n ret_4 = (vec3(0.0, 0.1, 0.1) + (0.1 * tmpvar_29));\n ret_4 = (ret_4 + (vec3(dot (texture (sampler_noise_hq, \n (tmpvar_28 + (0.1 * time))\n ), vec4(0.32, 0.49, 0.29, 0.0))) * (\n (clamp ((1.0 - (12.0 * uv_1.y)), 0.0, 1.0) * 0.1)\n / \n (0.05 + sqrt(dot (xlat_mutableuv4, xlat_mutableuv4)))\n )));\n ret_4 = (ret_4 + ((0.4 * xlat_mutableret1) + (xlat_mutableret1 * q22)));\n vec4 tmpvar_30;\n tmpvar_30.w = 1.0;\n tmpvar_30.xyz = ret_4;\n ret = tmpvar_30.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 2, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 20.944651, + wave_smoothing: 0, + wave_mystery: 0.08, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0.99, + ob_size: 0.015, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + textured: 1, + y: 0.47, + rad: 0.24057, + tex_zoom: 0.14057, + g: 0.3, + b: 0.5, + g2: 0, + b2: 0.3, + a2: 1, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.q24=0;', + frame_eqs_str: 'a.x=.5;a.y=.5;a.a=a.q24;a.a2=a.q24;', + }, + { + baseVals: { + enabled: 1, + sides: 100, + additive: 1, + thickoutline: 1, + rad: 0.05134, + tex_zoom: 0.12288, + r: 0.3, + g: 0.2, + b: 0.2, + a: 0.7, + g2: 0, + border_r: 0, + border_g: 0.5, + border_b: 0.5, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: + 'a.r=.5+.3*Math.sin(a.time);a.g=.5+.3*Math.sin(div(a.time,1.5));a.b=.5+.3*Math.sin(div(a.time,3.7));a.r2=0;a.b2=0;a.g2=0;a.a=.05;a.a2=0;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, samples: 100, thick: 1, scaling: 0.045052, smoothing: 0.1, a: 0.6 }, + init_eqs_str: 'a.k1=0;a.dy=0;a.dx=0;a.t2=0;a.q24=0;a.q27=0;', + frame_eqs_str: 'a.t2=.45+div(randint(10),100);', + point_eqs_str: + 'a.k1=bnot(mod(100*a.sample+a.time,2));a.dy=.015*above(Math.sin(11*a.sample),0)+.008*above(Math.sin(a.time+74*a.sample),0)+.008*above(Math.sin(a.time+128*a.sample),0);a.dx=.01*above(Math.sin(27*a.sample),0)+.01*above(Math.sin(a.time+134*a.sample),0);a.x=.2*(a.sample-.5)+.5+a.dx;a.y=a.t2+a.dy;a.a=a.q24*a.k1*bnot(mod(a.q27,4));a.r=.6;a.g=0;a.b=.6;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.dec_xlow=0;a.index2=0;a.speed_=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.q9=0;a.movx=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q10=0;a.tilt_=0;a.q4=0;a.peakx=0;a.dir__=0;a.dir=0;a.dir_=0;a.movy=0;a.q26=0;a.maxp=0;a.p2=0;a.avg=0;a.trig=0;a.beat=0;a.p1=0;a.peak=0;a.tilt=0;a.q2=0;a.q27=0;a.speed=0;a.q3=0;a.t0=0;a.q7=0;a.q20=0;a.q8=0;a.xk=0;', + frame_eqs_str: + 'a.dec_med=pow(.8,div(30,a.fps));a.dec_slow=pow(.95,div(30,a.fps));a.dec_xlow=pow(.995,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,16);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=\na.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att;a.q27=a.index+1;a.peakx=above(a.q22,1.5*a.maxp);a.maxp=Math.max(a.maxp,a.q22);a.maxp*=a.dec_xlow;a.k1=a.is_beat*equal(mod(a.index,3),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.trig=a.q24*bnot(mod(a.index,4));a.dir=a.dir+div(a.trig*a.q26*(div(randint(100),100)-.5),2)+a.peakx;a.dir_=a.dir_*a.dec_slow+a.dir*(1-a.dec_slow);\na.dir__=a.dir__*a.dec_slow+a.dir_*(1-a.dec_slow);a.q5=Math.cos(a.dir__);a.q6=Math.sin(a.dir__);a.speed=a.speed*bnot(a.trig)+div(a.trig*a.q26*5,a.fps);a.speed_=a.speed_*a.dec_slow+a.speed*(1-a.dec_slow);a.movx+=a.speed_*a.q6;a.movy+=a.speed_*a.q5;a.q7=a.movx;a.q8=a.movy;a.tilt=a.dir-a.dir__;a.tilt_=a.dec_slow*a.tilt_+(1-a.dec_slow)*a.tilt;a.monitor=a.maxp;a.q9=Math.cos(a.tilt_*a.speed_);a.q10=Math.sin(a.tilt_*a.speed_);a.q12=a.time;', + pixel_eqs_str: 'a.zoom=1.3;', + warp: ' shader_body { \n vec2 uv_1;\n vec2 uv6_2;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv - 0.5) * aspect.xy);\n float tmpvar_4;\n tmpvar_4 = ((2.0 * sqrt(\n dot (tmpvar_3, tmpvar_3)\n )) + (rand_frame * 64.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_4) / cos(tmpvar_4)) * normalize(tmpvar_3))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 20.0));\n uv6_2 = (0.4 * sin((tmpvar_3 * 22.0)));\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = (((q24 * \n (((texture (sampler_main, uv_1).xyz - (\n ((texture (sampler_blur1, fract(uv_1)).xyz * scale1) + bias1)\n * 0.04)) + (0.15 * (vec3(\n (0.1 / sqrt(dot (uv6_2, uv6_2)))\n ) * roam_cos.xyz))) - 0.02)\n ) * 0.98) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_5.xyz;\n }', + comp: 'vec3 xlat_mutableret1;\nvec2 xlat_mutablers;\n shader_body { \n vec2 uv1_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)].x = q9;\n tmpvar_2[uint(0)].y = -(q10);\n tmpvar_2[1u].x = q10;\n tmpvar_2[1u].y = q9;\n uv1_1 = (((uv_orig - 0.5) * aspect.xy) * tmpvar_2);\n uv1_1 = (uv1_1 * aspect.yx);\n float tmpvar_3;\n tmpvar_3 = (3.0 / abs(uv1_1.y));\n xlat_mutablers.x = (uv1_1.x * tmpvar_3);\n xlat_mutablers.y = (tmpvar_3 / 2.0);\n mat2 tmpvar_4;\n tmpvar_4[uint(0)].x = q5;\n tmpvar_4[uint(0)].y = -(q6);\n tmpvar_4[1u].x = q6;\n tmpvar_4[1u].y = q5;\n xlat_mutablers = (tmpvar_4 * xlat_mutablers);\n vec2 tmpvar_5;\n tmpvar_5.x = q7;\n tmpvar_5.y = q8;\n xlat_mutablers = (xlat_mutablers + tmpvar_5);\n xlat_mutableret1 = ((texture (sampler_blur1, fract(\n (xlat_mutablers / 12.0)\n )).xyz * scale1) + bias1);\n vec2 tmpvar_6;\n tmpvar_6.y = 0.0;\n tmpvar_6.x = q5;\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (((xlat_mutableret1 * 32.0) / tmpvar_3) + ((\n ((q22 * sqrt(tmpvar_3)) / 4.0)\n * \n sin(((uv1_1 - q12) * q27))\n .x) * texture (sampler_main, (\n (((4.0 * xlat_mutableret1) / tmpvar_3).xy + ((uv1_1 / 2.0) / (0.5 + abs(uv1_1.y))))\n + tmpvar_6)).xyz));\n ret = tmpvar_7.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 0.952, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 5, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.474, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0.8, + wave_g: 0.49, + ob_size: 0, + ob_a: 0.3, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b1x: 0.8, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 7, + additive: 1, + num_inst: 1024, + rad: 0.04896, + tex_ang: 1.00531, + tex_zoom: 1.53117, + r: 0, + g: 1, + b: 1, + a: 0, + g2: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.max_age=0;a.n=0;a.x0=0;a.y0=0;a.z0=0;a.rad0=0;', + frame_eqs_str: + 'a.max_age=a.reg00;a.n=12*a.instance;a.x0=a.gmegabuf[Math.floor(a.n)];a.y0=a.gmegabuf[Math.floor(a.n+1)];a.z0=a.gmegabuf[Math.floor(a.n+2)];.00001a.z0?1:0)?(a.rad=0,a.gmegabuf[Math.floor(a.n+8)]=a.max_age):(a.rad0=div(pow(1-div(a.gmegabuf[Math.floor(a.n+8)],a.max_age),.2),a.z0)*a.gmegabuf[Math.floor(a.n+7)]+.01,a.rad=.032*Math.abs(a.rad0),a.x=.5+div(a.x0,a.z0),a.y=.5+div(a.y0,a.z0));a.a=1;a.a2=.2;a.g=.8;a.g2=0;a.b=.2*(3a.z0?1:0);a.b2=0;\n', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + samples: 160, + sep: 20, + usedots: 1, + additive: 1, + scaling: 7.858, + smoothing: 0.1, + r: 0.2, + g: 0.3, + a: 0.6, + }, + init_eqs_str: 'a.q32=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.x=div(randint(100),100);a.y=.5-div(1-.7,a.q32)-.15*(div(randint(100),100)-.5);a.a=.15;a.r=0;a.b=1;a.g=0;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.max_age=0;a.ind2=0;a.n=0;a.free=0;a.high=0;a.index=0;a.tht=0;a.v00=0;a.yobf=0;a.dt=0;a.y0=0;a.q1=0;a.dec_med=0;a.q5=0;a.ran1_=0;a["new"]=0;a.push=0;a.new1=0;a.is_beat=0;a.q24=0;a.vol_alt=0;a.dec_slow=0;a.ran2=0;a.ind1=0;a.q10=0;a.v0=0;a.med=0;a.beat=0;a.vol=0;a.peak=0;a.dec_fast=0;a.q27=0;a.bass1=0;a.q3=0;a.t0=0;a.vol_=0;a.dec=0;a.m=0;a.ran1=0;a.q32=0;a.phi=0;a.air=0;a.max_age=4.5;a.reg00=a.max_age;for(var b=a.n=0;12288>b;b++)a.gmegabuf[Math.floor(a.n)]=a.max_age-1+randint(2),\na.n+=1;a.q9=2*(randint(25)-10);a.q3=div(randint(100),100);a.q4=div(randint(100),100);', + frame_eqs_str: + 'a.dec_fast=1-div(8.8,a.fps);a.dec_med=1-div(6,a.fps);a.dec_slow=1-div(1.6,a.fps);a.vol=div(a.bass+a.med+a.treb,3);a.vol_=a.vol_*a.dec_slow+(1-a.dec_slow)*a.vol;a.beat=a.vol;a.is_beat=above(a.beat,1+4*a.peak)*above(a.time,a.t0+.2);a.t0=.00001b;b++)a.megabuf[Math.floor(a.n)]=a.gmegabuf[Math.floor(a.n)],a.megabuf[Math.floor(a.n+1)]=a.gmegabuf[Math.floor(a.n+\n1)],a.megabuf[Math.floor(a.n+2)]=a.gmegabuf[Math.floor(a.n+2)],.00001a.max_age?1:0)?.00001=10*a.dt*bnot(a.high)?1:0,200>a["new"]?1:0))?(--a.free,a["new"]+=1,a.tht=div(randint(100),500)*(1+1.5*a.high),a.phi=randint(12),a.v0=a.v00*(1+div(randint(10),40)),a.gmegabuf[Math.floor(a.n)]=1.7*a.ran1,a.gmegabuf[Math.floor(a.n+1)]=a.y0+2.2*a.high,a.gmegabuf[Math.floor(a.n+2)]=2,a.gmegabuf[Math.floor(a.n+3)]=a.v0*Math.sin(a.tht)*Math.cos(a.phi),a.gmegabuf[Math.floor(a.n+\n4)]=a.v0*Math.cos(4*a.tht)*(1-1.5*a.high),a.gmegabuf[Math.floor(a.n+5)]=a.v0*Math.sin(a.tht)*Math.sin(a.phi)*1.5*a.vol,a.gmegabuf[Math.floor(a.n+7)]=0,a.gmegabuf[Math.floor(a.n+8)]=div(randint(100),100)):0:(--a.free,a.gmegabuf[Math.floor(a.n)]+=a.gmegabuf[Math.floor(a.n+3)]*a.dt,a.gmegabuf[Math.floor(a.n+1)]+=a.gmegabuf[Math.floor(a.n+4)]*a.dt,a.gmegabuf[Math.floor(a.n+2)]+=a.gmegabuf[Math.floor(a.n+5)]*a.dt,a.gmegabuf[Math.floor(a.n+3)]*=1-a.air,a.gmegabuf[Math.floor(a.n+4)]*=1-a.air,a.gmegabuf[Math.floor(a.n+\n4)]-=.8*a.dt,a.gmegabuf[Math.floor(a.n+5)]*=1-a.air,a.gmegabuf[Math.floor(a.n+7)]=(a.gmegabuf[Math.floor(a.n+1)]>a.yobf?1:0)*Math.min(1,18*(a.gmegabuf[Math.floor(a.n+1)]-a.yobf)),.00001a.gmegabuf[Math.floor(a.n+4)]?1:0))?a.gmegabuf[8]=a.max_age:0,a.gmegabuf[Math.floor(a.n+8)]+=a.dt),a.n+=12;for(b=a.n=0;512>b;b++)a.m=6132+a.n,a.gmegabuf[Math.floor(a.m)]=div(a.gmegabuf[Math.floor(a.n)]+a.megabuf[Math.floor(a.n)],2),a.gmegabuf[Math.floor(a.m+\n1)]=div(a.gmegabuf[Math.floor(a.n+1)]+a.megabuf[Math.floor(a.n+1)],2),a.gmegabuf[Math.floor(a.m+2)]=div(a.gmegabuf[Math.floor(a.n+2)]+a.megabuf[Math.floor(a.n+2)],2),a.gmegabuf[Math.floor(a.m+7)]=a.gmegabuf[Math.floor(a.n+7)],a.gmegabuf[Math.floor(a.m+8)]=a.gmegabuf[Math.floor(a.n+8)],a.n+=12;a.dec=.00001a.bass1?1:0)?.5:.9;a.bass1=a.bass1*a.dec+a.bass*(1-a.dec);a.q1=Math.min(1,Math.max(0,a.bass1-1.5)*Math.abs(a.q3-.5)*3);a.q10=Math.max(a.vol_-.1,.1);a.vol_alt=a.vol;a.q32=a.aspecty;\na.new1=.00001 0.5))))\n , 0.0, 1.0)));\n vec3 tmpvar_21;\n tmpvar_21.z = 0.0;\n tmpvar_21.xy = (((texture (sampler_blur3, uv_2).xyz * scale3) + bias3).xy * vec2(3.0, 5.0));\n ret_3 = (ret_3 + ((xlat_mutablesmoke * \n dot (tmpvar_21, vec3(0.32, 0.49, 0.29))\n ) * vec3(1.0, 0.84, 0.62)));\n float tmpvar_22;\n tmpvar_22 = clamp (((1.2 * \n clamp (texture (sampler_main, uv_2).y, 0.0, 1.0)\n ) - 0.2), 0.0, 1.0);\n vec3 tmpvar_23;\n tmpvar_23.x = tmpvar_22;\n tmpvar_23.y = (tmpvar_22 * tmpvar_22);\n tmpvar_23.z = pow (tmpvar_22, 8.0);\n vec3 tmpvar_24;\n tmpvar_24 = clamp ((tmpvar_23 / vec3(0.8, 0.8, 0.8)), 0.0, 1.0);\n ret_3 = (ret_3 + (tmpvar_24 * (tmpvar_24 * \n (3.0 - (2.0 * tmpvar_24))\n )));\n float tmpvar_25;\n tmpvar_25 = clamp (0.52, 0.0, 1.0);\n vec3 tmpvar_26;\n tmpvar_26.x = tmpvar_25;\n tmpvar_26.y = (tmpvar_25 * tmpvar_25);\n tmpvar_26.z = pow (tmpvar_25, 8.0);\n vec3 tmpvar_27;\n tmpvar_27 = clamp ((tmpvar_26 / vec3(0.8, 0.8, 0.8)), 0.0, 1.0);\n vec3 tmpvar_28;\n tmpvar_28 = mix (clamp (ret_3, 0.0, 1.0), (tmpvar_27 * (tmpvar_27 * \n (3.0 - (2.0 * tmpvar_27))\n )), vec3((pow (\n ((1.0 - uv_2.y) - ((uv_2.x - 0.5) * (q3 - 0.5)))\n , 4.0) * q1)));\n ret_3 = tmpvar_28;\n vec4 tmpvar_29;\n tmpvar_29.w = 1.0;\n tmpvar_29.xyz = tmpvar_28;\n ret = tmpvar_29.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.698, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0, + ob_g: 0.1, + ob_b: 1, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + mv_x: 25.6, + mv_y: 9.6, + mv_l: 5, + mv_g: 0.5, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.n=0;a.maxbpm=0;a.reg26=0;a.maxind1=0;a.uvx0=0;a.cosb_=0;a.reg34=0;a.num_res=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.sinb_=0;a.index=0;a.quali=0;a.v3=0;a.q18=0;a.q22=0;a.q21=0;a.diry=0;a.q6=0;a.posx=0;a.dt=0;a.reg25=0;a.mean=0;a.uvx=0;a.q1=0;a.posz=0;a.q5=0;a.reg52=0;a.dt1=0;a.dec_f=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.bt2=0;a.reg36=0;a.minbpm=0;a.reg22=0;a.uvy=0;a.rotz=0;a.cosb=0;a.omega=0;a.dist_=0;a.ec_steps=0;a.bpm=0;a.q23=0;a.q24=0;a.reg24=\n0;a.ran2=0;a.pi=0;a.q10=0;a.reg14=0;a.sinb=0;a.reg53=0;a.posy=0;a.reg31=0;a.dirx=0;a.dec_m=0;a.q4=0;a.start=0;a.reg12=0;a.reg13=0;a.v2p=0;a.c2=0;a.reg37=0;a.ex=0;a.s3=0;a.yslope=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.v3p=0;a.reg35=0;a.p2=0;a.mov=0;a.reg11=0;a.tx=0;a.avg=0;a.bt1=0;a.beatsin=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.q17=0;a.vol=0;a.reg32=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.beatcos=0;a.reg30=0;a.q2=0;a.b1y=0;a.q27=0;a.bri=0;a.slen=0;a.q14=0;a.dist=0;a.trel1=0;a.p3=0;a.reg17=\n0;a.v1=0;a.speed=0;a.vol2=0;a.q3=0;a.s1=0;a.vol_=0;a.dec=0;a.s2=0;a.quad=0;a.b2y=0;a.ran1=0;a.q32=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.ty=0;a.excite=0;a.c1=0;a.v2=0;a.q20=0;a.p4=0;a.q8=0;a.maxvol=0;for(var b=a.n=0;2E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;a.minbpm=30;a.maxbpm=230;a.num_res=100;for(b=a.index=0;bc;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:\n.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30d);d=.06>a.dist?1:0}while(.00001b);', + frame_eqs_str: + 'a.dt=Math.min(div(1,a.fps),.1);a.dec_f=.8;a.dec_m=1-4*a.dt;a.dec_s=1-a.dt;a.vol=div(a.bass+div(a.mid,2)+a.treb,3);a.vol_=a.vol_*a.dec_m+(1-a.dec_m)*a.vol;a.dec=a.dec_s;a.vol2=a.vol2*a.dec+(1-a.dec)*Math.min(3,a.vol);a.maxvol=.00001a.maxvol?1:0)?a.vol:a.maxvol*a.dec_s;a.excite=a.vol-a.vol_;a.index=0;a.maxind1=0;for(var b=a.mean=0;ba.gmegabuf[Math.floor(12*a.maxind1+3)]?1:0)?a.maxind1=a.index:0;a.index+=1}a.quali=div(a.gmegabuf[Math.floor(12*a.maxind1+3)],a.mean);a.bpm=a.minbpm*pow(div(a.maxbpm,a.minbpm),div(a.maxind1,a.num_res));.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=\n-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+\na.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var d;c=0;do{c+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*\na.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=1+2*(div(a.uvx,4)+30.5-Math.floor(div(a.uvx,4)+30.5)-.5);a.uvy=2+2*(div(a.uvy,4)+30.5-Math.floor(div(a.uvy,4)+30.5)-.5);a.uvz=3+2*(div(a.uvz,4)+30.5-Math.floor(div(a.uvz,4)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(d=0;8>d;d++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?\n1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*\na.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;d=(.6>a.dist?1:0)*(30c);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(8*(a.megabuf[1]-a.megabuf[3]),-2),2);a.yslope=Math.min(Math.max(8*(a.megabuf[4]-a.megabuf[2]),-2),2);a.dist_=a.dist_*a.dec_m+(1-a.dec_m)*a.dist;\na.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+div(1,255)+0*a.start;a.start*=.9;a.reg52=-a.v2;a.reg53=a.v3;a.warp=0;a.zoom=1;a.rot=a.v1;a.sinb=Math.sin(a.trel1);a.cosb=Math.cos(a.trel1);a.bt1=0>a.sinb*a.sinb_?1:0;a.bt2=0>a.cosb*a.cosb_?1:0;.00001 0.16)) {\n vec4 nb2_8;\n vec4 nb_9;\n vec4 tmpvar_10;\n tmpvar_10 = texture (sampler_pw_main, (uv_3 + vec2(-(pix))));\n nb_9.x = (1.0 - (tmpvar_10.z + (0.003921569 * tmpvar_10.y)));\n vec4 tmpvar_11;\n tmpvar_11 = texture (sampler_pw_main, (uv_3 + (pix * vec2(1.0, -1.0))));\n nb_9.y = (1.0 - (tmpvar_11.z + (0.003921569 * tmpvar_11.y)));\n vec4 tmpvar_12;\n tmpvar_12 = texture (sampler_pw_main, (uv_3 + vec2(pix)));\n nb_9.z = (1.0 - (tmpvar_12.z + (0.003921569 * tmpvar_12.y)));\n vec4 tmpvar_13;\n tmpvar_13 = texture (sampler_pw_main, (uv_3 + (pix * vec2(-1.0, 1.0))));\n nb_9.w = (1.0 - (tmpvar_13.z + (0.003921569 * tmpvar_13.y)));\n vec4 tmpvar_14;\n tmpvar_14 = texture (sampler_pw_main, (uv_3 + (pix * vec2(0.0, -1.0))));\n nb2_8.x = (1.0 - (tmpvar_14.z + (0.003921569 * tmpvar_14.y)));\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pw_main, (uv_3 + (pix * vec2(1.0, 0.0))));\n nb2_8.y = (1.0 - (tmpvar_15.z + (0.003921569 * tmpvar_15.y)));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pw_main, (uv_3 + (pix * vec2(0.0, 1.0))));\n nb2_8.z = (1.0 - (tmpvar_16.z + (0.003921569 * tmpvar_16.y)));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pw_main, (uv_3 + (pix * vec2(-1.0, 0.0))));\n nb2_8.w = (1.0 - (tmpvar_17.z + (0.003921569 * tmpvar_17.y)));\n vec4 tmpvar_18;\n tmpvar_18 = min (nb_9, nb2_8);\n nb_9.zw = tmpvar_18.zw;\n nb_9.xy = min (tmpvar_18.xy, tmpvar_18.zw);\n xlat_mutabledist = ((min (nb_9.x, nb_9.y) + (\n (0.006 * (tmpvar_7.xyz - 0.5).x)\n * tmpvar_7.y)) - (q10 * 0.5));\n };\n float theta_19;\n theta_19 = (xlat_mutabledist * 1.35);\n float theta_20;\n theta_20 = (xlat_mutabledist * 1.35);\n vec3 tmpvar_21;\n tmpvar_21.xy = (xlat_mutableuv1 * ((\n sin(theta_19)\n / \n cos(theta_19)\n ) / 1.35));\n tmpvar_21.z = ((sin(theta_20) / cos(theta_20)) / 1.35);\n xlat_mutableuv2 = (((tmpvar_21 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = (((\n fract(((xlat_mutableuv2 / 4.0) + 0.5))\n - 0.5) * 2.0) + vec3(1.0, 2.0, 3.0));\n vec3 zz0_23;\n vec3 zz_24;\n zz_24 = xlat_mutableuv2;\n zz0_23 = (xlat_mutableuv2 + q8);\n for (int n_22 = 0; n_22 <= 8; n_22++) {\n zz_24 = ((2.0 * clamp (zz_24, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_24);\n zz_24 = (zz_24 * max ((1.0/(\n dot (zz_24, zz_24)\n )), 1.0));\n zz_24 = ((2.6 * zz_24) + zz0_23);\n };\n vec4 tmpvar_25;\n tmpvar_25.w = 0.0;\n tmpvar_25.xyz = zz_24;\n float tmpvar_26;\n tmpvar_26 = sqrt(dot (zz_24, zz_24));\n vec4 tmpvar_27;\n tmpvar_27.w = 0.0;\n tmpvar_27.xyz = mod1;\n xlat_mutablestruc = ((1.0 - (\n (1.4 * dot (tmpvar_25, tmpvar_27))\n / 40.0)) - (xlat_mutabledist * 0.3));\n if (((tmpvar_26 < 40.0) && (xlat_mutabledist > (0.04 * \n (1.0 - rad)\n )))) {\n ret_4.x = mix (xlat_mutablestruc, texture (sampler_main, uv_3).x, sustain);\n float x_28;\n x_28 = ((1.0 - xlat_mutabledist) * 255.0);\n float ip_29;\n ip_29 = float(int(x_28));\n vec2 tmpvar_30;\n tmpvar_30.x = (x_28 - ip_29);\n tmpvar_30.y = (ip_29 / 255.0);\n ret_4.yz = tmpvar_30;\n } else {\n ret_4 = ((texture (sampler_fc_main, uv_3) * sustain) - 0.003921569).xyz;\n };\n vec4 tmpvar_31;\n tmpvar_31.w = 1.0;\n tmpvar_31.xyz = ret_4;\n ret = tmpvar_31.xyz;\n }', + comp: 'float xlat_mutablecross1;\nvec2 xlat_mutabledz1;\nfloat xlat_mutablerdist;\nvec2 xlat_mutableuv0;\nvec2 xlat_mutableuv4;\nvec2 xlat_mutableuva;\nvec2 xlat_mutableuvb;\n shader_body { \n vec2 tmpvar_1;\n tmpvar_1.x = q1;\n tmpvar_1.y = q2;\n vec2 tmpvar_2;\n tmpvar_2.x = q17;\n tmpvar_2.y = q18;\n vec2 uv_3;\n vec3 ret_4;\n uv_3 = (uv + (texsize.zw / 2.0));\n xlat_mutableuv0 = uv_3;\n vec2 uvi_5;\n uvi_5 = (uv_3 + vec2(0.002, 0.0));\n float tmpvar_6;\n tmpvar_6 = mix (((texture (sampler_blur1, uvi_5).xyz * scale1) + bias1).x, texture (sampler_main, uvi_5).x, 0.1);\n vec2 uvi_7;\n uvi_7 = (uv_3 - vec2(0.002, 0.0));\n float tmpvar_8;\n tmpvar_8 = mix (((texture (sampler_blur1, uvi_7).xyz * scale1) + bias1).x, texture (sampler_main, uvi_7).x, 0.1);\n xlat_mutabledz1.x = ((tmpvar_6 * float(\n (tmpvar_6 > 0.02)\n )) - (tmpvar_8 * float(\n (tmpvar_8 > 0.02)\n )));\n vec2 uvi_9;\n uvi_9 = (uv_3 + vec2(0.0, 0.002));\n float tmpvar_10;\n tmpvar_10 = mix (((texture (sampler_blur1, uvi_9).xyz * scale1) + bias1).x, texture (sampler_main, uvi_9).x, 0.1);\n vec2 uvi_11;\n uvi_11 = (uv_3 - vec2(0.0, 0.002));\n float tmpvar_12;\n tmpvar_12 = mix (((texture (sampler_blur1, uvi_11).xyz * scale1) + bias1).x, texture (sampler_main, uvi_11).x, 0.1);\n xlat_mutabledz1.y = ((tmpvar_10 * float(\n (tmpvar_10 > 0.02)\n )) - (tmpvar_12 * float(\n (tmpvar_12 > 0.02)\n )));\n uv_3 = (uv_3 + (xlat_mutabledz1 * 0.26));\n xlat_mutablerdist = ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1).z;\n vec4 tmpvar_13;\n tmpvar_13.w = 0.0;\n tmpvar_13.xyz = texture (sampler_noise_hq, vec2(((xlat_mutablerdist * 0.05) + (time * 0.02)))).xyz;\n vec4 tmpvar_14;\n tmpvar_14 = mix (tmpvar_13, roam_sin, vec4(0.5, 0.5, 0.5, 0.5));\n xlat_mutableuv4 = (uv_3 - 0.4);\n xlat_mutableuva = ((xlat_mutableuv4 - tmpvar_1) - ((\n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n .x * 0.4) * float(\n (xlat_mutablerdist > 0.2)\n )));\n xlat_mutableuvb = ((xlat_mutableuv4 - tmpvar_2) - ((\n (texture (sampler_blur1, uv_3).xyz * scale1)\n + bias1).x * 0.4));\n float angle_15;\n float tmpvar_16;\n tmpvar_16 = abs(xlat_mutableuva.x);\n if ((xlat_mutableuva.y >= 0.0)) {\n angle_15 = (1.0 - ((xlat_mutableuva.y - tmpvar_16) / (xlat_mutableuva.y + tmpvar_16)));\n } else {\n angle_15 = (3.0 - ((xlat_mutableuva.y + tmpvar_16) / (tmpvar_16 - xlat_mutableuva.y)));\n };\n float tmpvar_17;\n if ((xlat_mutableuva.x < 0.0)) {\n tmpvar_17 = -(angle_15);\n } else {\n tmpvar_17 = angle_15;\n };\n xlat_mutablecross1 = ((pow (\n sin((3.141593 * (tmpvar_17 + (5.1 * q20))))\n , 1.5) + (xlat_mutablerdist / 2.0)) + 0.1);\n vec3 tmpvar_18;\n tmpvar_18 = vec3((((1.0/(\n dot (xlat_mutableuva, xlat_mutableuva)\n )) / xlat_mutablecross1) * q3));\n vec3 tmpvar_19;\n tmpvar_19 = vec3(((1.0/(dot (xlat_mutableuvb, xlat_mutableuvb))) * q19));\n ret_4 = (clamp ((1.0 - \n (2.0 * xlat_mutablerdist)\n ), 0.0, 1.0) * ((\n (tmpvar_18 * tmpvar_14.xyz)\n + \n (tmpvar_19 * (1.0 - tmpvar_14.xyz))\n ) + 0.1));\n ret_4 = (ret_4 + (clamp (\n (2.0 * xlat_mutablerdist)\n , 0.0, 1.0) * (\n (tmpvar_18 * tmpvar_14.zyx)\n + \n (tmpvar_19 * (1.0 - tmpvar_14.zyx))\n )));\n ret_4 = (ret_4 + ((\n (texture (sampler_blur1, xlat_mutableuv0).xyz * scale1)\n + bias1).x * 0.05));\n ret_4 = (1.0 - exp(-(ret_4)));\n vec4 tmpvar_20;\n tmpvar_20.w = 1.0;\n tmpvar_20.xyz = ret_4;\n ret = tmpvar_20.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 2, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 5, + wave_dots: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 1.169162, + wave_smoothing: 0, + wave_mystery: 0.08, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0.99, + ob_size: 0.015, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 0, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b2x: 0.3, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 53, + rad: 0.05408, + tex_ang: 1.00531, + tex_zoom: 1.531168, + r: 0.2, + g: 0.7, + g2: 0, + a2: 1, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.q24=0;a.rad0=0;', + frame_eqs_str: + 'a.x=.5;a.y=.5;a.a=a.q24;a.a2=0;a.a=0;a.rad0=bnot(a.q24)*a.rad0+div(randint(10),50)*a.q24;a.rad=a.rad0;a.b=0;a.r=div(randint(10),10);a.g=1;a.a2=a.q24;', + }, + { + baseVals: { + enabled: 1, + sides: 44, + textured: 1, + x: 0.7, + rad: 0.2173, + tex_zoom: 3.277448, + g: 1, + b: 0.5, + r2: 1, + b2: 1, + a2: 1, + border_r: 0.5, + border_g: 0.5, + border_b: 0, + }, + init_eqs_str: 'a.rot0=0;a.q1=0;a.posx=0;a.q24=0;a.posy=0;a.rad0=0;', + frame_eqs_str: + 'a.textured=1;a.rot0+=div(1,a.fps)*a.q1;a.posx=(1-a.q24)*a.posx+a.q24*(.3+div(randint(100),200));a.posy=(1-a.q24)*a.posy+a.q24*(.3+div(randint(100),200));a.rad0=(1-a.q24)*a.rad0+a.q24*(.05+div(randint(100),300));a.rad=a.rad0;a.x=a.posx;a.y=a.posy;a.ang=a.rot0;', + }, + { + baseVals: { + enabled: 1, + sides: 63, + x: 0.503, + rad: 0.038857, + tex_zoom: 2.2233, + g: 0.1, + r2: 1, + b2: 1, + a2: 0.7, + border_a: 0, + }, + init_eqs_str: 'a.rot0=0;a.q2=0;a.posx=0;a.q24=0;a.posy=0;a.rad0=0;a.q26=0;', + frame_eqs_str: + 'a.textured=1;a.rot0+=div(.1,a.fps)*a.q2;a.posx=(1-a.q24)*a.posx+a.q24*(.3+div(randint(100),200));a.posy=(1-a.q24)*a.posy+a.q24*(.3+div(randint(100),200));a.rad0=(1-a.q24)*a.rad0+a.q24*(.05+div(randint(100),400));a.rad=a.rad0;a.x=a.posx+a.q26;a.y=a.posy;a.ang=a.rot0;', + }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.q25=0;a.index=0;a.q22=0;a.q21=0;a.q29=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.t_rel=0;a.dec_slow=0;a.q10=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q7=0;a.ds=0;a.q28=0;a.q30=0;a.q20=0;a.p4=0;a.q8=0;', + frame_eqs_str: + 'a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.beat=a.bass+a.mid+a.treb;a.beat*=a.beat;a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2*a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;\na.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att+3;a.q27=a.index+1;a.q28=a.index2;a.q29=a.index2;a.monitor=a.q29;a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.q5=Math.cos(div(a.time,17));a.q6=Math.sin(div(a.time,17));a.q7=-a.q2;a.q8=a.q1;a.ds=a.ds*a.dec_med+a.q24*(1-a.dec_med);a.q25=a.q24;a.q10=a.q22+3;a.t_rel=8*a.time;a.p3=\na.p3*a.dec_med+(1-a.dec_med)*(100*a.index+0*a.q26);a.q30=a.p3;a.p4=a.dec_med*a.p4+(1-a.dec_med)*a.q27;a.q31=a.p4;a.zoom=1.1+.2*a.q1;a.warp=0;a.ob_size=.01;a.ob_r=.9;a.ob_g=1;a.ob_b=0;a.ob_a=.2*Math.sin(div(a.time,7));', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec2 uv_1;\n vec2 tmpvar_2;\n tmpvar_2 = ((uv - 0.5) * aspect.xy);\n float tmpvar_3;\n tmpvar_3 = (sqrt(dot (tmpvar_2, tmpvar_2)) + (rand_frame * 13.0)).x;\n uv_1 = (uv + (clamp (\n ((sin(tmpvar_3) / cos(tmpvar_3)) / normalize(tmpvar_2))\n , vec2(-2.0, -2.0), vec2(2.0, 2.0)) / 16.0));\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = ((q24 * (\n ((texture (sampler_main, uv_1).xyz + ((0.1 * vec3(\n ((q1 * cos((uv_1.x * 44.0))) - cos((uv_1.y * 82.0)))\n )) * (1.0 + texture (sampler_noise_lq, \n ((uv_1 / 16.0) + (time / 100.0))\n )).xyz)) * 0.98)\n - 0.025)) + ((1.0 - q24) * texture (sampler_main, uv_orig).xyz));\n ret = tmpvar_4.xyz;\n }', + comp: 'vec2 xlat_mutabledz;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\n shader_body { \n vec2 uv2_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n xlat_mutabledz.x = dot ((texture (sampler_main, (uv + tmpvar_2)).xyz - texture (sampler_main, (uv - tmpvar_2)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledz.y = dot ((texture (sampler_main, (uv + tmpvar_3)).xyz - texture (sampler_main, (uv - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n uv2_1 = (uv - 0.5);\n vec2 tmpvar_4;\n tmpvar_4.y = 0.0;\n float tmpvar_5;\n tmpvar_5 = (time / 8.0);\n tmpvar_4.x = tmpvar_5;\n float tmpvar_6;\n tmpvar_6 = (q27 * 2.0);\n xlat_mutableuv3 = (((tmpvar_6 * uv2_1) * 0.1) + tmpvar_4);\n xlat_mutableuv3 = (fract(xlat_mutableuv3) * aspect.yx);\n xlat_mutableuv3 = ((0.1 * cos(\n (22.0 * xlat_mutableuv3)\n )) + (18.0 * xlat_mutabledz));\n float tmpvar_7;\n tmpvar_7 = clamp ((0.02 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n vec4 tmpvar_8;\n tmpvar_8 = (1.0 + roam_cos);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_7)) + ((0.45 * \n dot (vec3(tmpvar_7), vec3(0.32, 0.49, 0.29))\n ) * tmpvar_8).xyz);\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * 1.252262));\n vec2 tmpvar_9;\n tmpvar_9.y = 0.0;\n tmpvar_9.x = tmpvar_5;\n xlat_mutableuv3 = (((tmpvar_6 * uv2_1) * 0.1) + tmpvar_9);\n xlat_mutableuv3 = (fract(xlat_mutableuv3) * aspect.yx);\n xlat_mutableuv3 = ((0.1 * cos(\n (22.0 * xlat_mutableuv3)\n )) + (18.0 * xlat_mutabledz));\n float tmpvar_10;\n tmpvar_10 = clamp ((0.02 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_10)) + ((0.45 * \n dot (vec3(tmpvar_10), vec3(0.32, 0.49, 0.29))\n ) * tmpvar_8).xyz);\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * 1.252262));\n vec4 tmpvar_11;\n tmpvar_11.w = 1.0;\n tmpvar_11.xyz = (xlat_mutableret1 + clamp ((\n (texture (sampler_main, uv).xyz * 4.0)\n * \n (0.2 + xlat_mutableret1)\n ), 0.0, 1.0));\n ret = tmpvar_11.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 6, + wave_thick: 1, + modwavealphabyvolume: 1, + darken: 1, + wave_a: 0.001, + wave_scale: 0.159809, + wave_smoothing: 0.45, + wave_mystery: 0.08, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + wave_y: 0.9, + ob_r: 1, + ob_g: 1, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b1x: 0.6999, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q7=0;a.q20=0;', + frame_eqs_str: + 'a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=\na.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_slow*a.p2+(1-a.dec_slow)*a.p1;a.rott=div(3.1416*a.p2,4);a.q27=a.index+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1;a.rot=-0*a.index;a.q32=pow(.996,div(30,a.fps));a.q5=div(Math.sin(div(a.time,11))+1,5);a.movez+=div(.06,a.fps)*(1.1+a.q1);a.q6=a.movez;a.q7=.005*Math.sin(div(a.time,15));', + pixel_eqs_str: '', + pixel_eqs: '', + warp: 'vec3 xlat_mutablenoise;\nvec2 xlat_mutablers;\nvec2 xlat_mutablers0;\nvec2 xlat_mutableuv1;\n shader_body { \n vec3 copy_1;\n vec2 tmpvar_2;\n tmpvar_2.x = 0.5;\n tmpvar_2.y = q5;\n xlat_mutableuv1 = (uv - tmpvar_2);\n float tmpvar_3;\n tmpvar_3 = (1.0/(xlat_mutableuv1.y));\n xlat_mutablers0.x = (xlat_mutableuv1.x * tmpvar_3);\n xlat_mutablers0.y = tmpvar_3;\n xlat_mutablers.x = xlat_mutablers0.x;\n xlat_mutablers.y = (tmpvar_3 + (time * 0.3));\n xlat_mutablenoise = (vec3(dot (texture (sampler_pw_noise_lq, (xlat_mutablers / 63.0)), vec4(0.32, 0.49, 0.29, 0.0))) * (dot (texture (sampler_pw_noise_lq, \n (xlat_mutablers / 12.0)\n ), vec4(0.32, 0.49, 0.29, 0.0)) + 0.5));\n xlat_mutablenoise = (xlat_mutablenoise * (clamp (\n ((10.0 * xlat_mutablenoise) - 8.0)\n , 0.0, 1.0) * clamp (\n (2.0 / tmpvar_3)\n , 0.0, 1.0)));\n vec2 tmpvar_4;\n tmpvar_4.x = uv.x;\n tmpvar_4.y = (uv.y - (0.024 / tmpvar_3));\n vec2 tmpvar_5;\n tmpvar_5.x = uv.x;\n tmpvar_5.y = (uv.y - (0.012 / tmpvar_3));\n copy_1 = (texture (sampler_main, tmpvar_4).xyz + texture (sampler_main, tmpvar_5).xyz);\n vec2 tmpvar_6;\n tmpvar_6.x = uv.x;\n tmpvar_6.y = (uv.y - (0.006 / tmpvar_3));\n copy_1 = (copy_1 + texture (sampler_main, tmpvar_6).xyz);\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = ((xlat_mutablenoise + (\n (((copy_1 / 3.0) * (1.0 + slow_roam_cos).xyz) / 2.0)\n * 0.99)) - 0.005);\n ret = tmpvar_7.xyz;\n }', + comp: 'vec3 xlat_mutablecont;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers2;\n shader_body { \n vec2 uv_1;\n float inten_2;\n float dist_3;\n uv_1 = (uv - 0.5);\n uv_1 = (uv_1 * aspect.xy);\n dist_3 = (1.0 - fract(q6));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_4;\n tmpvar_4 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_4).xyz;\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (vec3(0.0, 0.0, 0.0), ((\n -(texture (sampler_main, tmpvar_4).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_4 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n dist_3 = (1.0 - fract((0.5 + q6)));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_5;\n tmpvar_5 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_5).xyz;\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (xlat_mutablecont, ((\n -(texture (sampler_main, tmpvar_5).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_5 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n dist_3 = (1.0 - fract((1.0 + q6)));\n inten_2 = ((dist_3 * (1.0 - dist_3)) * 6.0);\n vec2 tmpvar_6;\n tmpvar_6 = fract(((uv_1 * dist_3) + 0.55));\n xlat_mutableneu = texture (sampler_main, tmpvar_6).xyz;\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * inten_2));\n xlat_mutablecont = max (xlat_mutablecont, ((\n -(texture (sampler_main, tmpvar_6).xyz)\n + \n ((texture (sampler_blur1, (tmpvar_6 + q7)).xyz * scale1) + bias1)\n ) * inten_2));\n vec2 tmpvar_7;\n tmpvar_7.y = 5.0;\n tmpvar_7.x = (time / 12.0);\n xlat_mutablers2 = ((0.1 * cos(\n ((uv_1 * 3.0) + tmpvar_7)\n )) + (0.1 * xlat_mutableret1).xy);\n vec4 tmpvar_8;\n tmpvar_8.w = 1.0;\n tmpvar_8.xyz = (((-0.1 * xlat_mutableret1) + (\n (clamp ((0.005 / sqrt(\n dot (xlat_mutablers2, xlat_mutablers2)\n )), 0.0, 1.0) * vec3(18.0, 16.2, 10.8))\n * \n (0.2 + (0.3 * xlat_mutableret1))\n )) + ((\n dot (xlat_mutablecont, vec3(0.32, 0.49, 0.29))\n * \n (1.0 + slow_roam_cos)\n ) / 2.0).xyz);\n ret = tmpvar_8.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 6, + wave_dots: 1, + modwavealphabyvolume: 1, + darken: 1, + wave_a: 0.001, + wave_scale: 1.740724, + wave_smoothing: 0.45, + wave_mystery: 0.08, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_g: 0.99, + ob_size: 0, + ob_r: 1, + ob_b: 1, + ob_a: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.q6=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.t_rel=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.p3=0;a.q3=0;a.t0=0;a.q7=0;a.q28=0;a.q30=0;a.q20=0;a.q8=0;a.p3=0;a.t_rel=0;', + frame_eqs_str: + 'a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),4);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.monitor=a.index4;\na.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass_att+a.mid_att+a.treb_att+1;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.p3=a.dec_med*a.p3+(1-a.dec_med)*a.p2;a.rott=div(3.14159265359*a.p3,2);a.q27=8-a.index;a.q28=a.index2+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.t_rel+=div(.6,a.fps)*a.q1*a.q1;a.q5=Math.cos(a.t_rel);a.q6=Math.sin(a.t_rel);a.q7=-a.q6;a.q8=a.q5;a.movez+=div(div(.6,\na.fps),(1.4-a.q5)*(1.4-a.q5));a.q30=a.movez;a.zoom=1;', + pixel_eqs_str: 'a.dx=div(0*a.q28,8);', + warp: 'vec3 xlat_mutablenoise;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers;\n shader_body { \n float z_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)] = _qb.xy;\n tmpvar_2[1u] = _qb.zw;\n vec2 tmpvar_3;\n tmpvar_3 = ((uv * tmpvar_2) - 0.5);\n float tmpvar_4;\n tmpvar_4 = (0.4 / abs(tmpvar_3.y));\n xlat_mutablers.x = (tmpvar_3.x * tmpvar_4);\n xlat_mutablers.y = (tmpvar_4 + q30);\n vec4 tmpvar_5;\n tmpvar_5 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_5.xyz * vec3(greaterThanEqual (tmpvar_5.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutablenoise = (xlat_mutablenoise * (1.0 + (0.5 * \n (dot (texture (sampler_noise_hq, (16.0 * xlat_mutablers)), vec4(0.32, 0.49, 0.29, 0.0)) - 0.5)\n )));\n xlat_mutableret1 = xlat_mutablenoise;\n z_1 = (1.2 / abs(tmpvar_3.y));\n xlat_mutablers.x = (tmpvar_3.x * z_1);\n xlat_mutablers.y = (z_1 + q30);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_6.xyz * vec3(greaterThanEqual (tmpvar_6.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n z_1 = (0.4 / abs(tmpvar_3.x));\n xlat_mutablers.y = (tmpvar_3.y * z_1);\n xlat_mutablers.x = (z_1 + q30);\n vec4 tmpvar_7;\n tmpvar_7 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_7.xyz * vec3(greaterThanEqual (tmpvar_7.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutablenoise = (xlat_mutablenoise * (1.0 + (0.5 * \n (dot (texture (sampler_noise_hq, (16.0 * xlat_mutablers)), vec4(0.32, 0.49, 0.29, 0.0)) - 0.5)\n )));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n z_1 = (1.2 / abs(tmpvar_3.x));\n xlat_mutablers.y = (tmpvar_3.y * z_1);\n xlat_mutablers.x = (z_1 + q30);\n vec4 tmpvar_8;\n tmpvar_8 = texture (sampler_pw_noise_lq, (xlat_mutablers / 32.0));\n xlat_mutablenoise = (tmpvar_8.xyz * vec3(greaterThanEqual (tmpvar_8.xyz, vec3(0.9, 0.9, 0.9))));\n xlat_mutableret1 = (xlat_mutableret1 + xlat_mutablenoise);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = xlat_mutableret1;\n ret = tmpvar_9.xyz;\n }', + comp: 'uniform sampler2D sampler_clouds2;\n shader_body { \n vec2 uv_1;\n vec2 uv1_2;\n uv_1 = (uv * aspect.xy);\n vec2 tmpvar_3;\n tmpvar_3.y = 0.0;\n tmpvar_3.x = texsize.z;\n vec2 tmpvar_4;\n tmpvar_4.x = 0.0;\n tmpvar_4.y = texsize.w;\n vec2 tmpvar_5;\n tmpvar_5.x = (dot (texture (sampler_main, (uv_1 - tmpvar_3)).xyz, vec3(0.32, 0.49, 0.29)) - dot (texture (sampler_main, (uv_1 + tmpvar_3)).xyz, vec3(0.32, 0.49, 0.29)));\n tmpvar_5.y = (dot (texture (sampler_main, (uv_1 - tmpvar_4)).xyz, vec3(0.32, 0.49, 0.29)) - dot (texture (sampler_main, (uv_1 + tmpvar_4)).xyz, vec3(0.32, 0.49, 0.29)));\n uv1_2 = ((0.3 * sin(\n ((uv_1 + (0.02 * time)) * 6.0)\n )) + (0.2 * tmpvar_5));\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_clouds2, (uv_orig + tmpvar_5));\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (((-2.0 * \n (0.1 * texture (sampler_main, uv_1))\n .xyz) + (\n clamp (((0.004 * q26) / sqrt(dot (uv1_2, uv1_2))), 0.0, 1.0)\n * vec3(1.0, 0.8, 0.4))) + (0.4 * (tmpvar_6.xyz + \n (dot (tmpvar_6.xyz, vec3(0.32, 0.49, 0.29)) - 0.7)\n )));\n ret = tmpvar_7.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.780001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 5, + wave_dots: 1, + wave_thick: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 5.552, + wave_smoothing: 0.504, + wave_mystery: -1, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_g: 0, + wave_b: 0, + ob_size: 0.06, + ob_r: 1, + ob_g: 1, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 0.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b1x: 0.6999, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { + baseVals: { + enabled: 1, + sides: 5, + additive: 1, + x: 0.9, + rad: 0.22613, + g: 0.6, + g2: 0, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: + 'a.x=.05+div(randint(900),1E3);a.y=.05+div(randint(900),1E3);a.ang=div(randint(320),100);', + }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.ready=0;a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.sp0=0;a.q29=0;a.q1=0;a.dec_med=0;a.q5=0;a.index3=0;a.rott=0;a.is_beat=0;a.q31=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.go=0;a.q4=0;a.is_beat2=0;a.q26=0;a.p2=0;a.avg=0;a.movez=0;a.q19=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q28=0;a.q30=0;a.q20=0;a.index4=randint(2);a.index3=randint(4);', + frame_eqs_str: + 'a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,4);a.index2=mod(a.index2+a.is_beat*bnot(a.index),4);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),4);a.index4=mod(a.index4+\na.is_beat*bnot(a.index)*bnot(a.index2)*bnot(a.index3),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.ready=a.is_beat*bnot(a.ready)+bnot(a.is_beat2)*a.ready;a.is_beat2=a.ready*above(a.time,a.t0+.2);a.q19=a.is_beat2;a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265359*a.p2,2);a.q27=a.index+1;a.q28=a.index2+1;a.q29=4*a.index3+1;a.q30=a.index4;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);\na.q3=-a.q2;a.q4=a.q1;a.sp0=a.dec_slow*a.sp0+(a.q24+.05)*(1-a.dec_slow);a.go=a.go*a.dec_med+(1-a.dec_med)*(1-bnot(a.index2+a.index3));a.movez+=div(.015*30,a.fps)*a.go;a.q31=a.movez;a.q32=.5+.02*Math.sin(div(a.time,5));a.q5=mod(a.index4,2);a.zoom=1;a.rot=0;a.dx=.05*Math.max(Math.sin(div(a.time,9.7))-.95,0);a.dy=.002*(1-a.go);a.rot=50*(a.dx-a.dy);', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec2 tmpvar_1;\n tmpvar_1 = ((uv * texsize.xy) * 0.03);\n vec2 tmpvar_2;\n tmpvar_2.x = (cos((tmpvar_1.y * q1)) * sin(-(tmpvar_1.y)));\n tmpvar_2.y = (sin(tmpvar_1.x) * cos((tmpvar_1.y * q2)));\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = ((texture (sampler_main, (uv - \n ((tmpvar_2 * texsize.zw) * 18.0)\n )).xyz * 0.99) - 0.01);\n ret = tmpvar_3.xyz;\n }', + comp: ' shader_body { \n vec2 uv1_1;\n vec3 tmpvar_2;\n tmpvar_2 = texture (sampler_main, uv).xyz;\n vec2 tmpvar_3;\n tmpvar_3.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_3.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_1 = ((0.3 * cos(\n ((uv - 0.5) + 1.8)\n )) - (2.0 * tmpvar_3));\n vec4 tmpvar_4;\n tmpvar_4.w = 1.0;\n tmpvar_4.xyz = (0.8 * ((0.3 * \n dot (tmpvar_2, vec3(0.32, 0.49, 0.29))\n ) + (\n (22.0 * clamp ((0.01 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0))\n * \n (tmpvar_2 + 0.1)\n )));\n ret = tmpvar_4.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 3, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + wrap: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.958, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0.05, + ob_g: 0.1, + ob_b: 1, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + mv_x: 25.6, + mv_y: 9.6, + mv_l: 0, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.look=0;a.n=0;a.reg26=0;a.uvx0=0;a.reg34=0;a.reg28=0;a.reg23=0;a.q25=0;a.angchg=0;a.reg20=0;a.reg15=0;a.reg10=0;a.q12=0;a.v3=0;a.q22=0;a.q21=0;a.diry=0;a.q13=0;a.q6=0;a.posx=0;a.fps_=0;a.reg25=0;a.uvx=0;a.q1=0;a.travel=0;a.posz=0;a.q5=0;a.dirz=0;a.dec_s=0;a.reg16=0;a.slow=0;a.reg36=0;a.reg22=0;a.uvy=0;a.rotz=0;a.ly=0;a.dist_=0;a.q23=0;a.q24=0;a.reg24=0;a.cran0=0;a.ran2=0;a.q11=0;a.q10=0;a.reg14=0;a.posy=0;a.reg31=0;a.dirx=0;a.q4=0;a.start=0;a.reg12=0;a.reg13=0;a.c2=0;a.reg37=\n0;a.s3=0;a.yslope=0;a.lampy=0;a.q16=0;a.xslope=0;a.q26=0;a.reg38=0;a.reg35=0;a.reg11=0;a.tx=0;a.avg=0;a.uvz=0;a.c3=0;a.uvy0=0;a.reg27=0;a.q19=0;a.beat=0;a.reg32=0;a.lx=0;a.reg21=0;a.uvz0=0;a.len=0;a.reg18=0;a.reg30=0;a.q2=0;a.q27=0;a.slen=0;a.q14=0;a.dist=0;a.reg17=0;a.v1=0;a.speed=0;a.s1=0;a.t0=0;a.s2=0;a.ran1=0;a.reg33=0;a.q7=0;a.ds=0;a.q28=0;a.lampx=0;a.ty=0;a.c1=0;a.v2=0;a.q20=0;a.q8=0;a.avg=.01;a.q7=.25;a.q8=randint(2)-1;a.q16=1+randint(2);a.q18=randint(.8)+.1;a.q30=1;a.q31=128;a.start=1;a.travel=\n0;a.rotz=0;a.look=0;a.slow=0;a.t0=a.time+3;a.lampx=.5;a.lampy=.5;a.cran0=randint(1);for(var b=a.n=0;1E4>b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30\nd);d=.06>a.dist?1:0}while(.00001b);', + frame_eqs_str: + 'a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg15=a.s3*\na.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*a.reg24+a.reg15*a.reg27;\na.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;\na.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?\n-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+2*(Math.abs(a.v1)+\nMath.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;', + pixel_eqs_str: + 'a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;', + warp: 'float sustain;\nfloat xlat_mutabledist;\nfloat xlat_mutablestruc;\nvec2 xlat_mutableuv1;\nvec3 xlat_mutableuv2;\n shader_body { \n mat3 tmpvar_1;\n tmpvar_1[uint(0)].x = q20;\n tmpvar_1[uint(0)].y = q23;\n tmpvar_1[uint(0)].z = q26;\n tmpvar_1[1u].x = q21;\n tmpvar_1[1u].y = q24;\n tmpvar_1[1u].z = q27;\n tmpvar_1[2u].x = q22;\n tmpvar_1[2u].y = q25;\n tmpvar_1[2u].z = q28;\n vec3 tmpvar_2;\n tmpvar_2.x = q4;\n tmpvar_2.y = q5;\n tmpvar_2.z = q6;\n sustain = (0.98 - q14);\n vec2 uv_3;\n vec3 ret_4;\n vec2 tmpvar_5;\n tmpvar_5 = (uv - 0.5);\n xlat_mutableuv1 = ((tmpvar_5 * aspect.xy) * q16);\n vec4 tmpvar_6;\n tmpvar_6 = texture (sampler_pc_main, uv);\n uv_3 = ((tmpvar_5 * (1.0 - \n (q10 / (1.0 - ((tmpvar_6.z + \n (0.003921569 * tmpvar_6.y)\n ) + (q10 * 0.7))))\n )) + 0.5);\n vec4 tmpvar_7;\n tmpvar_7 = fract((8.0 * texture (sampler_noise_lq, (uv_3 + rand_frame.yz))));\n xlat_mutabledist = tmpvar_7.x;\n if ((tmpvar_7.y > 0.2)) {\n vec3 tmpvar_8;\n tmpvar_8 = (tmpvar_7.xyz - vec3(0.4, 0.5, 0.5));\n vec2 uvi_9;\n uvi_9 = ((tmpvar_8.zy * 0.003) + uv_3);\n vec2 pix_10;\n vec4 nb2_11;\n vec4 nb_12;\n vec2 x_13;\n x_13 = (uvi_9 - 0.5);\n pix_10 = (texsize.zw * (1.0 + (\n sqrt(dot (x_13, x_13))\n * 8.0)));\n float tmpvar_14;\n tmpvar_14 = (q10 * 0.7);\n vec4 tmpvar_15;\n tmpvar_15 = texture (sampler_pc_main, (uvi_9 - pix_10));\n nb_12.x = (1.0 - ((tmpvar_15.z + \n (0.003921569 * tmpvar_15.y)\n ) + tmpvar_14));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, -1.0))));\n nb_12.y = (1.0 - ((tmpvar_16.z + \n (0.003921569 * tmpvar_16.y)\n ) + tmpvar_14));\n vec4 tmpvar_17;\n tmpvar_17 = texture (sampler_pc_main, (uvi_9 + pix_10));\n nb_12.z = (1.0 - ((tmpvar_17.z + \n (0.003921569 * tmpvar_17.y)\n ) + tmpvar_14));\n vec4 tmpvar_18;\n tmpvar_18 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 1.0))));\n nb_12.w = (1.0 - ((tmpvar_18.z + \n (0.003921569 * tmpvar_18.y)\n ) + tmpvar_14));\n vec4 tmpvar_19;\n tmpvar_19 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, -1.0))));\n nb2_11.x = (1.0 - ((tmpvar_19.z + \n (0.003921569 * tmpvar_19.y)\n ) + tmpvar_14));\n vec4 tmpvar_20;\n tmpvar_20 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(1.0, 0.0))));\n nb2_11.y = (1.0 - ((tmpvar_20.z + \n (0.003921569 * tmpvar_20.y)\n ) + tmpvar_14));\n vec4 tmpvar_21;\n tmpvar_21 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(0.0, 1.0))));\n nb2_11.z = (1.0 - ((tmpvar_21.z + \n (0.003921569 * tmpvar_21.y)\n ) + tmpvar_14));\n vec4 tmpvar_22;\n tmpvar_22 = texture (sampler_pc_main, (uvi_9 + (pix_10 * vec2(-1.0, 0.0))));\n nb2_11.w = (1.0 - ((tmpvar_22.z + \n (0.003921569 * tmpvar_22.y)\n ) + tmpvar_14));\n vec4 tmpvar_23;\n tmpvar_23 = min (nb_12, nb2_11);\n nb_12.zw = tmpvar_23.zw;\n nb_12.xy = min (tmpvar_23.xy, tmpvar_23.zw);\n xlat_mutabledist = (min (nb_12.x, nb_12.y) + ((0.008 * tmpvar_8.x) * abs(tmpvar_8.y)));\n };\n vec4 tmpvar_24;\n tmpvar_24 = texture (sampler_pc_main, uv_3);\n float tmpvar_25;\n tmpvar_25 = min (xlat_mutabledist, (1.0 - (\n (tmpvar_24.z + (0.003921569 * tmpvar_24.y))\n + \n (q10 * 0.7)\n )));\n xlat_mutabledist = tmpvar_25;\n float tmpvar_26;\n tmpvar_26 = (tmpvar_25 + pow (tmpvar_25, 3.0));\n vec3 tmpvar_27;\n tmpvar_27.xy = (xlat_mutableuv1 * tmpvar_26);\n tmpvar_27.z = tmpvar_26;\n xlat_mutableuv2 = (((tmpvar_27 / q7) * tmpvar_1) + tmpvar_2);\n xlat_mutableuv2 = ((fract(\n ((xlat_mutableuv2 / 8.0) + 0.5)\n ) - 0.5) * 8.0);\n float li_28;\n vec3 zz0_29;\n vec3 zz_30;\n zz0_29 = (xlat_mutableuv2 + q8);\n li_28 = 0.0;\n zz_30 = ((2.0 * clamp (xlat_mutableuv2, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - xlat_mutableuv2);\n float tmpvar_31;\n tmpvar_31 = dot (zz_30, zz_30);\n if ((tmpvar_31 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_31 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_31);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_32;\n tmpvar_32 = dot (zz_30, zz_30);\n if ((tmpvar_32 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_32 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_32);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_33;\n tmpvar_33 = dot (zz_30, zz_30);\n if ((tmpvar_33 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_33 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_33);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_34;\n tmpvar_34 = dot (zz_30, zz_30);\n if ((tmpvar_34 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_34 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_34);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_35;\n tmpvar_35 = dot (zz_30, zz_30);\n if ((tmpvar_35 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_35 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_35);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_36;\n tmpvar_36 = dot (zz_30, zz_30);\n if ((tmpvar_36 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_36 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_36);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_37;\n tmpvar_37 = dot (zz_30, zz_30);\n if ((tmpvar_37 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_37 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_37);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n zz_30 = ((2.0 * clamp (zz_30, vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0))) - zz_30);\n float tmpvar_38;\n tmpvar_38 = dot (zz_30, zz_30);\n if ((tmpvar_38 <= 0.25)) {\n zz_30 = (zz_30 * 4.0);\n li_28 = 24.0;\n } else {\n if ((tmpvar_38 <= 1.0)) {\n zz_30 = (zz_30 / tmpvar_38);\n };\n };\n zz_30 = ((2.6 * zz_30) + zz0_29);\n vec4 tmpvar_39;\n tmpvar_39.xyz = zz_30;\n tmpvar_39.w = li_28;\n float tmpvar_40;\n tmpvar_40 = sqrt(dot (zz_30, zz_30));\n xlat_mutablestruc = (sqrt(dot (tmpvar_39.xyw, tmpvar_39.xyw)) / 24.0);\n vec4 tmpvar_41;\n tmpvar_41 = texture (sampler_pc_main, uv_3);\n float tmpvar_42;\n float tmpvar_43;\n tmpvar_43 = (q10 * 0.7);\n tmpvar_42 = ((log(\n (1.0 + (tmpvar_40 / 24.0))\n ) * 0.02) * (1.0 - (1.0 - \n ((tmpvar_41.z + (0.003921569 * tmpvar_41.y)) + tmpvar_43)\n )));\n float tmpvar_44;\n vec4 tmpvar_45;\n tmpvar_45 = texture (sampler_pc_main, uv_3);\n tmpvar_44 = (1.0 - ((tmpvar_45.z + \n (0.003921569 * tmpvar_45.y)\n ) + tmpvar_43));\n if ((((tmpvar_25 <= tmpvar_44) && (tmpvar_40 < 24.0)) && (tmpvar_25 > 0.005))) {\n ret_4.x = (((1.0 - sustain) * xlat_mutablestruc) + (sustain * mix (texture (sampler_main, uv_3).xyz, \n ((texture (sampler_blur1, uv_3).xyz * scale1) + bias1)\n , vec3(\n (q14 * 4.0)\n )).x));\n float x_46;\n x_46 = ((1.0 - tmpvar_25) * 255.0);\n float ip_47;\n ip_47 = float(int(x_46));\n vec2 tmpvar_48;\n tmpvar_48.x = (x_46 - ip_47);\n tmpvar_48.y = (ip_47 / 255.0);\n ret_4.yz = tmpvar_48;\n } else {\n vec3 tmpvar_49;\n tmpvar_49.y = 0.0;\n tmpvar_49.x = sustain;\n tmpvar_49.z = (1.0 - tmpvar_42);\n vec3 tmpvar_50;\n tmpvar_50.xy = vec2(0.003921569, 0.0);\n tmpvar_50.z = (q14 / 6.0);\n ret_4 = ((texture (sampler_fc_main, uv_3).xyz * tmpvar_49) - tmpvar_50);\n };\n vec4 tmpvar_51;\n tmpvar_51.w = 1.0;\n tmpvar_51.xyz = ret_4;\n ret = tmpvar_51.xyz;\n }', + comp: ' shader_body { \n vec3 tmpvar_1;\n tmpvar_1.x = q4;\n tmpvar_1.y = q5;\n tmpvar_1.z = q6;\n mat3 tmpvar_2;\n tmpvar_2[uint(0)].x = q20;\n tmpvar_2[uint(0)].y = q23;\n tmpvar_2[uint(0)].z = q26;\n tmpvar_2[1u].x = q21;\n tmpvar_2[1u].y = q24;\n tmpvar_2[1u].z = q27;\n tmpvar_2[2u].x = q22;\n tmpvar_2[2u].y = q25;\n tmpvar_2[2u].z = q28;\n vec2 tmpvar_3;\n tmpvar_3.x = q1;\n tmpvar_3.y = q2;\n vec2 uv_4;\n vec3 ret_5;\n uv_4 = (((uv - 0.5) * 0.9) + 0.5);\n vec3 tmpvar_6;\n tmpvar_6.xy = ((uv_4 - 0.5) * min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z)));\n tmpvar_6.z = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n float tmpvar_7;\n tmpvar_7 = clamp ((abs(\n ((1.0 - ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2).z) - clamp ((1.0 - (\n (texture (sampler_blur2, tmpvar_3).xyz * scale2)\n + bias2).z), 0.1, 0.4))\n ) + 0.2), 0.0, 1.0);\n float tmpvar_8;\n tmpvar_8 = clamp (((1.0 - \n exp(-(((texture (sampler_blur1, uv_4).xyz * scale1) + bias1).x))\n ) - 0.2), 0.0, 1.0);\n ret_5 = ((mix (texture (sampler_main, uv_4).xyz, \n ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1)\n , vec3(tmpvar_7)).x * (0.2 + \n ((1.0 - tmpvar_7) * (1.0 - min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z))))\n )) * (1.0 + (0.5 * \n sin((((tmpvar_6 / q7) * tmpvar_2) + tmpvar_1))\n )));\n vec3 tmpvar_9;\n tmpvar_9.xy = vec2(0.0, 1.0);\n tmpvar_9.z = (tmpvar_8 * 3.0);\n ret_5 = (mix (ret_5, tmpvar_9, vec3(tmpvar_8)) + ((\n pow ((1.0 - mix (texture (sampler_main, uv_4).xyz, (\n (texture (sampler_blur1, uv_4).xyz * scale1)\n + bias1), vec3(0.8, 0.8, 0.8)).z), 3.0)\n * \n (0.5 + (0.5 * slow_roam_cos))\n ) * q19).xyz);\n ret_5 = (1.0 - exp((-2.0 * ret_5)));\n vec4 tmpvar_10;\n tmpvar_10.w = 1.0;\n tmpvar_10.xyz = ret_5;\n ret = tmpvar_10.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 0, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 7, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.958178, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + ob_r: 0.3999, + ob_a: 0.2, + ib_size: 0, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { + baseVals: { + enabled: 1, + sides: 100, + additive: 1, + x: 0.26, + y: 0.2, + rad: 0.393173, + tex_zoom: 0.9355, + r: 0, + g: 0.55, + b: 0.5, + g2: 0.4, + b2: 0.4, + a2: 0.07, + border_r: 0.3, + border_g: 0.7, + border_b: 0.8, + border_a: 0, + }, + init_eqs_str: + 'a.g0=0;a.y0=0;a.q1=0;a.x0=0;a.q24=0;a.q26=0;a.r0=0;a.trig=0;a.q2=0;a.b0=0;a.rad0=0;', + frame_eqs_str: + 'a.trig=a.q24;a.x0=a.x0*bnot(a.trig)+a.trig*(.5+div(randint(100),200));a.y0=a.y0*bnot(a.trig)+a.trig*(.5+div(randint(100),200));a.x0+=div(.1*a.q1*(3+a.q26),a.fps);a.y0+=div(.1*a.q2*(3+a.q26),a.fps);a.x0-=Math.floor(a.x0);a.y0-=Math.floor(a.y0);a.tex_ang=a.time;a.tex_zoom=a.q1;a.ang=div(a.time,100)*a.q2;a.x=a.x0;a.y=a.y0;a.rad0=a.rad0*bnot(a.trig)+a.trig*(.04+div(randint(100),1E3));a.rad=a.rad0;a.r0=bnot(a.trig)*a.r0+div(a.trig*randint(10),10);a.g0=bnot(a.trig)*a.g0+div(a.trig*\nrandint(10),10);a.b0=bnot(a.trig)*a.b0+div(a.trig*randint(10),10);a.r=a.r0;a.b=a.b0;a.g=a.g0;a.r2=0;a.b2=0;a.g2=0;a.a=1;a.a2=.3;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.index4=0;a.index=0;a.q22=0;a.q21=0;a.q1=0;a.dec_med=0;a.index3=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q11=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q28=0;a.q20=0;', + frame_eqs_str: + 'a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.index3=mod(a.index3+a.is_beat*bnot(a.index)*bnot(a.index2),3);a.monitor=a.index4;\na.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.q11=Math.min(a.q22,3);a.k1=a.is_beat*equal(a.index,0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265359*a.p2,2);a.q27=8-a.index;a.q28=a.index2;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1+.02*a.q1;a.rot=.01*a.q2;a.dx=0*a.index;a.wave_a=0;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: 'float xlat_mutabledx;\nfloat xlat_mutabledy;\nvec2 xlat_mutableuv2;\nvec2 xlat_mutablezz;\n shader_body { \n vec2 uv_1;\n vec3 crisp_2;\n vec2 tmpvar_3;\n tmpvar_3.y = 0.0;\n tmpvar_3.x = texsize.w;\n vec2 tmpvar_4;\n tmpvar_4.x = 0.0;\n tmpvar_4.y = texsize.z;\n xlat_mutablezz = ((uv * texsize.xy) * 0.01);\n vec2 tmpvar_5;\n tmpvar_5.x = (cos((xlat_mutablezz.y * q1)) * sin(-(xlat_mutablezz.y)));\n tmpvar_5.y = (sin(xlat_mutablezz.x) * cos((xlat_mutablezz.y * q2)));\n uv_1 = (uv - ((tmpvar_5 * texsize.zw) * (8.0 + \n (6.0 * q11)\n )));\n xlat_mutableuv2 = (((uv_1 / 2.0) * q27) / 4.0);\n xlat_mutabledx = dot ((texture (sampler_main, (xlat_mutableuv2 + tmpvar_3)).xyz - texture (sampler_main, (xlat_mutableuv2 - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledy = dot ((texture (sampler_main, (xlat_mutableuv2 + tmpvar_4)).xyz - texture (sampler_main, (xlat_mutableuv2 - tmpvar_4)).xyz), vec3(0.32, 0.49, 0.29));\n float tmpvar_6;\n tmpvar_6 = (0.15 + (0.1 * q28));\n vec2 tmpvar_7;\n tmpvar_7 = (xlat_mutableuv2 + (time / 100.0));\n xlat_mutabledx = (xlat_mutabledx + (tmpvar_6 * (texture (sampler_noise_hq, tmpvar_7).x - 0.5)));\n xlat_mutabledy = (xlat_mutabledy + (tmpvar_6 * (texture (sampler_noise_hq, tmpvar_7).y - 0.5)));\n vec2 tmpvar_8;\n tmpvar_8.x = xlat_mutabledx;\n tmpvar_8.y = xlat_mutabledy;\n xlat_mutablezz = tmpvar_8;\n crisp_2 = (texture (sampler_main, (uv_1 + (tmpvar_8 * 0.04))).xyz + texture (sampler_main, uv_1).xyz);\n crisp_2 = (crisp_2 * 0.5);\n crisp_2 = (crisp_2 + ((0.05 * \n (0.9 + (0.1 * roam_cos))\n .xyz) - (\n sqrt(dot (tmpvar_8, tmpvar_8))\n * 0.3)));\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ((crisp_2 * 0.97) - 0.015);\n ret = tmpvar_9.xyz;\n }', + comp: 'vec2 xlat_mutabledz;\nvec3 xlat_mutableneu;\nvec3 xlat_mutableret1;\nvec2 xlat_mutableuv3;\n shader_body { \n vec2 uv2_1;\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = texsize.z;\n vec2 tmpvar_3;\n tmpvar_3.x = 0.0;\n tmpvar_3.y = texsize.w;\n xlat_mutabledz.x = dot ((texture (sampler_main, (uv + tmpvar_2)).xyz - texture (sampler_main, (uv - tmpvar_2)).xyz), vec3(0.32, 0.49, 0.29));\n xlat_mutabledz.y = dot ((texture (sampler_main, (uv + tmpvar_3)).xyz - texture (sampler_main, (uv - tmpvar_3)).xyz), vec3(0.32, 0.49, 0.29));\n uv2_1 = (uv - 0.5);\n xlat_mutableuv3 = ((0.2 * uv2_1) + 0.5);\n float tmpvar_4;\n tmpvar_4 = (time / 2.0);\n xlat_mutableuv3 = ((0.2 * cos(\n ((42.0 * fract(xlat_mutableuv3)) + tmpvar_4)\n )) + (99.0 * xlat_mutabledz));\n float tmpvar_5;\n tmpvar_5 = clamp ((0.01 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_5)) + (0.9 * dot (vec3(tmpvar_5), vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (vec3(0.0, 0.0, 0.0), (xlat_mutableneu * 1.252262));\n xlat_mutableuv3 = ((0.2 * uv2_1) + 0.5);\n xlat_mutableuv3 = ((0.2 * cos(\n ((42.0 * fract(xlat_mutableuv3)) + tmpvar_4)\n )) + (99.0 * xlat_mutabledz));\n float tmpvar_6;\n tmpvar_6 = clamp ((0.01 / sqrt(\n dot (xlat_mutableuv3, xlat_mutableuv3)\n )), 0.0, 1.0);\n xlat_mutableneu = ((0.1 * vec3(tmpvar_6)) + (0.9 * dot (vec3(tmpvar_6), vec3(0.32, 0.49, 0.29))));\n xlat_mutableret1 = max (xlat_mutableret1, (xlat_mutableneu * 1.252262));\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = (xlat_mutableret1 + clamp ((\n (16.0 * ((0.5 * texture (sampler_main, (uv + \n (0.1 * xlat_mutabledz)\n )).xyz) + 0.01))\n * \n (0.1 + xlat_mutableret1)\n ), 0.0, 1.0));\n ret = tmpvar_7.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 4, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.527, + wave_smoothing: 0.45, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0.8, + wave_g: 0.49, + ob_size: 0.015, + ob_a: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b2x: 0.3, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + samples: 506, + sep: 116, + spectrum: 1, + thick: 1, + scaling: 1.07408, + smoothing: 0, + a: 0.7, + }, + init_eqs_str: 'a.n=0;a.m=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.n=Math.floor((a.reg00+.5)*a.sample);a.m=30001+div(a.n,div(a.reg00,a.reg01));a.gmegabuf[Math.floor(a.m)]=a.value1+a.value2;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;', + }, + { + baseVals: { enabled: 1, samples: 506, thick: 1, scaling: 0.89152, smoothing: 0.82 }, + init_eqs_str: 'a.n=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.n=Math.floor((a.reg00+.5)*a.sample)+a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;', + }, + { + baseVals: { enabled: 1, samples: 506, thick: 1, scaling: 0.89152, smoothing: 0.82 }, + init_eqs_str: 'a.n=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.n=Math.floor((a.reg00+.5)*a.sample)+2*a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;', + }, + { + baseVals: { enabled: 1, samples: 506, spectrum: 1, thick: 1 }, + init_eqs_str: 'a.n=0;', + frame_eqs_str: '', + point_eqs_str: + 'a.n=Math.floor((a.reg00-.5)*a.sample)+3*a.reg00;a.x=a.gmegabuf[Math.floor(1E4+a.n)];a.y=a.gmegabuf[Math.floor(15E3+a.n)];a.a=a.gmegabuf[Math.floor(2E4+a.n)];a.b=Math.min(Math.max(a.gmegabuf[Math.floor(25E3+a.n)],0),1);a.r=1-a.b;a.g=.5;', + }, + ], + init_eqs_str: + 'a.xang=0;a.fov=0;a.hell=0;a.cbeat=0;a.index2=0;a.bindex=0;a.ran4=0;a.index=0;a.dec_v=0;a.yang=0;a.q29=0;a.q6=0;a.amp_=0;a.xlen=0;a.smooth=0;a.q1=0;a.dec_med=0;a.sum=0;a.q5=0;a.dec_f=0;a.trely=0;a.flen=0;a.reg01=0;a.my=0;a.oz=0;a.imag=0;a.is_beat=0;a.yind=0;a.oy0a=0;a.dec_slow=0;a.ran2=0;a.ind=0;a.z0=0;a.ylen=0;a.real=0;a.ran4_=0;a.ran3=0;a.q4=0;a.mz=0;a.oy0=0;a.amp=0;a.tc0=0;a.oy=0;a.avg=0;a.mx=0;a.vol=0;a.ran2_=0;a.peak=0;a.decc=0;a.q2=0;a.bd_bt=0;a.zang=0;a.q3=0;a.reg00=0;\na.trelz=0;a.q32=0;a.ran3_=0;a.q28=0;a.trelx=0;a.q30=0;a.ox=0;a.xind=0;for(var b=a.index=0;7E4>b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.zang=1;a.yang=0;a.zang=2;', + frame_eqs_str: + 'a.xlen=45;a.ylen=45;a.flen=30;a.reg00=div(a.xlen*a.ylen,4);a.reg01=div(a.reg00,4);a.dec_med=1-div(.06*30,a.fps);a.dec_slow=1-div(.6,a.fps);a.dec_f=pow(.8,div(30,a.fps));a.q30=a.dec_slow;a.smooth=Math.max(1,pow(6,div(a.fps,30))-2);a.cbeat=a.bass+a.mid+a.treb;a.decc=.00001a.cbeat?1:0)?.8:a.dec_med;a.vol=a.vol*a.decc+(1-a.decc)*a.cbeat;a.avg=a.avg*a.dec_slow+a.cbeat*(1-a.dec_slow);a.is_beat=above(a.cbeat,1.5*a.avg)*above(a.time,a.tc0+.2);a.tc0=.00001c;c++){a.xind=-1;for(var d=0;3>d;d++)a.ox=mod((a.cx+.5)*a.xlen+a.xind,a.xlen),a.oy=mod((a.cy+.5)*a.ylen+a.yind,a.ylen),a.amp=3*(a.cx*a.cx+a.cy*a.cy),a.megabuf[Math.floor(a.oy*a.ylen+a.ox)]-=div(div(60,a.fps)*sqrt(a.amp)*above(a.amp,.02),1+a.xind*a.xind+a.yind*a.yind),a.xind+=1;a.yind+=1}a.ind+=1}for(b=a.yind=0;bMath.abs(mod(a.bindex,4)-0)?1:0)?a.ran2=div(randint(100)-30,60):0;.00001\nMath.abs(mod(a.bindex,4)-2)?1:0)?a.ran3=div(randint(100)-30,60):0;.00001Math.abs(mod(a.bindex,6)-2)?1:0)?a.ran4=div(randint(100)-30,60):0;a.dec_v=Math.min(Math.max(0,1-div(8*a.vol,a.fps)),a.dec_slow);a.ran2_=a.ran2_*a.dec_v+(1-a.dec_v)*a.ran2;a.ran3_=a.ran3_*a.dec_v+(1-a.dec_v)*a.ran3;a.ran4_=a.ran4_*a.dec_v+(1-a.dec_v)*a.ran4;a.trelx+=div(div(a.ran2_,a.fps),7);a.trely+=div(div(a.ran3_,a.fps),2);a.trelz+=div(div(a.ran4_,a.fps),6);a.zang=6*Math.sin(a.trelz);a.xang=6*Math.sin(div(a.zang,\n5)+a.trelx);a.yang=6*Math.sin(0*div(a.zang,3)+a.trely);a.q1=Math.cos(a.xang);a.q2=Math.sin(a.xang);a.q3=Math.cos(a.yang);a.q4=Math.sin(a.yang);a.q5=Math.cos(a.zang);a.q6=Math.sin(a.zang);a.fov=1;for(b=a.yind=0;b 0.0))\n ) * 0.2) * min (1.0, (1.0/(tmpvar_8))));\n ret_4 = (ret_4 + tmpvar_14);\n ret_4 = (ret_4 + ((\n (sin((12.0 * q2)) * tmpvar_7)\n * tmpvar_14) * dot (\n (12.0 * ((texture (sampler_blur1, (tmpvar_10 - vec2(-0.5, 0.3))).xyz * scale1) + bias1))\n , vec3(0.32, 0.49, 0.29))));\n ret_4 = (ret_4 + ((\n ((0.5 / abs(tmpvar_8)) * normalize(xlat_mutablecol))\n * \n float((tmpvar_8 < 0.0))\n ) * tmpvar_7));\n vec4 tmpvar_15;\n tmpvar_15.w = 1.0;\n tmpvar_15.xyz = ret_4;\n ret = tmpvar_15.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 5, + gammaadj: 1.980001, + decay: 0.5, + echo_zoom: 0.999998, + echo_alpha: 0.5, + echo_orient: 3, + modwavealphabyvolume: 1, + darken: 1, + wave_a: 0.001, + wave_scale: 10.437056, + wave_smoothing: 0.45, + wave_mystery: 0.08, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.4595, + warpscale: 2.0067, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0.99, + ob_size: 0, + ob_r: 1, + ob_g: 1, + ob_b: 1, + ib_size: 0, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.4999, + mv_g: 0.4999, + mv_b: 0.4999, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + rad: 0.048958, + tex_ang: 1.00531, + tex_zoom: 1.531168, + r: 0.5, + g: 1, + b: 0.9, + r2: 0.83, + g2: 0.93, + b2: 0.8, + a2: 1, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.trel=0;a.q20=0;a.q28=0;a.q26=0;', + frame_eqs_str: + 'a.trel=div(a.time,2)+a.q20;a.x=.5+Math.sin(2*a.trel);a.y=.5+Math.cos(1.3*a.trel+div(a.q28,3));a.a=div(a.q26,4)+.2;', + }, + { baseVals: { enabled: 0 } }, + { + baseVals: { + enabled: 1, + x: 0.503, + rad: 0.038857, + tex_zoom: 0.609857, + g: 0.1, + a: 0.9, + r2: 1, + b2: 1, + border_r: 0.5, + border_g: 0.5, + border_b: 0.5, + border_a: 0, + }, + init_eqs_str: 'a.is_beat=0;a.t0=0;a.q21=0;', + frame_eqs_str: + 'a.x=div(randint(10),10);a.y=div(randint(10),10);a.r=div(randint(4),3);a.g=div(randint(4),3);a.b=div(randint(4),3);a.is_beat=above(a.time,a.t0+.03);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.a=Math.min(div(a.q21,2),.9)*a.is_beat;a.rad=div(a.a*a.a,3);', + }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, sep: 120, additive: 1, scaling: 0.891519, smoothing: 0.82, a: 0.6 }, + init_eqs_str: + 'a.k1=0;a.k2=0;a.xi=0;a.yi=0;a.dx=0;a.dy=0;a.q22=0;a.t2=0;a.t1=1+.3*(.01*randint(101)-.01*randint(101));a.t2=1+.3*(.01*randint(101)-.01*randint(101));a.t3=1+.3*(.01*randint(101)-.01*randint(101));a.t4=1+.3*(.01*randint(101)-.01*randint(101));a.t5=1+.3*(.01*randint(101)-.01*randint(101));a.t6=1+.3*(.01*randint(101)-.01*randint(101));a.t7=1+.3*(.01*randint(101)-.01*randint(101));a.t8=1+.3*(.01*randint(101)-.01*randint(101));', + frame_eqs_str: 'a.t2+=a.bass_att;', + point_eqs_str: + 'a.k1=mod(100*a.sample,8);a.k2=bnot(a.k1);a.xi=a.value1*a.k2+a.xi*(1-a.k2);a.yi=a.value2*(1-a.k2)+a.yi*a.k2;a.dx=.99*a.dx+a.xi;a.dy=.99*a.dy+a.yi;a.x=.5+div(a.xi,2);a.y=.5+div(a.yi,2);a.a=div(a.q22,8);a.a=Math.min(a.a,.2);', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index=0;a.q22=0;a.q21=0;a.fade=0;a.q1=0;a.dec_med=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q32=0;a.q20=0;a.fade=.5;', + frame_eqs_str: + 'a.dec_med=pow(.9,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.5+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.q23=a.index;a.q24=a.is_beat;a.q26=a.bass+a.mid+a.treb;a.k1=a.is_beat*equal(a.index,0);a.p1=\na.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.14159265358*a.p2,2);a.q27=a.index+1;a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;a.zoom=1;a.rot=-0*a.index;a.fade=a.fade*a.dec_med+pow(.996,div(30,a.fps))*(1-a.dec_med);a.q32=a.fade;', + pixel_eqs_str: '', + pixel_eqs: '', + warp: ' shader_body { \n vec2 zz_1;\n mat2 tmpvar_2;\n tmpvar_2[uint(0)] = _qa.xy;\n tmpvar_2[1u] = _qa.zw;\n zz_1 = (((\n (uv - vec2(0.5, 0.5))\n * texsize.xy) * (0.015 * q27)) * tmpvar_2);\n vec4 tmpvar_3;\n tmpvar_3.w = 1.0;\n tmpvar_3.xyz = (((q32 * texture (sampler_main, \n (uv + ((clamp (\n (sin(zz_1) / cos(zz_1))\n , vec2(-20.0, -20.0), vec2(20.0, 20.0)) * texsize.zw) * 8.0))\n ).xyz) + (\n (0.03 * texture (sampler_noise_lq, ((uv * 0.3) + (0.01 * rand_frame).xy)))\n .xyz * \n (1.0 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n )) - 0.02);\n ret = tmpvar_3.xyz;\n }', + comp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_main, uv);\n vec4 tmpvar_2;\n tmpvar_2.w = 1.0;\n tmpvar_2.xyz = ((tmpvar_1.xyz + clamp (\n (3.0 * (((texture (sampler_blur1, \n (uv - (0.01 * tmpvar_1.xyz).xy)\n ).xyz * scale1) + bias1) - vec3(0.1, 0.1, 0.2)))\n , 0.0, 1.0)) * 1.3);\n ret = tmpvar_2.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 0.952, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 6, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 2.103, + wave_smoothing: 0.54, + wave_mystery: 0.38, + modwavealphastart: 0.81, + modwavealphaend: 1.4, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0, + wave_g: 0, + wave_b: 0, + ob_size: 0.015, + ob_b: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 16, + thickoutline: 1, + textured: 1, + num_inst: 3, + x: 0.73, + rad: 0.29466, + tex_zoom: 1.87511, + r: 0.7, + g: 0.7, + b: 1, + g2: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.trig=0;a.q25=0;a.x0=0;a.y0=0;', + frame_eqs_str: + 'a.trig=a.q25;a.a=.8*a.trig;a.a2=0;a.x0=a.x0*bnot(a.trig)+div(a.trig*randint(100),100);a.y0=a.y0*bnot(a.trig)+div(a.trig*randint(100),100);a.tex_ang=randint(20);a.rad=.1+div(randint(10),8);a.x=a.x0;a.y=a.y0;a.r=.7+.3*Math.sin(div(a.time,12));a.b=.7+.3*Math.sin(div(a.time,15));a.g=.7+.3*Math.sin(div(a.time,8));a.r2=a.r;a.b2=a.b;a.g2=a.g;', + }, + { + baseVals: { + enabled: 1, + sides: 36, + thickoutline: 1, + textured: 1, + num_inst: 4, + x: 0.3, + rad: 0.05429, + ang: 1.25664, + tex_ang: 0.37699, + tex_zoom: 1.02841, + g: 0.7, + b: 0.5, + r2: 1, + g2: 0, + border_g: 0.59, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.q31=0;a.q32=0;a.q30=0;', + frame_eqs_str: 'a.x=a.q31;a.y=a.q32;a.rad=.06;a.tex_ang=a.time;a.a=a.q30;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.q25=0;a.index=0;a.q12=0;a.q22=0;a.q21=0;a.q15=0;a.q29=0;a.q6=0;a.dec_med=0;a.q5=0;a.mindev=0;a.trel=0;a.t0a=0;a.mov1=0;a.vis=0;a.is_beat=0;a.q31=0;a.q23=0;a.q24=0;a.dec_slow=0;a.q11=0;a.hpeak=0;a.q10=0;a.sdev=0;a.med=0;a.spb=0;a.dir=0;a.spb_=0;a.q16=0;a.rota=0;a.q19=0;a.vol=0;a.peak=0;a.trig1=0;a.wamp=0;a.speed=0;a.t0=0;a.vol_=0;a.q32=0;a.q7=0;a.wamp_=0;a.q30=0;a.q20=0;a.q8=0;a.t0a=a.time;a.t0=a.time+.5;a.spb_=.5;a.volb=.5;a.volx=.5;a.vol_=1;a.index=0;a.mov1=0;a.sdev=.1;a.wamp_=\n.1;', + frame_eqs_str: + 'a.dec_med=pow(.8,div(30,a.fps));a.dec_slow=pow(.95,div(30,a.fps));a.vol=div(a.bass+a.med+a.treb,1.5);a.vol_=a.vol_*a.dec_slow+(1-a.dec_slow)*a.vol;a.is_beat=above(a.vol,a.vol_+2*a.peak)*above(a.time,a.t0+.45*a.spb_);a.t0a=.00001= 0.0)\n )) + (q30 * 0.02));\n xlat_mutablered = (xlat_mutablered + ((\n (xlat_mutablewave / abs(sin((\n (1.0/(tmpvar_12))\n + \n (q1 / 8.0)\n ))))\n * xlat_mutablegreen) * ky_3));\n xlat_mutablezv = ((time * 0.08) + (0.2 * sin(\n ((uv * 16.0) + time)\n ))).x;\n vec2 tmpvar_13;\n tmpvar_13.x = q28;\n tmpvar_13.y = (0.2 * time);\n xlat_mutableuv2 = ((tmpvar_4 * 2.0) + tmpvar_13);\n vec3 tmpvar_14;\n tmpvar_14.xy = xlat_mutableuv2;\n tmpvar_14.z = xlat_mutablezv;\n vec3 tmpvar_15;\n tmpvar_15.xy = (xlat_mutableuv2 * vec2(2.0, 2.0));\n tmpvar_15.z = (xlat_mutablezv * 2.0);\n vec3 tmpvar_16;\n tmpvar_16.xy = (xlat_mutableuv2 * vec2(4.0, 4.0));\n tmpvar_16.z = (xlat_mutablezv * 3.0);\n vec3 tmpvar_17;\n tmpvar_17.xy = (xlat_mutableuv2 * vec2(8.0, 8.0));\n tmpvar_17.z = (xlat_mutablezv * 7.0);\n xlat_mutableuv2 = (tmpvar_4 + ((\n ((texture (sampler_noisevol_hq, tmpvar_14).z + (texture (sampler_noisevol_hq, tmpvar_15).z / 2.0)) + (texture (sampler_noisevol_hq, tmpvar_16).z / 4.0))\n + \n (texture (sampler_noisevol_hq, tmpvar_17).z / 8.0)\n ) * 0.1));\n vec3 tmpvar_18;\n tmpvar_18.x = xlat_mutablered;\n tmpvar_18.y = xlat_mutablegreen;\n tmpvar_18.z = ((1.0 + xlat_mutableuv2.y) * sqrt(dot (xlat_mutableuv2, xlat_mutableuv2)));\n vec4 tmpvar_19;\n tmpvar_19.w = 1.0;\n tmpvar_19.xyz = ((tmpvar_18 * 0.8) - 0.005);\n ret = tmpvar_19.xyz;\n }', + comp: 'float trel;\nfloat vshift;\nvec3 xlat_mutableret1;\nvec2 xlat_mutablers;\nvec2 xlat_mutablers0;\nfloat xlat_mutablesmoke;\nfloat xlat_mutablesmoke2;\nvec2 xlat_mutableuv_l;\nfloat xlat_mutablew;\nfloat xlat_mutablez;\n shader_body { \n trel = (time / 2.0);\n vshift = (0.5 - q29);\n vec2 tmpvar_1;\n tmpvar_1.x = rand_preset.x;\n tmpvar_1.y = ((-0.1 - (rand_preset.y / 2.0)) + vshift);\n vec2 tmpvar_2;\n tmpvar_2.y = 0.0;\n tmpvar_2.x = (0.005 * time);\n xlat_mutableuv_l = (uv + tmpvar_2);\n vec2 tmpvar_3;\n vec2 tmpvar_4;\n tmpvar_4 = (uv - 0.5);\n tmpvar_3 = sin(((\n (tmpvar_4 * aspect.xy)\n + 0.5) - (tmpvar_1 * aspect.xy)));\n vec2 tmpvar_5;\n tmpvar_5 = fract(uv);\n vec3 tmpvar_6;\n tmpvar_6 = vec3((texture (sampler_fc_main, tmpvar_5).x + (2.0 * (\n (texture (sampler_blur2, tmpvar_5).xyz * scale2)\n + bias2).x)));\n vec3 tmpvar_7;\n tmpvar_7.x = tmpvar_6.x;\n tmpvar_7.y = pow (tmpvar_6.x, 2.1);\n tmpvar_7.z = pow (tmpvar_6.x, 4.0);\n xlat_mutablew = ((uv.y - (\n ((dot (texture (sampler_noise_hq, vec2((xlat_mutableuv_l.x / 6.0))), vec4(0.32, 0.49, 0.29, 0.0)) + uv.x) - 0.5)\n / 4.0)) - vshift);\n xlat_mutablez = (0.2 / xlat_mutablew);\n float tmpvar_8;\n tmpvar_8 = clamp ((-0.2 - (\n (8.0 * q5)\n * xlat_mutablew)), 0.0, 1.0);\n xlat_mutablers0.x = (((uv.x - 0.5) * (1.0 + \n abs(xlat_mutablez)\n )) * 2.0);\n xlat_mutablers0.y = xlat_mutablez;\n xlat_mutablers0 = (xlat_mutablers0 * ((4.0 * \n float((xlat_mutablez <= 0.0))\n ) + 1.0));\n vec2 tmpvar_9;\n tmpvar_9.x = 0.0;\n tmpvar_9.y = (1.5 + xlat_mutablew);\n vec2 x_10;\n x_10 = (xlat_mutablers0 - tmpvar_9);\n float tmpvar_11;\n tmpvar_11 = ((q26 / sqrt(\n dot (x_10, x_10)\n )) / 4.0);\n xlat_mutablers0 = (xlat_mutablers0 * (1.0 + (tmpvar_11 * tmpvar_11)));\n xlat_mutablers.x = (xlat_mutablers0 * 2.0).x;\n xlat_mutablers.y = (xlat_mutablers0.y + (trel * 0.5));\n float tmpvar_12;\n tmpvar_12 = (texture (sampler_main, uv).y * tmpvar_8);\n vec3 tmpvar_13;\n tmpvar_13.xy = (xlat_mutablers * 2.0);\n tmpvar_13.z = (0.2 * trel);\n float tmpvar_14;\n tmpvar_14 = dot (((\n ((2.0 * clamp ((texture (sampler_noisevol_hq, \n (tmpvar_13 * float((xlat_mutablez >= 0.0)))\n ) - 0.2), 0.0, 1.0)).xyz * clamp ((texture (sampler_noise_hq, (xlat_mutablers / 16.0)) - 0.5), 0.0, 1.0).x)\n / \n sqrt(abs(xlat_mutablez))\n ) + tmpvar_11), vec3(0.32, 0.49, 0.29));\n vec3 tmpvar_15;\n tmpvar_15.x = tmpvar_14;\n tmpvar_15.y = pow (tmpvar_14, 2.1);\n tmpvar_15.z = pow (tmpvar_14, 6.0);\n xlat_mutableret1 = (((\n ((uv.y * (1.0 + q23)) + (0.1 / sqrt(dot (tmpvar_3, tmpvar_3))))\n * vec3(0.1, 0.1, 0.2)) * tmpvar_8) + (clamp (tmpvar_15, 0.0, 1.0) * (1.0 - \n clamp ((-1.0 - (12.0 * xlat_mutablew)), 0.0, 1.0)\n )));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((1.0 - \n (tmpvar_12 * 8.0)\n ), 0.0, 1.0));\n vec4 tmpvar_16;\n tmpvar_16 = texture (sampler_main, fract((tmpvar_4 + 0.5)));\n xlat_mutablesmoke = (tmpvar_16.z * (tmpvar_16.z * q5));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((1.0 - \n ((xlat_mutablesmoke * q32) * tmpvar_8)\n ), 0.0, 1.0));\n xlat_mutablesmoke2 = (texture (sampler_main, ((tmpvar_4 / 2.0) + 0.5)).z * q30);\n xlat_mutableret1 = (xlat_mutableret1 + (clamp (tmpvar_7, 0.0, 1.0) - (\n ((xlat_mutablez * clamp ((xlat_mutablesmoke + \n (xlat_mutablew * q31)\n ), 0.0, 1.0)) * vec3(1.0, 0.4, 0.1))\n * tmpvar_8)));\n float tmpvar_17;\n tmpvar_17 = clamp (((\n (tmpvar_12 * xlat_mutablez)\n * xlat_mutablez) / 16.0), 0.0, 1.0);\n vec3 tmpvar_18;\n tmpvar_18.x = tmpvar_17;\n tmpvar_18.y = pow (tmpvar_17, 2.1);\n tmpvar_18.z = pow (tmpvar_17, 6.0);\n xlat_mutableret1 = (xlat_mutableret1 + clamp (tmpvar_18, 0.0, 1.0));\n xlat_mutableret1 = (xlat_mutableret1 * clamp ((\n (((dot (texture (sampler_noise_mq, vec2(\n ((xlat_mutableuv_l.x / 4.0) + (0.02 * trel))\n )), vec4(0.32, 0.49, 0.29, 0.0)) / 6.0) - uv.y) + 0.8)\n * 32.0), 0.0, 1.0));\n vec3 tmpvar_19;\n tmpvar_19.x = xlat_mutablesmoke2;\n tmpvar_19.y = pow (xlat_mutablesmoke2, 2.1);\n tmpvar_19.z = pow (xlat_mutablesmoke2, 6.0);\n xlat_mutableret1 = ((xlat_mutableret1 * clamp (\n (1.0 - xlat_mutablesmoke2)\n , 0.0, 1.0)) + clamp (tmpvar_19, 0.0, 1.0));\n vec4 tmpvar_20;\n tmpvar_20.w = 1.0;\n tmpvar_20.xyz = (1.0 - exp((\n -(xlat_mutableret1)\n * 2.0)));\n ret = tmpvar_20.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 3, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 6, + wave_thick: 1, + modwavealphabyvolume: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.527, + wave_smoothing: 0.09, + modwavealphastart: 0, + modwavealphaend: 1.32, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0.8, + wave_g: 0.49, + ob_a: 1, + ib_size: 0.26, + mv_x: 64, + mv_y: 48, + mv_l: 1.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + b2x: 0.7, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 12, + num_inst: 1024, + rad: 0.03632, + tex_ang: 1.00531, + tex_zoom: 1.53117, + b: 1, + a: 0, + g2: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: 'a.fov=0;a.n=0;a.x0=0;a.y0=0;a.z0=0;a.q32=0;a.t1=0;', + frame_eqs_str: + 'a.fov=a.reg03;a.n=a.instance*a.reg00;a.x0=a.gmegabuf[Math.floor(a.n)];a.y0=a.gmegabuf[Math.floor(a.n+1)];a.z0=a.gmegabuf[Math.floor(a.n+2)]+a.reg02;a.x=div(a.x0,a.z0)*a.fov+.5;a.y=div(a.y0,a.z0)*a.q32*a.fov+.5;a.r=a.gmegabuf[Math.floor(a.n+3)];a.g=a.gmegabuf[Math.floor(a.n+4)];a.b=a.gmegabuf[Math.floor(a.n+5)];a.r2=div(a.r,2);a.g2=div(a.g,2);a.b2=div(a.b2,2);a.a=div(a.instance,1024);a.a2=.5*a.a;a.rad=Math.min(div(.02,a.z0),.5)*(0b;b++)a.megabuf[Math.floor(a.index)]=0,a.gmegabuf[Math.floor(a.index)]=0,a.index+=1;a.recsize=8;a.reg00=a.recsize;a.points=1024;a.reg01=0;a.zofs=1+2*div(randint(100),100);a.reg02=a.zofs;a.fov=.3;a.reg03=a.fov;', + frame_eqs_str: + 'a.dec_f=pow(.3,div(30,a.fps));a.dec_m=pow(.85,div(30,a.fps));a.dec_s=pow(.95,div(30,a.fps));a.beat=a.bass+a.mid+a.treb-(a.bass_att+a.mid_att+a.treb_att)+(a.bass+a.mid+a.treb);a.beat/=3;a.peak=a.peak*a.dec_m+(1-a.dec_m)*pow(a.beat-1,1)*(1Math.abs(a.index-2)?1:0))?(a.ran4=div(randint(100),50)-1,a.ran5=div(randint(100),50)-1,a.ran6=div(randint(100),50)-1):0;a.ran4_=a.dec_m*a.ran4_+(1-a.dec_m)*a.ran4;a.ran5_=a.dec_m*a.ran5_+(1-a.dec_m)*a.ran5;a.ran6_=\na.dec_m*a.ran6_+(1-a.dec_m)*a.ran6;.00001Math.abs(a.index-6)?1:0))?(a.ran7=div(randint(100),50)-1,a.ran8=div(randint(100),50)-1,a.ran9=div(randint(100),50)-1):0;a.ran7_=a.dec_m*a.ran7_+(1-a.dec_m)*a.ran7;a.ran8_=a.dec_m*a.ran8_+(1-a.dec_m)*a.ran8;a.ran9_=a.dec_m*a.ran9_+(1-a.dec_m)*a.ran9;a.pk=sqrt(a.peak+.1);a["new"]=Math.floor(12*(a.ran4-a.ran5)*a.pk-div(12*(a.ran3-a.ran1),a.pk));a["new"]=Math.max(Math.min(a["new"],20),2);a.reg01+=a["new"];a.dec=a.dec_m;a.n=a.recsize*\na.points;a.m=0;a.dt1=div(div(.00001 0.5)))\n * 2.0)));\n flash_1 = tmpvar_14;\n float angle_15;\n float tmpvar_16;\n tmpvar_16 = abs(xlat_mutableuv2.x);\n if ((xlat_mutableuv2.y >= 0.0)) {\n angle_15 = (1.0 - ((xlat_mutableuv2.y - tmpvar_16) / (xlat_mutableuv2.y + tmpvar_16)));\n } else {\n angle_15 = (3.0 - ((xlat_mutableuv2.y + tmpvar_16) / (tmpvar_16 - xlat_mutableuv2.y)));\n };\n angle_15 = (angle_15 * 0.25);\n float tmpvar_17;\n if ((xlat_mutableuv2.x < 0.0)) {\n tmpvar_17 = -(angle_15);\n } else {\n tmpvar_17 = angle_15;\n };\n flash_1 = (tmpvar_14 * (tmpvar_14 / (\n abs((fract((\n (3.0 * tmpvar_17)\n + \n (time * 2.0)\n )) - 0.5))\n + 0.18)));\n vec3 tmpvar_18;\n tmpvar_18 = max ((texture (sampler_main, uv).xyz * 2.0), ((\n (texture (sampler_blur2, uv).xyz * scale2)\n + bias2) * 2.0));\n vec2 tmpvar_19;\n tmpvar_19 = sin(xlat_mutableuv3);\n ret_4 = (clamp ((0.025 / \n sqrt(dot (tmpvar_19, tmpvar_19))\n ), 0.0, 1.0) * vec3(0.4, 0.1, 1.0));\n ret_4 = (ret_4 + clamp ((stars_3 * stars_3), 0.0, 1.0));\n ret_4 = (ret_4 * clamp ((1.0 - \n (2.0 * dot (tmpvar_18, vec3(0.32, 0.49, 0.29)))\n ), 0.0, 1.0));\n ret_4 = (ret_4 + tmpvar_18);\n vec3 tmpvar_20;\n tmpvar_20.x = q10;\n tmpvar_20.y = q11;\n tmpvar_20.z = q12;\n ret_4 = (ret_4 + ((2.0 * \n clamp (flash_1, 0.0, 1.0)\n ) * tmpvar_20));\n vec4 tmpvar_21;\n tmpvar_21.w = 1.0;\n tmpvar_21.xyz = ret_4;\n ret = tmpvar_21.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 4, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + additivewave: 1, + wave_thick: 1, + modwavealphabyvolume: 1, + darken: 1, + wave_a: 0.001, + wave_scale: 0.133, + wave_smoothing: 0, + wave_mystery: -1, + modwavealphastart: 1, + modwavealphaend: 1.3, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0.5, + wave_g: 0.5, + wave_b: 0.5, + ob_size: 0.015, + ob_b: 1, + ib_size: 0.26, + mv_a: 0, + b2x: 0.3, + b1ed: 0, + }, + shapes: [ + { + baseVals: { + enabled: 1, + sides: 40, + thickoutline: 1, + rad: 0.06623, + tex_zoom: 1.79845, + r: 0, + a: 0.1, + g2: 0, + border_b: 0, + border_a: 0, + }, + init_eqs_str: + 'a.vol=0;a.bob=0;a.border_1=0;a.ro=0;a.sp=0;a.red=0;a.spi=0;a.tm=0;a.bob=1.5;a.ro=0;a.red=randint(20);', + frame_eqs_str: + 'a.vol=1+.2*div(a.bass_att+a.treb_att+a.mid_att,3);a.bob=a.bob*above(a.bob,.01)-.01+(1-above(a.bob,.01));a.bob=.4+.4*Math.sin(.8*a.time);a.bob*=a.vol;a.border_1=.4;a.sides=30;a.ro+=.02;a.ang=a.ro;a.sp=.025*a.red;a.spi=.5-a.sp;a.tm=.1*a.time;a.border_r=.5+a.sp*Math.sin(.6*a.tm)+a.spi*Math.cos(1.46*a.tm);a.border_g=.5+a.sp*Math.sin(1.294*a.tm)+a.spi*Math.cos(.87*a.tm);a.border_b=.5+a.sp*Math.sin(1.418*a.tm)+a.spi*Math.cos(.76*a.tm);', + }, + { + baseVals: { enabled: 1, sides: 40, additive: 1, num_inst: 4, g: 1, b: 1, g2: 0, border_a: 0 }, + init_eqs_str: '', + frame_eqs_str: + 'a.x=.5+.225*Math.sin(.7*div(a.time,a.instance));a.y=.5+.3*Math.cos(.7*div(a.time,a.instance));a.x-=.4*a.x*Math.sin(a.time);a.y-=.4*a.y*Math.cos(a.time);a.rad*=a.mid_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);', + }, + { + baseVals: { enabled: 1, sides: 40, additive: 1, g: 1, b: 1, g2: 0, border_a: 0 }, + init_eqs_str: '', + frame_eqs_str: + 'a.x=.5+.5*(.3*Math.sin(1.1*a.time)+.7*Math.sin(.5*a.time));a.x=.5+.225*Math.sin(a.time+2.09);a.y=.5+.3*Math.cos(a.time+2.09);a.rad*=a.bass_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);', + }, + { + baseVals: { + enabled: 1, + sides: 40, + additive: 1, + num_inst: 5, + rad: 0.07419, + g: 1, + b: 1, + g2: 0, + border_a: 0, + }, + init_eqs_str: '', + frame_eqs_str: + 'a.x=.5+.225*Math.sin(div(a.time,a.instance));a.y=.5+.3*Math.cos(div(a.time,a.instance));a.x+=.4*a.x*Math.sin(a.time);a.y+=.4*a.y*Math.cos(a.time);a.rad*=a.treb_att;a.r=.5+.5*Math.sin(.5*a.frame);a.b=.5+.5*Math.sin(.5*a.frame+2.094);a.g=.5+.5*Math.sin(.5*a.frame+4.188);', + }, + ], + waves: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: + 'a.index2=0;a.index=0;a.q22=0;a.q21=0;a.q1=0;a.dec_med=0;a.ps=0;a.rott=0;a.is_beat=0;a.q23=0;a.k1=0;a.q24=0;a.dec_slow=0;a.q4=0;a.q26=0;a.p2=0;a.avg=0;a.beat=0;a.p1=0;a.peak=0;a.q2=0;a.q27=0;a.q3=0;a.t0=0;a.q28=0;a.q20=0;', + frame_eqs_str: + 'a.dec_med=pow(.7,div(30,a.fps));a.dec_slow=pow(.99,div(30,a.fps));a.beat=Math.max(Math.max(a.bass,a.mid),a.treb);a.avg=a.avg*a.dec_slow+a.beat*(1-a.dec_slow);a.is_beat=above(a.beat,.2+a.avg+a.peak)*above(a.time,a.t0+.2);a.t0=a.is_beat*a.time+(1-a.is_beat)*a.t0;a.peak=a.is_beat*a.beat+(1-a.is_beat)*a.peak*a.dec_med;a.index=mod(a.index+a.is_beat,8);a.index2=mod(a.index2+a.is_beat*bnot(a.index),2);a.q20=a.avg;a.q21=a.beat;a.q22=a.peak;a.ps=.9*a.ps+.1*a.q22;a.q23=a.ps;a.q24=a.is_beat;\na.q26=a.bass_att+a.mid_att+a.treb_att;a.q27=a.index+1;a.q28=a.index2;a.k1=a.is_beat*equal(mod(a.index,2),0);a.p1=a.k1*(a.p1+1)+(1-a.k1)*a.p1;a.p2=a.dec_med*a.p2+(1-a.dec_med)*a.p1;a.rott=div(3.1416*a.p2,4);a.q1=Math.cos(a.rott);a.q2=Math.sin(a.rott);a.q3=-a.q2;a.q4=a.q1;', + pixel_eqs_str: 'a.zoom=1.05;', + warp: ' shader_body { \n vec2 uv_1;\n vec2 tmpvar_2;\n tmpvar_2 = (uv - vec2(0.5, 0.5));\n vec4 tmpvar_3;\n tmpvar_3.w = 0.0;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_blur1, uv);\n tmpvar_3.xyz = ((tmpvar_4.xyz * scale1) + bias1);\n float tmpvar_5;\n tmpvar_5 = (dot (tmpvar_3, roam_sin) * 16.0);\n mat2 tmpvar_6;\n tmpvar_6[uint(0)].x = cos(tmpvar_5);\n tmpvar_6[uint(0)].y = -(sin(tmpvar_5));\n tmpvar_6[1u].x = sin(tmpvar_5);\n tmpvar_6[1u].y = cos(tmpvar_5);\n uv_1 = ((tmpvar_2 + (\n (0.2 * dot (((tmpvar_4.xyz * scale1) + bias1), vec3(0.32, 0.49, 0.29)))\n * \n (tmpvar_2 * tmpvar_6)\n )) - 0.5);\n vec2 tmpvar_7;\n tmpvar_7 = ((uv_1 * texsize.xy) * 0.02);\n vec2 tmpvar_8;\n tmpvar_8.x = (cos((tmpvar_7.y * q1)) * sin(-(tmpvar_7.y)));\n tmpvar_8.y = (sin(tmpvar_7.x) * cos((tmpvar_7.y * q2)));\n uv_1 = (uv_1 - ((tmpvar_8 * texsize.zw) * 12.0));\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = ((texture (sampler_main, uv_1).xyz * 0.98) - 0.02);\n ret = tmpvar_9.xyz;\n }', + comp: 'vec3 xlat_mutableret1;\nvec2 xlat_mutablers;\nvec2 xlat_mutableuv1;\nfloat xlat_mutablez;\n shader_body { \n xlat_mutableuv1 = (uv - 0.5);\n xlat_mutablez = (0.2 / abs(xlat_mutableuv1.y));\n xlat_mutablers.x = (xlat_mutableuv1.x * xlat_mutablez);\n xlat_mutablers.y = ((xlat_mutablez / 2.0) + (time * 4.0));\n vec4 tmpvar_1;\n tmpvar_1 = texture (sampler_noise_hq, xlat_mutablers);\n xlat_mutableret1 = ((tmpvar_1.xyz * vec3(\n greaterThanEqual (tmpvar_1.xyz, vec3(0.0, 0.0, 0.0))\n )) - 0.6);\n float tmpvar_2;\n tmpvar_2 = clamp ((128.0 * xlat_mutableuv1.y), 0.0, 1.0);\n vec2 tmpvar_3;\n tmpvar_3 = fract(((\n (xlat_mutableuv1 * (1.0 - abs(xlat_mutableuv1.x)))\n - 0.5) - (\n (xlat_mutableret1 * 0.05)\n * tmpvar_2).xy));\n float x_4;\n x_4 = (tmpvar_3.y - 0.52);\n vec3 tmpvar_5;\n tmpvar_5 = (texture (sampler_main, tmpvar_3) + ((0.02 / \n (0.02 + sqrt((x_4 * x_4)))\n ) * slow_roam_sin)).xyz;\n xlat_mutableret1 = tmpvar_5;\n vec2 tmpvar_6;\n tmpvar_6 = (32.0 * ((\n (uv * mat2(0.6, -0.8, 0.8, 0.6))\n + \n (tmpvar_5 * 0.1)\n .xy) + (time / 64.0)));\n vec2 tmpvar_7;\n tmpvar_7 = abs((fract(tmpvar_6) - 0.5));\n vec3 tmpvar_8;\n tmpvar_8 = clamp (((0.25 / \n sqrt(dot (tmpvar_7, tmpvar_7))\n ) * vec3((texture (sampler_pw_noise_lq, \n (tmpvar_6 / 256.0)\n ).y - 0.9))), 0.0, 1.0);\n vec4 tmpvar_9;\n tmpvar_9.w = 1.0;\n tmpvar_9.xyz = (tmpvar_5 + ((\n (tmpvar_8.x * tmpvar_8.x)\n + \n ((rand_preset * (0.5 - uv.y)).xyz * vec3(0.0, 0.0, 1.0))\n ) * (1.0 - tmpvar_2)));\n ret = tmpvar_9.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 2, + gammaadj: 1.98, + decay: 0.5, + echo_zoom: 1, + echo_alpha: 0.5, + echo_orient: 3, + wave_mode: 3, + wave_thick: 1, + wrap: 0, + darken: 1, + wave_a: 100, + wave_scale: 0.282, + wave_smoothing: 0.9, + wave_mystery: 1, + warpanimspeed: 1.459, + warpscale: 2.007, + zoom: 0.9999, + warp: 0.01, + sx: 0.9999, + wave_r: 0.5, + wave_g: 0.5, + wave_b: 0.5, + ob_size: 0.05, + ob_g: 0.1, + ob_b: 1, + ob_a: 1, + ib_size: 0, + ib_r: 0, + ib_g: 0, + ib_b: 0, + mv_a: 0, + b1ed: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1, spectrum: 1, thick: 1, scaling: 0.2248 }, + init_eqs_str: 'a.ma=0;a.mx=0;a.my=0;', + frame_eqs_str: 'a.r=a.bass;a.g=a.treb;a.b=.5;', + point_eqs_str: + 'a.ma+=3.1415*above(a.bass,1)*.01*a.bass;a.ma-=3.1415*above(a.treb,1)*.01*a.treb;a.mx+=.0002*Math.cos(a.ma);a.my+=.0002*Math.sin(a.ma);a.mx=.00001b;b++)a.gmegabuf[Math.floor(a.n)]=0,a.n+=1;for(b=a.n=0;1E4>b;b++)a.megabuf[Math.floor(a.n)]=0,a.n+=1;a.trelx=0;a.trely=0;a.trelz=0;a.reg20=1;a.reg21=0;a.reg22=0;a.reg23=0;a.reg24=1;a.reg25=0;a.reg26=0;a.reg27=0;a.reg28=1;b=0;do{b+=1;var c;a.ran1=div(randint(800),100);a.ran2=div(randint(800),100);a.ran3=div(randint(800),100);a.posx=randint(5)-2;a.posy=randint(5)-2;a.posz=randint(5)-2;a.c1=Math.cos(a.ran1);\na.c2=Math.cos(a.ran2);a.c3=Math.cos(a.ran3);a.s1=Math.sin(a.ran1);a.s2=Math.sin(a.ran2);a.s3=Math.sin(a.ran3);a.reg20=a.c2*a.c1;a.reg21=a.c2*a.s1;a.reg22=-a.s2;a.reg23=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg24=a.s3*a.s2*a.s1+a.c3*a.c1;a.reg25=a.s3*a.c2;a.reg26=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg27=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg28=a.c3*a.c2;a.dist=.001;var d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;a.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,\n8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=\na.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.05;c=(.6>a.dist?1:0)*(30\nd);d=.06>a.dist?1:0}while(.00001b);', + frame_eqs_str: + 'a.wave_a=0;a.fps_=0*a.fps_+1*(.00001=a.fps?1:0)?a.fps:25+.5*(a.fps-25));a.dec_s=1-div(.06*30,a.fps_);a.beat=a.time>a.t0+3?1:0;a.t0=.00001Math.abs(a.rotz-0)?1:0)?a.beat*(randint(100)<20*a.travel?1:0)*(div(randint(10),10)-.3):bnot(a.beat*(30>randint(100)?1:0))*a.rotz;a.slow=.00001<\nMath.abs(bnot(a.slow))?a.beat*(6>randint(1E3*a.avg)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.look=.00001randint(1E3*a.speed)?1:0):bnot(a.beat*(50>randint(100)?1:0));a.lx=.00001a.dist_?1:0)*2;a.travel=.00001b;b++){a.n+=1;a.ran1=div(randint(100),100);a.ran2=div(randint(100),200)-.25;a.tx=Math.cos(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.ty=Math.sin(1.57*a.n+a.ran2)*(4>=a.n?1:0)*a.ran1;a.c1=Math.cos(a.v1);a.c2=Math.cos(a.v2+a.ty);a.c3=Math.cos(a.v3+a.tx);a.s1=Math.sin(a.v1);a.s2=Math.sin(a.v2+a.ty);a.s3=Math.sin(a.v3+a.tx);a.reg10=a.c2*a.c1;a.reg11=a.c2*a.s1;a.reg12=-a.s2;a.reg13=a.s3*a.s2*a.c1-a.c3*a.s1;a.reg14=a.s3*a.s2*\na.s1+a.c3*a.c1;a.reg15=a.s3*a.c2;a.reg16=a.c3*a.s2*a.c1+a.s3*a.s1;a.reg17=a.c3*a.s2*a.s1-a.s3*a.c1;a.reg18=a.c3*a.c2;a.reg20=a.reg30;a.reg21=a.reg31;a.reg22=a.reg32;a.reg23=a.reg33;a.reg24=a.reg34;a.reg25=a.reg35;a.reg26=a.reg36;a.reg27=a.reg37;a.reg28=a.reg38;a.q20=a.reg10*a.reg20+a.reg11*a.reg23+a.reg12*a.reg26;a.q21=a.reg10*a.reg21+a.reg11*a.reg24+a.reg12*a.reg27;a.q22=a.reg10*a.reg22+a.reg11*a.reg25+a.reg12*a.reg28;a.q23=a.reg13*a.reg20+a.reg14*a.reg23+a.reg15*a.reg26;a.q24=a.reg13*a.reg21+a.reg14*\na.reg24+a.reg15*a.reg27;a.q25=a.reg13*a.reg22+a.reg14*a.reg25+a.reg15*a.reg28;a.q26=a.reg16*a.reg20+a.reg17*a.reg23+a.reg18*a.reg26;a.q27=a.reg16*a.reg21+a.reg17*a.reg24+a.reg18*a.reg27;a.q28=a.reg16*a.reg22+a.reg17*a.reg25+a.reg18*a.reg28;a.reg20=a.q20;a.reg21=a.q21;a.reg22=a.q22;a.reg23=a.q23;a.reg24=a.q24;a.reg25=a.q25;a.reg26=a.q26;a.reg27=a.q27;a.reg28=a.q28;a.dist=.002;var c,d=0;do{d+=1;a.uvx=div(a.reg26*a.dist,a.q7);a.uvy=div(a.reg27*a.dist,a.q7);a.uvz=div(a.reg28*a.dist,a.q7);a.uvx+=a.posx;\na.uvy+=a.posy;a.uvz+=a.posz;a.uvx=8*(div(a.uvx,8)+30.5-Math.floor(div(a.uvx,8)+30.5)-.5);a.uvy=8*(div(a.uvy,8)+30.5-Math.floor(div(a.uvy,8)+30.5)-.5);a.uvz=8*(div(a.uvz,8)+30.5-Math.floor(div(a.uvz,8)+30.5)-.5);a.uvx0=a.uvx+a.q8;a.uvy0=a.uvy+a.q8;a.uvz0=a.uvz+a.q8;for(c=0;8>c;c++)a.uvx=.00001a.uvx?1:0)?-2-a.uvx:a.uvx,a.uvy=.00001a.uvy?1:0)?-2-a.uvy:a.uvy,a.uvz=.00001a.uvz?1:0)?-2-a.uvz:a.uvz,a.slen=a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz,a.uvx=2.6*(.00001a.slen?1:0)?4*a.uvx:.00001a.slen?1:0)?div(a.uvx,a.slen):a.uvx)+a.uvx0,a.uvy=2.6*(.00001a.slen?1:0)?4*a.uvy:.00001a.slen?1:0)?div(a.uvy,a.slen):a.uvy)+a.uvy0,a.uvz=2.6*(.00001a.slen?1:0)?4*a.uvz:.00001a.slen?1:0)?div(a.uvz,a.slen):a.uvz)+a.uvz0;a.len=sqrt(a.uvx*a.uvx+a.uvy*a.uvy+a.uvz*a.uvz);a.dist*=1.1;c=(.6>a.dist?1:0)*(30<\na.len?1:0)}while(.00001d);a.megabuf[Math.floor(a.n)]=a.megabuf[Math.floor(a.n)]*a.dec_s+(1-a.dec_s)*a.dist;a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5))}a.n=0;for(b=a.avg=0;5>b;b++)a.n+=1,a.avg+=Math.abs(div(a.megabuf[Math.floor(a.n)],5));a.xslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[1]-a.megabuf[3]),-3),3);a.yslope=Math.min(Math.max(div(2,a.avg)*(a.megabuf[4]-a.megabuf[2]),-3),3);a.monitor=a.avg;a.dist_=a.dist_*a.dec_s+(1-a.dec_s)*a.dist;a.q10=a.ds*a.q7;a.q14=Math.abs(a.ds)+\n2*(Math.abs(a.v1)+Math.abs(a.v2)+Math.abs(a.v3))+div(1,255)+.05*a.start;a.q19=.6+.4*Math.sin(.02*a.time+6*a.cran0);a.start*=.9;a.q11=a.v1;a.q12=a.v2;a.q13=a.v3;a.monitor=a.q16;', + pixel_eqs_str: + 'a.warp=0;a.zoom=1;a.dx=div(-a.q12,a.q16)*(1+0*pow(a.x-.5,2));a.dy=div(a.q13,a.q16)*(1+0*pow(a.y-.5,2));a.rot=a.q11;', + warp: ' shader_body { \n float dy_1;\n float dx_2;\n vec3 ret_3;\n vec2 tmpvar_4;\n tmpvar_4 = ((uv * texsize.xy) * texsize_noise_lq.zw);\n vec2 tmpvar_5;\n tmpvar_5 = (texsize.zw * 4.0);\n vec2 tmpvar_6;\n tmpvar_6.x = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).y * 0.5);\n tmpvar_6.y = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).y * 0.5);\n ret_3.y = texture (sampler_fw_main, clamp ((uv + (\n (tmpvar_6 * texsize.zw)\n * 4.0)), 0.0, 1.0)).y;\n ret_3.y = (ret_3.y + ((\n (ret_3 - ((texture (sampler_blur1, uv).xyz * scale1) + bias1))\n .y * 0.025) + -0.01));\n ret_3.y = (ret_3.y + ((texture (sampler_noise_lq, tmpvar_4).y - 0.5) * 0.02));\n dx_2 = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(1.0, 0.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).z * 0.5);\n dy_1 = (((2.0 * \n ((texture (sampler_blur1, (uv + (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv - (vec2(0.0, 1.0) * tmpvar_5))).xyz * scale1) + bias1)\n )).z * 0.5);\n vec2 tmpvar_7;\n tmpvar_7.x = dx_2;\n tmpvar_7.y = dy_1;\n ret_3.z = ((texture (sampler_main, (uv - \n ((tmpvar_7 * texsize.zw) * 4.0)\n )).z - (ret_3.y * 0.01)) + 0.004);\n ret_3.z = (ret_3.z + ((texture (sampler_noise_lq, tmpvar_4).y - 0.5) * 0.01));\n dx_2 = (((2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(1.0, 0.0)))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(-1.0, 0.0)))).xyz * scale1) + bias1)\n )).x * 0.5);\n dy_1 = (((2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(0.0, 1.0)))).xyz * scale1) + bias1)\n ) - (2.0 * \n ((texture (sampler_blur1, (uv + (tmpvar_5 * vec2(0.0, -1.0)))).xyz * scale1) + bias1)\n )).x * 0.5);\n vec2 tmpvar_8;\n tmpvar_8.x = dx_2;\n tmpvar_8.y = dy_1;\n vec2 tmpvar_9;\n tmpvar_9 = (tmpvar_8 * texsize.zw);\n vec2 domain_10;\n domain_10 = (uv - (tmpvar_9 * 2.5));\n vec4 tmpvar_11;\n tmpvar_11.w = 0.0;\n tmpvar_11.xyz = max (vec4(0.0, 0.0, 0.0, 0.0), texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(-1.0, 0.0))))).xyz;\n vec4 tmpvar_12;\n tmpvar_12.w = 0.0;\n tmpvar_12.xyz = max (tmpvar_11, texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(0.0, -1.0))))).xyz;\n vec4 tmpvar_13;\n tmpvar_13.w = 0.0;\n tmpvar_13.xyz = max (tmpvar_12, texture (sampler_fc_main, domain_10)).xyz;\n vec4 tmpvar_14;\n tmpvar_14.w = 0.0;\n tmpvar_14.xyz = max (tmpvar_13, texture (sampler_fc_main, (domain_10 + (texsize.zw * vec2(0.0, 1.0))))).xyz;\n ret_3.x = ((max (tmpvar_14, texture (sampler_fc_main, \n (domain_10 + (texsize.zw * vec2(1.0, 0.0)))\n )).x + (\n (texture (sampler_main, (uv + (tmpvar_9 * 4.0))).x - ((texture (sampler_blur1, (uv + \n (tmpvar_9 * 4.0)\n )).xyz * scale1) + bias1).x)\n * 0.206)) - 0.09);\n vec4 tmpvar_15;\n tmpvar_15.w = 1.0;\n tmpvar_15.xyz = ret_3;\n ret = tmpvar_15.xyz;\n }', + comp: 'float xlat_mutablelamp;\nvec2 xlat_mutablers0;\nvec2 xlat_mutablerss;\nvec2 xlat_mutableuv1;\n shader_body { \n vec3 tmpvar_1;\n tmpvar_1.x = q4;\n tmpvar_1.y = q5;\n tmpvar_1.z = q6;\n mat3 tmpvar_2;\n tmpvar_2[uint(0)].x = q20;\n tmpvar_2[uint(0)].y = q23;\n tmpvar_2[uint(0)].z = q26;\n tmpvar_2[1u].x = q21;\n tmpvar_2[1u].y = q24;\n tmpvar_2[1u].z = q27;\n tmpvar_2[2u].x = q22;\n tmpvar_2[2u].y = q25;\n tmpvar_2[2u].z = q28;\n vec2 tmpvar_3;\n tmpvar_3.x = q1;\n tmpvar_3.y = q2;\n vec2 uv_4;\n vec3 dots_5;\n vec3 ret_6;\n vec2 tmpvar_7;\n vec2 tmpvar_8;\n tmpvar_8 = (uv - 0.5);\n tmpvar_7 = (0.5 + (tmpvar_8 * vec2(1.1, 0.81)));\n vec2 tmpvar_9;\n tmpvar_9 = (uv - vec2(0.5, 0.5));\n uv_4 = (tmpvar_8 * aspect.xy);\n float tmpvar_10;\n float tmpvar_11;\n tmpvar_11 = (min (abs(\n (uv_4.y / uv_4.x)\n ), 1.0) / max (abs(\n (uv_4.y / uv_4.x)\n ), 1.0));\n float tmpvar_12;\n tmpvar_12 = (tmpvar_11 * tmpvar_11);\n tmpvar_12 = (((\n ((((\n ((((-0.01213232 * tmpvar_12) + 0.05368138) * tmpvar_12) - 0.1173503)\n * tmpvar_12) + 0.1938925) * tmpvar_12) - 0.3326756)\n * tmpvar_12) + 0.9999793) * tmpvar_11);\n tmpvar_12 = (tmpvar_12 + (float(\n (abs((uv_4.y / uv_4.x)) > 1.0)\n ) * (\n (tmpvar_12 * -2.0)\n + 1.570796)));\n tmpvar_10 = (tmpvar_12 * sign((uv_4.y / uv_4.x)));\n if ((abs(uv_4.x) > (1e-08 * abs(uv_4.y)))) {\n if ((uv_4.x < 0.0)) {\n if ((uv_4.y >= 0.0)) {\n tmpvar_10 += 3.141593;\n } else {\n tmpvar_10 = (tmpvar_10 - 3.141593);\n };\n };\n } else {\n tmpvar_10 = (sign(uv_4.y) * 1.570796);\n };\n xlat_mutablers0.x = ((tmpvar_10 / 3.1416) * 2.0);\n xlat_mutablers0.y = (0.02 / sqrt(dot (uv_4, uv_4)));\n vec2 tmpvar_13;\n tmpvar_13.x = xlat_mutablers0.x;\n tmpvar_13.y = (xlat_mutablers0.y + time);\n xlat_mutablerss = (tmpvar_13 * mat2(0.7, -0.7, 0.7, 0.7));\n vec4 tmpvar_14;\n tmpvar_14 = vec4(greaterThanEqual ((texture (sampler_pw_noise_lq, \n (xlat_mutablerss / 32.0)\n ) - 0.7), vec4(0.0, 0.0, 0.0, 0.0)));\n vec2 tmpvar_15;\n tmpvar_15 = abs((fract(\n (xlat_mutablerss * 8.0)\n ) - 0.5));\n vec2 tmpvar_16;\n tmpvar_16.x = (xlat_mutablers0.x * 2.0);\n tmpvar_16.y = (xlat_mutablers0.y + (time / 2.0));\n xlat_mutablerss = (tmpvar_16 * mat2(0.7, -0.7, 0.7, 0.7));\n vec4 tmpvar_17;\n tmpvar_17 = vec4(greaterThanEqual ((texture (sampler_pw_noise_lq, \n (xlat_mutablerss / 32.0)\n ) - 0.7), vec4(0.0, 0.0, 0.0, 0.0)));\n vec2 tmpvar_18;\n tmpvar_18 = abs((fract(\n (xlat_mutablerss * 8.0)\n ) - 0.5));\n xlat_mutablerss = tmpvar_18;\n dots_5 = (vec3((clamp (\n (0.04 / sqrt(dot (tmpvar_15, tmpvar_15)))\n , 0.0, 1.0) * tmpvar_14.x)) + (clamp (\n (0.04 / sqrt(dot (tmpvar_18, tmpvar_18)))\n , 0.0, 1.0) * tmpvar_17.x));\n dots_5 = (dots_5 * clamp ((0.04 / \n abs((0.01 / xlat_mutablers0.y))\n ), 0.0, 1.0));\n dots_5 = (dots_5 * (dots_5 * 2.0));\n vec2 tmpvar_19;\n tmpvar_19.x = -((tmpvar_9.y * -1024.0));\n tmpvar_19.y = (tmpvar_9.x * -1024.0);\n vec2 tmpvar_20;\n tmpvar_20.x = tmpvar_19.x;\n tmpvar_20.y = -(tmpvar_19.y);\n uv_4 = (vec2(-100.0, 100.0) * (tmpvar_20 / (\n (tmpvar_19.x * tmpvar_19.x)\n + \n (tmpvar_19.y * tmpvar_19.y)\n )).yx);\n uv_4 = (0.5 + ((\n (1.0 - abs(((\n fract((mix ((0.5 + \n ((tmpvar_7 - 0.5) * 2.0)\n ), (uv_4 + 0.5), vec2(0.5, 0.5)) * 0.5))\n * 2.0) - 1.0)))\n - 0.5) * 0.98));\n uv_4 = (((uv_4 - 0.5) * 0.9) + 0.5);\n xlat_mutableuv1 = ((uv_4 - tmpvar_3) * aspect.xy);\n float tmpvar_21;\n tmpvar_21 = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n vec3 tmpvar_22;\n tmpvar_22.xy = ((uv_4 - 0.5) * min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - \n ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2)\n .z)));\n tmpvar_22.z = min ((1.0 - texture (sampler_main, uv_4).z), (1.0 - (\n (texture (sampler_blur2, uv_4).xyz * scale2)\n + bias2).z));\n float tmpvar_23;\n tmpvar_23 = clamp ((abs(\n ((1.0 - ((texture (sampler_blur2, uv_4).xyz * scale2) + bias2).z) - clamp ((1.0 - (\n (texture (sampler_blur2, tmpvar_3).xyz * scale2)\n + bias2).z), 0.1, 0.4))\n ) + 0.2), 0.0, 1.0);\n vec3 tmpvar_24;\n tmpvar_24 = mix (texture (sampler_main, uv_4).xyz, ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1), vec3(tmpvar_23));\n float tmpvar_25;\n tmpvar_25 = clamp (((1.0 - \n exp(-(((texture (sampler_blur1, uv_4).xyz * scale1) + bias1).x))\n ) - 0.2), 0.0, 1.0);\n ret_6 = ((tmpvar_24.x * (0.2 + \n ((1.0 - tmpvar_23) * (1.0 - tmpvar_21))\n )) * (1.0 + (0.5 * \n sin((((tmpvar_22 / q7) * tmpvar_2) + tmpvar_1))\n )));\n vec3 tmpvar_26;\n tmpvar_26.xy = vec2(0.0, 1.0);\n tmpvar_26.z = (tmpvar_25 * 3.0);\n vec3 tmpvar_27;\n tmpvar_27 = mix (ret_6, tmpvar_26, vec3(tmpvar_25));\n xlat_mutablelamp = (((\n clamp ((1.0 - (4.0 * sqrt(\n dot (xlat_mutableuv1, xlat_mutableuv1)\n ))), 0.0, 1.0)\n * tmpvar_24.x) * clamp (\n (1.0 - (2.0 * mix (tmpvar_21, (1.0 - \n ((texture (sampler_blur1, uv_4).xyz * scale1) + bias1)\n .z), 0.2)))\n , 0.0, 1.0)) * 1.8);\n ret_6 = (tmpvar_27 + ((1.0 - \n dot (tmpvar_27, vec3(0.32, 0.49, 0.29))\n ) * xlat_mutablelamp));\n ret_6 = (1.0 - exp((-2.0 * ret_6)));\n ret_6 = (ret_6 + (dots_5 * (1.0 + ret_6)));\n vec4 tmpvar_28;\n tmpvar_28.w = 1.0;\n tmpvar_28.xyz = ret_6;\n ret = tmpvar_28.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 3, + wave_mode: 4, + additivewave: 1, + wave_dots: 1, + modwavealphabyvolume: 1, + wave_a: 0.331, + wave_scale: 0.898, + wave_smoothing: 0.108, + wave_mystery: 0.1, + modwavealphastart: 0.72, + modwavealphaend: 1.28, + zoom: 1.3345, + wave_r: 0, + wave_g: 0.5, + wave_b: 0.5, + wave_y: 0.54, + mv_x: 24.8, + mv_dy: 0.16, + mv_l: 1.5, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { + enabled: 1, + samples: 352, + usedots: 1, + additive: 1, + scaling: 0.03856, + smoothing: 0.2, + g: 0, + }, + init_eqs_str: 'a.t02=0;a.q1=0;a.ratio=0;a.ampl=0;a.x1=0;a.y1=0;', + frame_eqs_str: 'a.q1=a.bass_att;', + point_eqs_str: + 'a.r=Math.abs(Math.sin(div(a.frame,38)));a.g=.5*Math.abs(Math.cos(div(a.frame,45)));a.b=.5*Math.abs(Math.sin(div(a.frame,133)));a.a=.3;a.t02+=div(a.q1,10);a.ratio=Math.sin(div(a.frame,49));a.ampl=.01+.4*sqr(Math.sin(div(a.frame,18))*Math.cos(div(a.frame,123)));a.x1=div(a.r-.5,15)+.5+a.ampl*Math.sin(6.28*a.sample);a.y1=div(a.b-.5,15)+.5+a.ampl*Math.cos(6.28*a.sample);a.x=a.x1+.2*(a.ampl+a.ratio)*Math.sin(6.28*a.sample*a.ratio*7.3);a.y=a.y1+.2*(a.ampl+a.ratio)*Math.cos(37.68*a.sample);\n', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: 'a.oldshift=0;a.shift=0;a.normalframez=0;a.crash=0;a.nex=0;a.rshift=0;a.q1=0;a.zoom1=0;', + frame_eqs_str: + 'a.dx=0;a.oldshift=a.shift;a.normalframez+=1;a.shift=above(a.bass_att,1)*above(a.treb_att,.9);a.crash=Math.abs(a.oldshift-a.shift);a.nex=1*equal(a.rshift,0)+2*equal(a.rshift,1);a.rshift=.00001 0.9)) {\n ret_2.x = 0.0;\n };\n if ((ret_2.y > 0.9)) {\n ret_2.y = 0.0;\n };\n if ((ret_2.z > 0.9)) {\n ret_2.z = 0.0;\n };\n vec4 tmpvar_7;\n tmpvar_7.w = 1.0;\n tmpvar_7.xyz = ret_2;\n ret = tmpvar_7.xyz;\n }', + comp: ' shader_body { \n vec3 ret1_1;\n vec2 uv1_2;\n vec3 ret_3;\n vec4 tmpvar_4;\n tmpvar_4 = texture (sampler_main, uv);\n ret_3 = (tmpvar_4.xyz * (0.6 + (0.3 * \n sin(((uv.x * 10.0) + time))\n )));\n vec2 tmpvar_5;\n tmpvar_5.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_5.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_2 = ((0.5 * cos(\n (((uv - 0.5) * 1.5) + 1.6)\n )) - (3.0 * tmpvar_5));\n ret1_1 = ((0.3 * dot (tmpvar_4.xyz, vec3(0.32, 0.49, 0.29))) + ((\n clamp ((0.01 / sqrt(dot (uv1_2, uv1_2))), 0.0, 1.0)\n * \n mix (vec3(dot (((texture (sampler_blur2, uv).xyz * scale2) + bias2), vec3(0.32, 0.49, 0.29))), ret_3, pow (ret_3, vec3((0.05 + (mid_att * 0.03)))))\n ) * (\n (4.0 + bass)\n + \n (mid + treb_att)\n )));\n ret_3 = ret1_1;\n vec4 tmpvar_6;\n tmpvar_6.w = 1.0;\n tmpvar_6.xyz = ret1_1;\n ret = tmpvar_6.xyz;\n }', + }; + }, + function (a, e) { + a.exports = { + baseVals: { + rating: 3, + gammaadj: 1, + decay: 0.997, + echo_zoom: 0.997, + echo_orient: 1, + wave_thick: 1, + wave_brighten: 0, + darken: 1, + wave_a: 0.001, + wave_scale: 0.01, + wave_smoothing: 0.27, + wave_mystery: -0.38, + modwavealphastart: 0.71, + modwavealphaend: 1.3, + warpscale: 1.331, + zoom: 0.99951, + warp: 0.01, + ob_size: 0.5, + ob_r: 0.01, + ib_size: 0.26, + ib_r: 1, + ib_g: 1, + ib_b: 1, + mv_x: 64, + mv_y: 48, + mv_l: 0.85, + mv_r: 0.5, + mv_g: 0.5, + mv_b: 0.5, + mv_a: 0, + }, + shapes: [ + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + waves: [ + { + baseVals: { enabled: 1 }, + init_eqs_str: '', + frame_eqs_str: '', + point_eqs_str: + 'a.x=.5+.2*a.bass*Math.sin(20*a.sample*a.time*a.treb);a.y=.5+.2*a.bass*Math.cos(20*a.sample*a.time*a.treb);a.r=1+.5*Math.sin(.1*a.sample+10*a.time*a.bass);a.g=1+.5*Math.sin(2*a.sample+50*a.time*a.treb);a.b=1+.5*Math.sin(5*a.sample+20*a.time*a.mid);a.a=a.r;', + }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + { baseVals: { enabled: 0 } }, + ], + init_eqs_str: '', + frame_eqs_str: 'a.warp=0;a.decay=.92;', + pixel_eqs_str: + 'a.zoom+=.03*a.bass_att*a.bass_att*a.rad;a.rot+=a.rad*bitand(-2.5,5*Math.cos(a.time))*.01;', + warp: ' shader_body { \n vec4 tmpvar_1;\n tmpvar_1.w = 1.0;\n tmpvar_1.xyz = texture (sampler_main, uv).xyz;\n ret = tmpvar_1.xyz;\n }', + comp: ' shader_body { \n vec2 uv1_1;\n vec3 ret_2;\n vec3 tmpvar_3;\n tmpvar_3 = texture (sampler_main, uv).xyz;\n vec2 tmpvar_4;\n tmpvar_4.x = (texture (sampler_main, (uv - vec2(0.001, 0.0))).xyz - texture (sampler_main, (uv + vec2(0.001, 0.0))).xyz).x;\n tmpvar_4.y = (texture (sampler_main, (uv - vec2(0.0, 0.001))).xyz - texture (sampler_main, (uv + vec2(0.0, 0.001))).xyz).x;\n uv1_1 = ((0.5 * cos(\n (((uv - 0.5) * 1.5) + 1.6)\n )) - (3.0 * tmpvar_4));\n ret_2 = (0.8 * ((0.3 * \n dot (tmpvar_3, vec3(0.32, 0.49, 0.29))\n ) + (\n (clamp ((0.01 / sqrt(\n dot (uv1_1, uv1_1)\n )), 0.0, 1.0) * tmpvar_3)\n * \n ((4.0 + bass) + (mid + treb_att))\n )));\n ret_2 = (ret_2 * 0.77);\n vec4 tmpvar_5;\n tmpvar_5.w = 1.0;\n tmpvar_5.xyz = ret_2;\n ret = tmpvar_5.xyz;\n }', + }; + }, + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + function (a, e, t) { + 'use strict'; + Object.defineProperty(e, '__esModule', { value: !0 }); + var r = _(t(6)), + n = _(t(7)); + function _(a) { + return a && a.__esModule ? a : { default: a }; + } + var s = {}; + ((s['$$$ Royal - Mashup (197)'] = t(35)), + (s['$$$ Royal - Mashup (220)'] = t(36)), + (s['$$$ Royal - Mashup (431)'] = t(37)), + (s[ + '_Aderrasi - Wanderer in Curved Space - mash0000 - faclempt kibitzing meshuggana schmaltz (Geiss color mix)' + ] = t(38)), + (s['_Geiss - Artifact 01'] = t(39)), + (s['_Geiss - Desert Rose 2'] = t(40)), + (s['_Geiss - untitled'] = t(41)), + (s._Mig_049 = t(42)), + (s._Mig_085 = t(43)), + (s['_Rovastar + Geiss - Hurricane Nightmare (Posterize Mix)'] = t(44)), + (s['Aderrasi + Geiss - Airhandler (Kali Mix) - Canvas Mix'] = t(45)), + (s['Aderrasi - Potion of Spirits'] = t(20)), + (s['Aderrasi - Songflower (Moss Posy)'] = t(21)), + (s['Aderrasi - Storm of the Eye (Thunder) - mash0000 - quasi pseudo meta concentrics'] = t(46)), + (s[ + 'An AdamFX n Martin Infusion 2 flexi - Why The Sky Looks Diffrent Today - AdamFx n Martin Infusion - Tack Tile Disfunction B' + ] = t(47)), + (s['cope + martin - mother-of-pearl'] = t(48)), + (s['Cope - The Neverending Explosion of Red Liquid Fire'] = t(49)), + (s['Eo.S. + Phat - cubetrace - v2'] = t(22)), + (s['Eo.S. + Zylot - skylight (Stained Glass Majesty mix)'] = t(23)), + (s['Eo.S. - glowsticks v2 05 and proton lights (+Krashβ€²s beat code) _Phat_remix02b'] = t(24)), + (s['fiShbRaiN + Flexi - witchcraft 2.0'] = t(50)), + (s['flexi + amandio c - organic [random mashup]'] = t(51)), + (s['flexi + amandio c - organic12-3d-2.milk'] = t(52)), + (s['Flexi + amandio c - piercing 05 - Kopie (2) - Kopie'] = t(53)), + (s['flexi + fishbrain - neon mindblob grafitti'] = t(54)), + (s['flexi + geiss - pogo cubes vs. tokamak vs. game of life [stahls jelly 4.5 finish]'] = t(55)), + (s['Flexi + Martin - astral projection'] = t(56)), + (s['Flexi + Martin - cascading decay swing'] = t(57)), + (s['Flexi + stahlregen - jelly showoff parade'] = t(58)), + (s['Flexi - alien fish pond'] = t(59)), + (s['Flexi - area 51'] = t(60)), + (s['flexi - bouncing balls [double mindblob neon mix]'] = t(61)), + (s['Flexi - infused with the spiral'] = t(62)), + (s['Flexi - mindblob [shiny mix]'] = t(63)), + (s['Flexi - mindblob mix'] = t(64)), + (s['flexi - mom, why the sky looks different today'] = t(65)), + (s['flexi - patternton, district of media, capitol of the united abstractions of fractopia'] = t(66)), + (s['Flexi - predator-prey-spirals'] = t(67)), + (s['Flexi - smashing fractals [acid etching mix]'] = t(68)), + (s['flexi - swing out on the spiral'] = t(69)), + (s['Flexi - truly soft piece of software - this is generic texturing (Jelly) '] = t(70)), + (s['flexi - what is the matrix'] = t(71)), + (s['Flexi, fishbrain, Geiss + Martin - tokamak witchery'] = t(72)), + (s['Flexi, martin + geiss - dedicated to the sherwin maxawow'] = t(73)), + (s['Fumbling_Foo & Flexi, Martin, Orb, Unchained - Star Nova v7b'] = t(74)), + (s['Geiss + Flexi + Martin - disconnected'] = t(75)), + (s['Geiss - Cauldron - painterly 2 (saturation remix)'] = t(76)), + (s['Geiss - Reaction Diffusion 2'] = t(77)), + (s['Geiss - Spiral Artifact'] = t(78)), + (s['Geiss - Thumb Drum'] = t(79)), + (s['Geiss, Flexi + Stahlregen - Thumbdrum Tokamak [crossfiring aftermath jelly mashup]'] = t(80)), + (s['Goody - The Wild Vort'] = t(81)), + (s['high-altitude basket unraveling - singh grooves nitrogen argon nz+'] = t(82)), + (s['Idiot - Star Of Annon'] = t(25)), + (s['Krash + Illusion - Spiral Movement'] = t(26)), + (s[ + 'martin + flexi - diamond cutter [prismaticvortex.com] - camille - i wish i wish i wish i was constrained' + ] = t(83)), + (s['Martin - acid wiring'] = t(84)), + (s['martin - angel flight'] = t(85)), + (s['martin - another kind of groove'] = t(86)), + (s['martin - bombyx mori'] = t(87)), + (s['martin - castle in the air'] = t(88)), + (s['martin - chain breaker'] = t(89)), + (s['Martin - charisma'] = t(90)), + (s['martin - disco mix 4'] = t(91)), + (s['martin - extreme heat'] = t(92)), + (s['martin - frosty caves 2'] = t(93)), + (s['martin - fruit machine'] = t(94)), + (s['martin - ghost city'] = t(95)), + (s['martin - glass corridor'] = t(96)), + (s['martin - infinity (2010 update)'] = t(27)), + (s['Martin - liquid arrows'] = t(97)), + (s['martin - mandelbox explorer - high speed demo version'] = t(98)), + (s['martin - mucus cervix'] = t(99)), + (s['Martin - QBikal - Surface Turbulence IIb'] = t(100)), + (s['martin - reflections on black tiles'] = t(101)), + (s['martin - stormy sea (2010 update)'] = t(102)), + (s['martin - The Bridge of Khazad-Dum'] = t(103)), + (s['martin - witchcraft reloaded'] = t(104)), + (s['martin [shadow harlequins shape code] - fata morgana'] = t(105)), + (s['martin, flexi, fishbrain + sto - enterstate [random mashup]'] = t(106)), + (s['Milk Artist At our Best - FED - SlowFast Ft AdamFX n Martin - HD CosmoFX'] = t(107)), + (s['ORB - Waaa'] = t(108)), + (s['Phat+fiShbRaiN+Eo.S_Mandala_Chasers_remix'] = t(28)), + (s['Rovastar + Loadus + Geiss - FractalDrop (Triple Mix)'] = t(109)), + (s['Rovastar - Oozing Resistance'] = t(29)), + (s['sawtooth grin roam'] = t(110)), + (s['shifter - dark tides bdrv mix 2'] = t(111)), + (s['suksma - heretical crosscut playpen'] = t(112)), + (s[ + 'suksma - Rovastar - Sunflower Passion (Enlightment Mix)_Phat_edit + flexi und martin shaders - circumflex in character classes in regular expression' + ] = t(113)), + (s['suksma - uninitialized variabowl (hydroponic chronic)'] = t(114)), + (s['suksma - vector exp 1 - couldnβ€²t not'] = t(115)), + (s["TonyMilkdrop - Leonardo Da Vinci's Balloon [Flexi - merry-go-round + techstyle]"] = t(116)), + (s["TonyMilkdrop - Magellan's Nebula [Flexi - you enter first + multiverse]"] = t(117)), + (s['Unchained & Rovastar - Wormhole Pillars (Hall of Shadows mix)'] = t(30)), + (s['Unchained - Rewop'] = t(31)), + (s['Unchained - Unified Drag 2'] = t(32)), + (s['yin - 191 - Temporal singularities'] = t(33)), + (s['Zylot - Paint Spill (Music Reactive Paint Mix)'] = t(118)), + (s['Zylot - Star Ornament'] = t(34)), + (s['Zylot - True Visionary (Final Mix)'] = t(119))); + var v = (function () { + function a() { + (0, r.default)(this, a); + } + return ( + (0, n.default)(a, null, [ + { + key: 'getPresets', + value: function () { + return s; + }, + }, + ]), + a + ); + })(); + ((e.default = v), (a.exports = v)); + }, + ]); +}); diff --git a/public/manifest.json b/public/manifest.json index af1e1c990..7a5b79028 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -10,22 +10,46 @@ "orientation": "portrait-primary", "icons": [ { - "src": "assets/appicon.png", - "sizes": "192x192", + "src": "assets/icons/icon-48.webp", "type": "image/png", - "purpose": "any" + "sizes": "48x48", + "purpose": "any maskable" }, { - "src": "assets/appicon.png", - "sizes": "512x512", + "src": "assets/icons/icon-72.webp", "type": "image/png", - "purpose": "any" + "sizes": "72x72", + "purpose": "any maskable" }, { - "src": "assets/appicon.png", - "sizes": "512x512", + "src": "assets/icons/icon-96.webp", + "type": "image/png", + "sizes": "96x96", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-128.webp", + "type": "image/png", + "sizes": "128x128", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-192.webp", "type": "image/png", - "purpose": "maskable" + "sizes": "192x192", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-256.webp", + "type": "image/png", + "sizes": "256x256", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-512.webp", + "type": "image/png", + "sizes": "512x512", + "purpose": "any maskable" } ], "categories": ["music", "entertainment"], diff --git a/stream-stub.js b/stream-stub.js new file mode 100644 index 000000000..f5265c0ac --- /dev/null +++ b/stream-stub.js @@ -0,0 +1 @@ +export function Stream() {} diff --git a/styles.css b/styles.css index 611a32b07..fcf503bc0 100644 --- a/styles.css +++ b/styles.css @@ -1075,7 +1075,7 @@ ul { /* Floating bar overrides */ width: calc(96% - 190px) !important; left: calc(190px + 2%); - bottom: 15px !important; + bottom: max(15px, env(safe-area-inset-bottom)) !important; border-radius: var(--radius); /* Standardized radius */ @@ -1264,12 +1264,38 @@ ul { .main-header { display: flex; - justify-content: center; + justify-content: flex-start; align-items: center; margin-bottom: var(--spacing-xl); gap: var(--spacing-md); position: relative; z-index: 1000; + width: 100%; +} + +.header-account-control { + position: relative; + flex-shrink: 0; + margin-left: auto; +} + +#header-account-dropdown { + left: auto; + right: 0; +} + +#header-account-btn { + display: flex; + align-items: center; + justify-content: center; +} + +.header-account-icon-wrap { + display: inline-flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; } .navigation-controls { @@ -1326,8 +1352,10 @@ ul { } .search-bar { - width: 80%; + width: auto; max-width: 100%; + min-width: 0; + flex: 1; } .search-bar input { @@ -1634,6 +1662,13 @@ input[type='search']::-webkit-search-cancel-button { gap: var(--spacing-xs); margin-bottom: var(--spacing-lg); border-bottom: 1px solid var(--border); + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; +} + +.search-tabs::-webkit-scrollbar { + display: none; } .search-tab { @@ -1645,6 +1680,8 @@ input[type='search']::-webkit-search-cancel-button { font-size: 1rem; font-weight: 500; border-bottom: 2px solid transparent; + white-space: nowrap; + flex-shrink: 0; /* Keep layout stable */ border-radius: var(--radius-sm) var(--radius-sm) 0 0; @@ -1733,6 +1770,14 @@ input[type='search']::-webkit-search-cancel-button { animation: fade-in-slide-up 0.4s var(--ease-out-back); } +/* Prevent settings tab content from overflowing on small displays (fixes #313) */ +.settings-tab-content { + max-width: 100%; + min-width: 0; + overflow-x: auto; + overflow-y: visible; +} + .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); @@ -1974,6 +2019,24 @@ input[type='search']::-webkit-search-cancel-button { line-height: 1; } +.quality-atmos { + border: 1px solid var(--secondary); + color: var(--muted-foreground); + padding: 0.15rem 0.3rem; + border-radius: var(--radius-xs); + margin-left: 0.5rem; + vertical-align: middle; + line-height: 1; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.quality-atmos svg { + height: 0.6rem; + width: auto; +} + .track-list { display: flex; flex-direction: column; @@ -1988,6 +2051,62 @@ input[type='search']::-webkit-search-cancel-button { gap: 2px var(--spacing-xl); } +#artist-detail-in-library { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(580px, 1fr)); + gap: 2px var(--spacing-xl); +} + +#artist-detail-in-library[hidden] { + display: none; +} + +.library-source { + color: var(--muted-foreground); + font-size: inherit; + display: flex; + align-items: center; + min-width: 0; + flex-shrink: 1; + overflow: hidden; + cursor: pointer; +} + +.library-artist-flex { + display: flex; + align-items: center; + gap: 0.35em; + min-width: 0; +} + +.library-artist-name { + flex-shrink: 0; + white-space: nowrap; +} + +.library-year { + flex-shrink: 0; + white-space: nowrap; +} + +.library-source-label { + flex-shrink: 0; + white-space: nowrap; +} + +.library-source-link { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; + transition: color var(--transition); +} + +.library-source:hover .library-source-link { + color: var(--highlight); + text-decoration: underline; +} + #playlist-detail-recommended .track-item { grid-template-columns: 40px 1fr 32px auto; } @@ -1995,6 +2114,7 @@ input[type='search']::-webkit-search-cancel-button { @media (max-width: 1100px) { #home-recommended-songs, #artist-detail-tracks, + #artist-detail-in-library, #playlist-detail-recommended { grid-template-columns: 1fr; } @@ -2091,6 +2211,7 @@ input[type='search']::-webkit-search-cancel-button { transform var(--transition-fast); cursor: pointer; border: 1px solid transparent; + position: relative; } .track-item:hover { @@ -2135,6 +2256,93 @@ input[type='search']::-webkit-search-cancel-button { pointer-events: auto; } +.track-checkbox { + display: none; + width: 18px; + height: 18px; + cursor: pointer; + color: var(--muted-foreground); + flex-shrink: 0; + transition: color var(--transition-fast); + position: absolute; + left: 8px; + z-index: 1; +} + +.multi-select-mode .track-checkbox, +body.multi-select-mode .track-checkbox { + display: flex !important; + align-items: center; + justify-content: center; +} + +.track-checkbox:hover { + color: var(--foreground); +} + +.track-checkbox.checked { + color: var(--primary); +} + +.track-item.selected { + background-color: rgb(var(--highlight-rgb), 0.1); +} + +body.multi-select-mode .track-item { + cursor: default; + padding-left: 36px; +} + +body.multi-select-mode .track-item:hover { + transform: none; +} + +.selection-bar { + display: none; + position: fixed; + bottom: 100px; + left: 50%; + transform: translateX(-50%); + background: var(--primary); + color: var(--primary-foreground); + padding: 12px 20px; + border-radius: 24px; + font-size: 0.9rem; + font-weight: 500; + z-index: 1000; + box-shadow: 0 4px 20px rgb(0, 0, 0, 0.3); + gap: 12px; + align-items: center; +} + +.selection-bar.visible { + display: flex; +} + +.selection-bar .selection-count { + color: var(--primary-foreground); +} + +.selection-bar .selection-actions { + display: flex; + gap: 8px; +} + +.selection-bar button { + background: transparent; + border: 1px solid var(--primary-foreground); + color: var(--primary-foreground); + padding: 6px 12px; + border-radius: 16px; + cursor: pointer; + font-size: 0.85rem; + transition: background var(--transition-fast); +} + +.selection-bar button:hover { + background: rgb(255, 255, 255, 0.2); +} + .track-number { color: var(--muted-foreground); text-align: center; @@ -2180,6 +2388,40 @@ input[type='search']::-webkit-search-cancel-button { text-overflow: ellipsis; } +.track-item--inline-like { + grid-template-columns: 40px 1fr auto 3.25rem auto; +} + +.track-item-inline-like { + display: flex; + align-items: center; + justify-content: center; +} + +.track-row-like-btn { + display: flex; + align-items: center; + justify-content: center; + padding: 0.25rem; + background: transparent; + border: none; + color: var(--muted-foreground); + cursor: pointer; + border-radius: var(--radius-sm); + transition: + color var(--transition-fast), + transform var(--transition-fast); +} + +.track-row-like-btn:hover { + color: var(--foreground); + transform: scale(1.08); +} + +.track-row-like-btn.active { + color: #ef4444; +} + .track-item-duration { color: var(--muted-foreground); justify-self: flex-end; @@ -2312,7 +2554,9 @@ input[type='search']::-webkit-search-cancel-button { align-items: center; gap: 1rem; flex-wrap: wrap; - overflow-wrap: break-word; + overflow-wrap: anywhere; + word-break: normal; + min-width: 0; } .detail-header-info .title.long-title { @@ -2571,6 +2815,9 @@ input[type='search']::-webkit-search-cancel-button { .settings-list { max-width: 800px; + width: 100%; + min-width: 0; + box-sizing: border-box; } .settings-group { @@ -2615,6 +2862,7 @@ input[type='search']::-webkit-search-cancel-button { padding: var(--spacing-lg) 0; border-bottom: 1px solid var(--border); gap: var(--spacing-lg); + min-width: 0; } .setting-item.sidebar-setting-item { @@ -2654,6 +2902,7 @@ input[type='search']::-webkit-search-cancel-button { .setting-item .info { display: flex; flex-direction: column; + min-width: 0; } .setting-item .label { @@ -2665,6 +2914,15 @@ input[type='search']::-webkit-search-cancel-button { color: var(--muted-foreground); } +.setting-item .info.setting-details { + width: 100%; + display: block; +} + +.setting-item .info.setting-details .description { + font-size: 0.8rem; +} + .setting-item select, .setting-item input[type='number'] { background-color: var(--input); @@ -3641,7 +3899,8 @@ input:checked + .slider::before { /* Use a CSS variable for the image so we can set it in JS */ --bg-image: none; - padding-bottom: 0; + /* Reserve space above taskbar / system UI so volume controls stay visible (fixes #322) */ + padding-bottom: max(env(safe-area-inset-bottom), 1.5rem); } #fullscreen-cover-overlay::before { @@ -4863,10 +5122,6 @@ input:checked + .slider::before { margin-bottom: 1rem; } -.shortcuts-list { - /* list scrolls with modal */ -} - .customize-shortcut-item { display: flex; justify-content: space-between; @@ -4976,9 +5231,10 @@ input:checked + .slider::before { gap: 2px; } -#playlist-detail-tracklist .track-list-header { +#playlist-detail-tracklist .track-list-header, +#mix-detail-tracklist .track-list-header { display: grid; - grid-template-columns: 40px 1fr 80px auto; + grid-template-columns: 40px 1fr 3.25rem 80px auto; align-items: center; gap: var(--spacing-md); padding: var(--spacing-sm); @@ -4988,7 +5244,8 @@ input:checked + .slider::before { margin-bottom: var(--spacing-xs); } -#playlist-detail-tracklist .track-list-header .duration-header { +#playlist-detail-tracklist .track-list-header .duration-header, +#mix-detail-tracklist .track-list-header .duration-header { justify-self: flex-end; } @@ -5003,6 +5260,15 @@ input:checked + .slider::before { .sidebar { padding-top: max(var(--spacing-md), env(safe-area-inset-top)); } + + .sidebar { + padding-bottom: env(safe-area-inset-bottom); + } + + .side-panel { + padding-top: env(safe-area-inset-top); + padding-bottom: env(safe-area-inset-bottom); + } } /* Side Panels (Lyrics & Queue) */ @@ -5011,8 +5277,8 @@ input:checked + .slider::before { right: 0; top: 0; bottom: 0; - width: 600px; - max-width: 50vw; + width: var(--side-panel-width, 600px); + max-width: 90vw; background: var(--card); border-left: 1px solid var(--border); z-index: 2050; @@ -5023,6 +5289,51 @@ input:checked + .slider::before { transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease; box-shadow: none; + container-type: inline-size; + container-name: sidepanel; +} + +@container sidepanel (min-width: 500px) { + .panel-content am-lyrics { + --lyplus-font-size-base: 36px; + } +} + +@container sidepanel (min-width: 700px) { + .panel-content am-lyrics { + --lyplus-font-size-base: 42px; + } +} + +@container sidepanel (min-width: 900px) { + .panel-content am-lyrics { + --lyplus-font-size-base: 52px; + --lyplus-padding-line: 16px; + } +} + +@container sidepanel (min-width: 1100px) { + .panel-content am-lyrics { + --lyplus-font-size-base: 64px; + --lyplus-padding-line: 24px; + } +} + +.side-panel-resizer { + position: absolute; + left: -3px; + top: 0; + bottom: 0; + width: 6px; + cursor: ew-resize; + z-index: 10; + background: transparent; + transition: background-color 0.2s ease; +} + +.side-panel-resizer:hover, +.side-panel-resizer:active { + background-color: var(--brand); } .side-panel.active { @@ -5049,6 +5360,7 @@ input:checked + .slider::before { margin: 0; font-size: 1.25rem; font-weight: 600; + padding-left: 0.5rem; } .panel-controls { @@ -5393,30 +5705,37 @@ img[src=''] { .fullscreen-main-view { flex: 1; + min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 6rem 2rem 2rem; + overflow-y: auto; transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); } +#fullscreen-cover-overlay.is-video-mode .fullscreen-cover-content { + align-items: stretch; +} + #fullscreen-cover-overlay.is-video-mode .fullscreen-main-view { justify-content: flex-end; - align-items: flex-start; - padding: 2rem 2rem 6rem; + align-items: center; + width: 100%; + padding: 2rem 2rem max(1.5rem, env(safe-area-inset-bottom)); pointer-events: none; background: linear-gradient(to top, rgb(0, 0, 0, 0.6) 0%, rgb(0, 0, 0, 0.2) 15%, transparent 40%); } #fullscreen-cover-overlay.is-video-mode .fullscreen-track-info { - text-align: left; + text-align: center; background: none !important; backdrop-filter: none !important; border: none !important; box-shadow: none !important; padding: 0 !important; - max-width: 40%; + max-width: min(500px, 90vw); margin: 0; pointer-events: auto; } @@ -5435,12 +5754,13 @@ img[src=''] { } #fullscreen-cover-overlay.is-video-mode .fullscreen-controls { - position: absolute; - bottom: 1.5rem; - left: 2rem; - right: 2rem; + position: relative; + bottom: auto; + left: auto; + right: auto; + width: 100%; max-width: 500px; - margin: 0 auto; + margin: 0.75rem auto 0; background: transparent; backdrop-filter: none; padding: 0.6rem 1rem; @@ -5633,20 +5953,203 @@ img[src=''] { max-width: 500px; } -.modal-list { - margin: 1rem 0; - max-height: 200px; - overflow-y: auto; +.email-auth-modal-content { + padding: 1.5rem; } -.modal-option { - padding: 0.75rem; - cursor: pointer; - border-bottom: 1px solid var(--border); - transition: background 0.2s ease; +.email-auth-modal-header { display: flex; + align-items: flex-start; justify-content: space-between; - align-items: center; + gap: 1rem; + margin-bottom: 1.25rem; +} + +.email-auth-modal-header h3 { + margin: 0; + font-size: 1.1rem; + font-weight: 600; +} + +.email-auth-modal-close { + flex-shrink: 0; +} + +.email-auth-input { + width: 100%; + margin-bottom: 0.65rem; +} + +.email-auth-password-block { + margin-bottom: 0.65rem; +} + +.email-auth-password-block .email-auth-input { + margin-bottom: 0; +} + +.email-auth-actions { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-top: 1.25rem; +} + +.email-auth-actions .email-auth-submit { + width: 100%; + min-height: 2.75rem; + padding: 0.75rem 1.5rem; + border-radius: var(--radius-md); + font-size: 0.95rem; + font-weight: 600; + box-sizing: border-box; +} + +.email-auth-actions .btn-primary.email-auth-submit { + border: 1px solid var(--primary); +} + +.email-auth-actions .btn-secondary.email-auth-submit { + border: 1px solid var(--border); + background-color: var(--secondary); + color: var(--foreground); +} + +.email-auth-forgot-link { + display: block; + width: fit-content; + max-width: 100%; + margin-top: 0.35rem; + margin-left: 0; + padding: 0; + background: none; + border: none; + color: var(--muted-foreground); + font-size: 0.8125rem; + text-align: left; + text-decoration: underline; + cursor: pointer; +} + +.email-auth-forgot-link:hover { + color: var(--foreground); +} + +#page-library .library-header { + margin-bottom: var(--spacing-xl); +} + +#page-library .library-header h2 { + margin: 0; +} + +#page-library #my-playlists-container { + margin-bottom: var(--spacing-lg); +} + +#page-library #my-playlists-container .library-create-dashed-card { + order: 1; +} + +#page-library .library-create-dashed-card { + display: block; + width: 100%; + min-width: 0; + padding: var(--spacing-md); + margin: 0; + text-align: left; + font: inherit; + color: inherit; + cursor: pointer; + border: 1px solid transparent; + background-color: var(--card); + -webkit-tap-highlight-color: transparent; +} + +#page-library .library-create-dashed-art { + position: relative; + margin-bottom: var(--spacing-md); + border-radius: var(--radius); + overflow: hidden; + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + border: 2px dashed var(--border); + background: var(--secondary); + box-shadow: var(--shadow-md); + transition: + border-color var(--transition-fast), + box-shadow var(--transition-normal); +} + +#page-library .library-create-dashed-card:hover .library-create-dashed-art { + border-color: var(--highlight); + box-shadow: var(--shadow-xl); +} + +#page-library .library-create-dashed-card .card-info { + padding: 0; +} + +#page-library .library-create-dashed-card .card-title { + margin-bottom: 0; +} + +.library-liked-tracks-toolbar { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); +} + +.library-liked-search.track-list-search-container { + width: 100%; +} + +.library-liked-tracks-toolbar-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; +} + +.library-liked-tracks-toolbar-actions .btn-secondary { + display: flex; +} + +.library-liked-view-btn.active { + color: var(--highlight); + background: rgb(var(--highlight-rgb) / 0.12); +} + +@media (min-width: 720px) { + .library-liked-tracks-toolbar { + flex-direction: row; + align-items: center; + } + + .library-liked-search.track-list-search-container { + flex: 1; + min-width: 200px; + max-width: 420px; + } +} + +.modal-list { + margin: 1rem 0; + max-height: 200px; + overflow-y: auto; +} + +.modal-option { + padding: 0.75rem; + cursor: pointer; + border-bottom: 1px solid var(--border); + transition: background 0.2s ease; + display: flex; + justify-content: space-between; + align-items: center; } .modal-option:hover { @@ -5876,6 +6379,8 @@ img[src=''] { border-top: 1px solid var(--border); display: flex; justify-content: flex-end; + gap: 0.75rem; + flex-wrap: wrap; } .missing-tracks-actions .btn-secondary { @@ -6057,11 +6562,14 @@ img[src=''] { padding: var(--spacing-md); grid-area: main; overflow-y: visible; + overflow-x: hidden; + min-width: 0; } .main-header { grid-area: header; margin-bottom: var(--spacing-md); + padding-top: env(safe-area-inset-top); } .sidebar { @@ -6091,6 +6599,7 @@ img[src=''] { .search-bar { max-width: none; + width: auto; } .content-section { @@ -6118,7 +6627,7 @@ img[src=''] { flex-wrap: wrap; } - #page-library .library-header button { + #page-library .library-create-dashed-card { margin: 0 !important; } @@ -6312,6 +6821,10 @@ img[src=''] { padding: var(--spacing-sm); } + .track-item.track-item--inline-like { + grid-template-columns: 36px minmax(0, 1fr) auto minmax(2.5rem, auto) auto; + } + .track-item-info { gap: var(--spacing-sm); min-width: 0; @@ -6387,6 +6900,10 @@ img[src=''] { bottom: 0; } + .side-panel-resizer { + display: none; + } + .panel-content { padding-bottom: calc(var(--player-bar-height-mobile) + 2rem); } @@ -6513,11 +7030,8 @@ img[src=''] { margin-bottom: var(--spacing-sm); } - #page-library .library-header button { + #page-library .library-create-dashed-card { margin: 0 !important; - flex: 1; - min-width: auto; - white-space: nowrap; } .detail-header-info .title { @@ -6578,6 +7092,10 @@ img[src=''] { padding: var(--spacing-xs); } + .track-item.track-item--inline-like { + grid-template-columns: 32px minmax(0, 1fr) auto minmax(2.25rem, auto) auto; + } + .track-number { width: 32px; } @@ -6712,6 +7230,8 @@ img[src=''] { .main-content { padding: var(--spacing-sm); grid-area: main; + overflow-x: hidden; + min-width: 0; } .progress-bar:not(.waveform-loaded), @@ -6742,6 +7262,10 @@ img[src=''] { grid-template-columns: 32px 1fr 32px auto; } + .track-item.track-item--inline-like { + grid-template-columns: 32px minmax(0, 1fr) auto minmax(2.25rem, auto) auto; + } + .player-controls .buttons button { min-height: 36px; min-width: 36px; @@ -7591,7 +8115,7 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { /* EQ Response Curve Canvas */ .eq-response-canvas { - position: fixed; + position: absolute; top: var(--spacing-md); left: 4px; width: calc(100% - 8px); @@ -8211,69 +8735,298 @@ body:has(#side-panel.active) #close-fullscreen-cover-btn { #command-palette-overlay { position: fixed; inset: 0; - background: rgb(0, 0, 0, 0.5); - backdrop-filter: blur(4px); + background: rgb(0 0 0 / 60%); + backdrop-filter: blur(8px); z-index: 10000; display: flex; justify-content: center; align-items: flex-start; - padding-top: 10vh; - animation: fade-in 0.2s ease-out; + padding-top: min(10vh, 120px); + animation: cmdk-overlay-in 150ms ease-out; +} + +@keyframes cmdk-overlay-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes cmdk-scale-in { + from { + opacity: 0; + transform: scale(0.96); + } + + to { + opacity: 1; + transform: scale(1); + } } .command-palette { width: 100%; - max-width: 600px; + max-width: 640px; + margin: 0 1rem; background: var(--card); border: 1px solid var(--border); border-radius: 16px; - box-shadow: var(--shadow-2xl); + box-shadow: + 0 16px 70px rgb(0 0 0 / 50%), + 0 0 0 1px rgb(255 255 255 / 5%) inset; display: flex; flex-direction: column; overflow: hidden; - max-height: 60vh; + max-height: min(60vh, 480px); + animation: cmdk-scale-in 150ms ease-out; } .command-palette-header { - padding: 1.25rem 1.5rem; + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; border-bottom: 1px solid var(--border); } +.command-palette-search-icon { + flex-shrink: 0; + color: var(--muted-foreground); +} + #command-palette-input { - width: 100%; + flex: 1; + min-width: 0; background: transparent; border: none; - font-size: 1.2rem; - font-weight: 500; + font-size: 1rem; + font-weight: 400; color: var(--foreground); outline: none; } +#command-palette-input::placeholder { + color: var(--muted-foreground); +} + +.command-palette-kbd { + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 2px 6px; + font-size: 11px; + font-family: inherit; + font-weight: 500; + color: var(--muted-foreground); + background: var(--secondary); + border: 1px solid var(--border); + border-radius: 6px; + line-height: 1.4; +} + .command-palette-results { + flex: 1; overflow-y: auto; - padding: 0.5rem; + overscroll-behavior: contain; + padding: 6px 8px; } -.command-result-item { - padding: 0.75rem 1rem; - border-radius: var(--radius); - cursor: pointer; +.cmdk-group + .cmdk-group { + margin-top: 4px; +} + +.cmdk-group-heading { + padding: 6px 10px 4px; + font-size: 11px; + font-weight: 600; + color: var(--muted-foreground); + text-transform: uppercase; + letter-spacing: 0.04em; + user-select: none; +} + +.cmdk-item { display: flex; - justify-content: space-between; align-items: center; + gap: 10px; + padding: 8px 10px; + border-radius: var(--radius, 8px); + cursor: pointer; + font-size: 0.875rem; color: var(--foreground); + transition: background 80ms ease; + user-select: none; + position: relative; } -.command-result-item:hover, -.command-result-item.selected { +.cmdk-item:hover { background: var(--secondary); } -.command-result-desc { - font-size: 0.85rem; +.cmdk-item[data-selected='true'] { + background: var(--secondary); +} + +.cmdk-item-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + min-width: 20px; + min-height: 20px; color: var(--muted-foreground); } +/* stylelint-disable-next-line no-descending-specificity */ +.cmdk-item-icon img { + width: 28px; + height: 28px; + border-radius: 4px; + object-fit: cover; + aspect-ratio: 1 / 1; +} + +.cmdk-item-content { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 1px; +} + +.cmdk-item-label { + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.cmdk-item-description { + font-size: 0.75rem; + color: var(--muted-foreground); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.cmdk-item-shortcut { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 4px; + margin-left: auto; +} + +.cmdk-item-shortcut kbd { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + height: 20px; + padding: 0 5px; + font-size: 10px; + font-family: inherit; + font-weight: 500; + color: var(--muted-foreground); + background: var(--secondary); + border: 1px solid var(--border); + border-radius: 4px; + line-height: 1; +} + +.cmdk-empty { + display: flex; + align-items: center; + justify-content: center; + height: 64px; + color: var(--muted-foreground); + font-size: 0.875rem; +} + +.cmdk-loading { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px; + color: var(--muted-foreground); + font-size: 0.8rem; +} + +.cmdk-loading-spinner { + width: 14px; + height: 14px; + border: 2px solid var(--border); + border-top-color: var(--foreground); + border-radius: 50%; + animation: cmdk-spin 600ms linear infinite; +} + +@keyframes cmdk-spin { + to { + transform: rotate(360deg); + } +} + +.cmdk-separator { + height: 1px; + background: var(--border); + margin: 4px 8px; +} + +.command-palette-footer { + display: flex; + align-items: center; + gap: 16px; + padding: 8px 16px; + border-top: 1px solid var(--border); + font-size: 0.7rem; + color: var(--muted-foreground); +} + +.command-palette-hint { + display: flex; + align-items: center; + gap: 4px; +} + +.command-palette-hint kbd { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 1px 4px; + font-size: 10px; + font-family: inherit; + font-weight: 500; + color: var(--muted-foreground); + background: var(--secondary); + border: 1px solid var(--border); + border-radius: 4px; +} + +@media (width <= 640px) { + #command-palette-overlay { + padding-top: 0; + align-items: flex-start; + } + + .command-palette { + max-width: 100%; + max-height: 100dvh; + margin: 0; + border-radius: 0; + border: none; + } + + .command-palette-footer { + display: none; + } +} + .video-card .card-image-container { aspect-ratio: 16 / 9 !important; margin-bottom: var(--spacing-sm); diff --git a/test-search.js b/test-search.js new file mode 100644 index 000000000..060129ae5 --- /dev/null +++ b/test-search.js @@ -0,0 +1,8 @@ +import { HiFiClient } from './js/HiFi.ts'; +async function test() { + const client = new HiFiClient(); + const res = await client.query('/search/?q=alskdjfalksjdfld&limit=5'); + const json = await res.json(); + console.log(JSON.stringify(json.data || {})); +} +test(); diff --git a/vite-plugin-auth-gate.js b/vite-plugin-auth-gate.js index a83b58c57..a9e9f0683 100644 --- a/vite-plugin-auth-gate.js +++ b/vite-plugin-auth-gate.js @@ -19,6 +19,33 @@ function parseBody(req) { }); } +function buildInjectionScript(env) { + const AUTH_ENABLED = (env.AUTH_ENABLED ?? 'false') !== 'false'; + const APPWRITE_ENDPOINT = env.APPWRITE_ENDPOINT; + const APPWRITE_PROJECT_ID = env.APPWRITE_PROJECT_ID; + const POCKETBASE_URL = env.POCKETBASE_URL; + const AUTH_GOOGLE_ENABLED = env.AUTH_GOOGLE_ENABLED; + const AUTH_EMAIL_ENABLED = env.AUTH_EMAIL_ENABLED; + + const flags = []; + if (AUTH_ENABLED) flags.push('window.__AUTH_GATE__=true'); + const authProviderOverrides = {}; + if (AUTH_GOOGLE_ENABLED !== undefined) { + authProviderOverrides.google = AUTH_GOOGLE_ENABLED !== 'false'; + } + if (AUTH_EMAIL_ENABLED !== undefined) { + authProviderOverrides.password = AUTH_EMAIL_ENABLED !== 'false'; + } + if (Object.keys(authProviderOverrides).length > 0) { + flags.push(`window.__AUTH_PROVIDERS__=${JSON.stringify(authProviderOverrides)}`); + } + if (APPWRITE_ENDPOINT) flags.push(`window.__APPWRITE_ENDPOINT__=${JSON.stringify(APPWRITE_ENDPOINT)}`); + if (APPWRITE_PROJECT_ID) flags.push(`window.__APPWRITE_PROJECT_ID__=${JSON.stringify(APPWRITE_PROJECT_ID)}`); + if (POCKETBASE_URL) flags.push(`window.__POCKETBASE_URL__=${JSON.stringify(POCKETBASE_URL)}`); + + return flags.length > 0 ? `` : null; +} + export default function authGatePlugin() { let env = {}; @@ -29,33 +56,13 @@ export default function authGatePlugin() { env = loadEnv(mode, process.cwd(), ''); }, + transformIndexHtml(html) { + const scriptTag = buildInjectionScript(env); + return scriptTag ? html.replace('', `${scriptTag}\n`) : html; + }, + configurePreviewServer(server) { - const AUTH_ENABLED = (env.AUTH_ENABLED ?? 'false') !== 'false'; - const APPWRITE_ENDPOINT = env.APPWRITE_ENDPOINT; - const APPWRITE_PROJECT_ID = env.APPWRITE_PROJECT_ID; - const POCKETBASE_URL = env.POCKETBASE_URL; - const AUTH_GOOGLE_ENABLED = env.AUTH_GOOGLE_ENABLED; - const AUTH_EMAIL_ENABLED = env.AUTH_EMAIL_ENABLED; - - // --- Build injection script (always, for both auth gate and env config) --- - - const flags = []; - if (AUTH_ENABLED) flags.push('window.__AUTH_GATE__=true'); - const authProviderOverrides = {}; - if (AUTH_GOOGLE_ENABLED !== undefined) { - authProviderOverrides.google = AUTH_GOOGLE_ENABLED !== 'false'; - } - if (AUTH_EMAIL_ENABLED !== undefined) { - authProviderOverrides.password = AUTH_EMAIL_ENABLED !== 'false'; - } - if (Object.keys(authProviderOverrides).length > 0) { - flags.push(`window.__AUTH_PROVIDERS__=${JSON.stringify(authProviderOverrides)}`); - } - if (APPWRITE_ENDPOINT) flags.push(`window.__APPWRITE_ENDPOINT__=${JSON.stringify(APPWRITE_ENDPOINT)}`); - if (APPWRITE_PROJECT_ID) - flags.push(`window.__APPWRITE_PROJECT_ID__=${JSON.stringify(APPWRITE_PROJECT_ID)}`); - if (POCKETBASE_URL) flags.push(`window.__POCKETBASE_URL__=${JSON.stringify(POCKETBASE_URL)}`); - const configScript = flags.length > 0 ? `` : null; + const configScript = buildInjectionScript(env); // --- Pre-build injected HTML pages --- @@ -69,6 +76,7 @@ export default function authGatePlugin() { } let loginHtml = null; + const AUTH_ENABLED = (env.AUTH_ENABLED ?? 'false') !== 'false'; if (AUTH_ENABLED) { const loginPath = join(distDir, 'login.html'); if (existsSync(loginPath)) { @@ -98,7 +106,7 @@ export default function authGatePlugin() { process.exit(1); } - console.log(`Auth gate enabled (Project: ${APPWRITE_PROJECT_ID})`); + console.log(`Auth gate enabled (Project: ${env.APPWRITE_PROJECT_ID})`); server.middlewares.use( cookieSession({ diff --git a/vite-plugin-blob.ts b/vite-plugin-blob.ts new file mode 100644 index 000000000..069ac5e22 --- /dev/null +++ b/vite-plugin-blob.ts @@ -0,0 +1,126 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { gzipSync, constants as zlibConstants } from 'zlib'; +import type { Plugin } from 'vite'; +import mime from 'mime'; +import { createHash } from 'crypto'; + +function hashString(input: string, algorithm = 'sha256'): string { + return createHash(algorithm) + .update(input, 'utf8') // specify string encoding + .digest('hex'); // return as hex +} + +/** + * Vite plugin enabling `?blob-url` imports. + * + * Example: + * import getBlobUrl from "./file.bin?blob-url"; + * const blobUrl = await getBlobUrl(); + * + * Behavior: + * - Compresses the asset using max gzip compression + * - Build: emits compressed asset + * - Dev: serves compressed asset from middleware + * - Runtime fetches + decompresses it and returns an object URL + */ +export default function blobAssetPlugin(): Plugin { + const devAssets = new Map(); + + return { + name: 'vite-blob-asset', + + async load(id) { + if (!id.includes('?blob-url')) return; + + const [filepath] = id.split('?'); + const absPath = path.resolve(filepath); + + const input = await fs.readFile(absPath); + + /** gzip with maximum compression */ + const compressed = gzipSync(input, { + level: zlibConstants.Z_BEST_COMPRESSION, + }); + + let assetUrl: string; + + if (this.meta.watchMode) { + /** dev server path */ + assetUrl = `/@blob/${hashString(absPath)}/${path.basename(filepath)}.gz`; + devAssets.set(assetUrl, compressed); + } else { + /** build asset */ + const refId = this.emitFile({ + type: 'asset', + name: path.basename(filepath) + '.gz', + source: compressed, + }); + + assetUrl = `__BLOB_ASSET_${refId}__`; + } + + return ` +/** + * Decompress gzip data using browser DecompressionStream + */ +async function decompress(buffer) { + const ds = new DecompressionStream("gzip"); + const stream = new Response(buffer).body.pipeThrough(ds); + return new Response(stream).arrayBuffer(); +} + +let blobPromise = null; + +export default function getBlobUrl() { + if (blobPromise) return blobPromise; + + return blobPromise = (async () => { + try { + const res = await fetch(${JSON.stringify(assetUrl)}); + const compressed = await res.arrayBuffer(); + + const decompressed = await decompress(compressed); + + const blob = new Blob([decompressed], ${JSON.stringify({ + type: mime.getType(filepath), + })}); + return URL.createObjectURL(blob); + } catch (err) { + console.error("Error loading blob asset:", err); + blobPromise = null; + throw err; + } + })() +} +`; + }, + + resolveFileUrl({ referenceId }) { + return `"${this.getFileName(referenceId)}"`; + }, + + generateBundle(_, bundle) { + for (const chunk of Object.values(bundle)) { + if (chunk.type !== 'chunk') continue; + + chunk.code = chunk.code.replace( + /"__BLOB_ASSET_(.*?)__"/g, + (_, refId) => `"${this.getFileName(refId)}"` + ); + } + }, + + configureServer(server) { + server.middlewares.use((req, res, next) => { + if (!req.url?.startsWith('/@blob/')) return next(); + + const data = devAssets.get(req.url); + if (!data) return next(); + + res.setHeader('Content-Type', 'application/gzip'); + res.end(data); + }); + }, + }; +} diff --git a/vite-plugin-svg-use.ts b/vite-plugin-svg-use.ts new file mode 100644 index 000000000..edbfc69ac --- /dev/null +++ b/vite-plugin-svg-use.ts @@ -0,0 +1,234 @@ +import { normalizePath, Plugin } from 'vite'; +import path from 'path'; +import fs from 'fs'; +import { optimize } from 'svgo'; + +const virtualModuleId = 'svg-merge-attributes'; + +/** + * Regex for matching attributes inside a tag + */ +const ATTR_REGEX = /([a-z0-9_-]+)="([^"]*)"/gim; + +/** + * Regex for matching + */ +const SVG_USE_REGEX = /]*?)svg="([^"]+\.svg)"([^>]*)\/?>/gim; + +/** + * Parse attribute string to object + */ +function parseAttrs(str: string): Record { + const out: Record = {}; + for (const [, name, value] of str.matchAll(ATTR_REGEX)) { + out[name] = value; + } + return out; +} + +/** + * Merge attributes into root + */ +function mergeSvgAttributes(svg: string, attrs: Record) { + return svg.replace(/]*)>/i, (match, existingAttrs) => { + // Size is shorthand for setting both width and height to the same value + if (attrs['size']) { + attrs['width'] = attrs['size']; + attrs['height'] = attrs['size']; + delete attrs['size']; + } + + const map = new Map(); + + for (const [, name, value] of existingAttrs.matchAll(ATTR_REGEX)) { + map.set(name, value); + } + + for (const [k, v] of Object.entries(attrs)) { + // optional: merge class and style + if (k === 'class' && map.has('class')) { + map.set('class', map.get('class') + ' ' + v); + } else if (k === 'style' && map.has('style')) { + map.set('style', map.get('style') + ';' + v); + } else { + map.set(k, v); + } + } + + const merged = [...map.entries()].map(([k, v]) => `${k}="${v}"`).join(' '); + return ``; + }); +} + +function getResizer(base: string, params: string) { + const cache: Record = {}; + + return function getIcon(size: number, attrs: Record = {}) { + const attributes = { + ...getParams(params), + ...attrs, + height: size.toString(), + width: size.toString(), + }; + return (cache[JSON.stringify(attributes)] ??= mergeSvgAttributes(base, attributes)); + }; +} + +function getParams(str: string): Record { + return Object.fromEntries(new URLSearchParams(str).entries()); +} + +/** + * Load SVG content from disk + */ +function loadSvg>( + filePath: string, + sync: S = true as S +): T { + if (sync) { + return fs.readFileSync(filePath, 'utf-8') as T; + } + + return new Promise((resolve, reject) => { + fs.readFile(filePath, { encoding: 'utf-8' }, (err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + }) as T; +} + +/** + * Main plugin + */ +export default function viteSvgUsePlugin(): Plugin { + let config: any; + const watched = new Set(); + + /** + * Resolve path + */ + function resolveSvg(root: string, importer: string, src: string) { + // Handle Vite aliases + if (src.startsWith('.')) { + return normalizePath(path.resolve(path.dirname(importer), src)); + } + // Check for alias + if (config && config.resolve && config.resolve.alias) { + for (const [_, { find, replacement }] of Object.entries<{ find: string; replacement: string }>( + config.resolve.alias + )) { + if (src.startsWith(find)) { + // Remove alias prefix and resolve + const aliasedPath = src.replace(find, replacement); + return normalizePath(path.resolve(root, aliasedPath.replace(/^\//, ''))); + } + } + } + return normalizePath(path.resolve(root, src.replace(/^\//, ''))); + } + + return { + name: 'vite-svg-use-plugin', + enforce: 'pre', + + configResolved(resolvedConfig) { + config = resolvedConfig; + }, + + /** + * HTML transform + */ + transformIndexHtml: { + order: 'pre', + async handler(html, ctx) { + return html.replace(SVG_USE_REGEX, (full, before, src, after) => { + const attrs = { + ...parseAttrs(before || ''), + ...parseAttrs(after || ''), + }; + + delete attrs['use']; + + const filePath = resolveSvg(config.root, ctx.filename || '', src); + + watched.add(filePath); + + let svg = loadSvg(filePath); + svg = mergeSvgAttributes(optimize(svg).data, attrs); + + return svg; + }); + }, + }, + + /** Resolve virtual modules */ + resolveId(id) { + if (id == virtualModuleId) { + return id; + } + + return null; + }, + + /** Load virtual modules */ + async load(id) { + if (id === virtualModuleId) { + return [ + `const ATTR_REGEX = ${ATTR_REGEX};`, + `export ${getParams.toString()}`, + `export ${mergeSvgAttributes.toString()}`, + `export ${getResizer.toString()}`, + ].join('\n'); + } + + if (id.includes('?svg')) { + const [file, queryString] = id.split('?'); + const params = new URLSearchParams(queryString); + const absPath = path.resolve(file); + + // Derived module: import base and merge attributes + params.delete('svg'); + + if (params.size === 0) { + // No attributes to merge, just return raw content + watched.add(absPath); + + // Read and return the SVG content directly as a string export + const svgContent = optimize(await loadSvg(absPath, false)).data; + return `export default ${JSON.stringify(svgContent)};`; + } + + const baseImport = file + '?svg'; + + if (params.has('icon')) { + params.delete('icon'); + return [ + `import base from ${JSON.stringify(baseImport)};`, + `import { getResizer } from ${JSON.stringify(virtualModuleId)};`, + `export default getResizer(base, ${JSON.stringify(params.toString())});`, + ].join('\n'); + } + + return [ + `import base from ${JSON.stringify(baseImport)};`, + `import { getParams, mergeSvgAttributes } from ${JSON.stringify(virtualModuleId)};`, + `export default mergeSvgAttributes(base, getParams(${JSON.stringify(params.toString())}));`, + ].join('\n'); + } + }, + + /** + * HMR support + */ + handleHotUpdate({ file, server }) { + if (watched.has(normalizePath(file))) { + server.ws.send({ + type: 'full-reload', + }); + } + }, + }; +} diff --git a/vite.config.js b/vite.config.ts similarity index 79% rename from vite.config.js rename to vite.config.ts index c5669d3b6..6d7f8c2fc 100644 --- a/vite.config.js +++ b/vite.config.ts @@ -3,17 +3,36 @@ import { VitePWA } from 'vite-plugin-pwa'; import authGatePlugin from './vite-plugin-auth-gate.js'; import path from 'path'; import uploadPlugin from './vite-plugin-upload.js'; +import blobAssetPlugin from './vite-plugin-blob.js'; +import svgUse from './vite-plugin-svg-use.js'; +import { execSync } from 'child_process'; + +function getGitCommitHash() { + try { + return execSync('git rev-parse --short HEAD').toString().trim(); + } catch { + return 'unknown'; + } +} export default defineConfig(() => { return { base: './', + define: { + __COMMIT_HASH__: JSON.stringify(commitHash), + }, worker: { format: 'es', }, resolve: { alias: { + '!lucide': '/node_modules/lucide-static/icons', + '!simpleicons': '/node_modules/simple-icons/icons', '!': '/node_modules', + + events: '/node_modules/events/events.js', pocketbase: '/node_modules/pocketbase/dist/pocketbase.es.js', + stream: path.resolve(__dirname, 'stream-stub.js'), // Stub for stream module }, }, optimizeDeps: { @@ -33,10 +52,13 @@ export default defineConfig(() => { build: { outDir: 'dist', emptyOutDir: true, + sourcemap: true, }, plugins: [ authGatePlugin(), uploadPlugin(), + blobAssetPlugin(), + svgUse(), VitePWA({ registerType: 'prompt', workbox: {